mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2025-12-08 17:12:28 +08:00
Compare commits
147 Commits
v3.6.0
...
v3.6.3last
| Author | SHA1 | Date | |
|---|---|---|---|
| 857fb53fa1 | |||
| 9db6c1a7ac | |||
| fd0461644e | |||
| 10263720d4 | |||
| 7548f3aa60 | |||
| ad3d2eb3fc | |||
| d0406fcd83 | |||
| 9159b55096 | |||
| faebdee755 | |||
| 2fc672dfab | |||
| 4dc4e87900 | |||
| 13d00a8bb4 | |||
| fb95cf7f2f | |||
| 78f048fda5 | |||
| 200adb8490 | |||
| f1496b5084 | |||
| 7b06715bff | |||
| 3091d5b6f0 | |||
| c117abb2d4 | |||
| dbc3f13c65 | |||
| ea6927a2a7 | |||
| b69a716b04 | |||
| 7e71fa26d7 | |||
| 4fed40ff7d | |||
| ee4ff35c90 | |||
| c9b92decaf | |||
| eed3bc346d | |||
| 6edef14f07 | |||
| ab49983759 | |||
| 5a09a6fb4a | |||
| ac93bf7d6b | |||
| c9c6dd5c1d | |||
| e3e1cd6b0d | |||
| f3cf90bd28 | |||
| 70847d17f1 | |||
| 2cfc39b23f | |||
| c8676b3040 | |||
| 73bd04d04a | |||
| 0ca4badb77 | |||
| 80b92ca132 | |||
| 58865bef28 | |||
| 9fd40d0973 | |||
| 266ebd9122 | |||
| fee729e16c | |||
| 10a3e9c6ba | |||
| 990f79fdfe | |||
| 6360aee0ff | |||
| 685b81e5ec | |||
| e38e395436 | |||
| 39af6e25ee | |||
| b15e6e0422 | |||
| 8f99a80352 | |||
| 936a87e738 | |||
| 2af165b201 | |||
| 3d5efc07ad | |||
| 21e8d640d2 | |||
| b0ce456909 | |||
| b8e1306955 | |||
| 37a38ad288 | |||
| 9ee05c9510 | |||
| 275a68bb6a | |||
| f3f70e8549 | |||
| e15e9d80c4 | |||
| f7538c1ed8 | |||
| a9dba08a8d | |||
| acf0713385 | |||
| cee872000a | |||
| 4a857680d0 | |||
| a47d0984dc | |||
| e333b126b6 | |||
| 3618842f44 | |||
| fd8c848c9e | |||
| 09614a0239 | |||
| 6fe8f1d81a | |||
| 0bd7f715c4 | |||
| 041d88161e | |||
| 79a62aa056 | |||
| b86b4d9676 | |||
| aeaac80012 | |||
| e0ef20cf08 | |||
| 169a66f5dd | |||
| 7e39b31123 | |||
| 18765450a6 | |||
| dff8c84d9c | |||
| d962c34846 | |||
| cd9794d818 | |||
| 5034b7cf18 | |||
| fdde84c68a | |||
| 4c54ff6f52 | |||
| de3285dc1b | |||
| 7f0c035c4c | |||
| 43593e8def | |||
| 48b0b608d8 | |||
| 69287a772b | |||
| 337d5a9489 | |||
| cfeb81ee1e | |||
| 09f92f01aa | |||
| 6d1094936b | |||
| 8836a2793a | |||
| c36ece8923 | |||
| a82213b90c | |||
| 98facdd2ee | |||
| d080b0b5ea | |||
| 338902ca0c | |||
| 7ae6a11cf0 | |||
| cdbe1cb1a9 | |||
| 232037ec58 | |||
| b18c1120ab | |||
| f6a7831963 | |||
| 08a4473bbc | |||
| 9008ddafa4 | |||
| 7012ed4c2c | |||
| 1d8c8c30d0 | |||
| 090f790df4 | |||
| 82d051f388 | |||
| 5a3631c332 | |||
| c00b5526c3 | |||
| 2e35abd3a3 | |||
| 9bc3f6c56e | |||
| 5588912b62 | |||
| 37cf913d6d | |||
| 94ba767090 | |||
| a406c7cd81 | |||
| 480878a3db | |||
| a85499119d | |||
| 4cbe9cad8e | |||
| 2dfc06c679 | |||
| a591ad9fed | |||
| 5420e69b59 | |||
| f157c96f65 | |||
| 9588ace87f | |||
| cc57ac379b | |||
| 074920552a | |||
| 2a00a24058 | |||
| 06cc4ec0fe | |||
| decea393a5 | |||
| 65b0fab80d | |||
| 1d4098ae14 | |||
| 5c4f303a0d | |||
| 8dcc5bdf8a | |||
| b3e4a73a34 | |||
| 60b4a038f6 | |||
| 4e3738100a | |||
| 8216889078 | |||
| 6ab4ee6a91 | |||
| a8dde73a8c | |||
| b2b11611c1 |
7
.github/ISSUE_TEMPLATE.md
vendored
7
.github/ISSUE_TEMPLATE.md
vendored
@ -1,8 +1,9 @@
|
||||
##### 版本号:
|
||||
|
||||
##### 分支: master?还是springboot3?
|
||||
|
||||
##### 前端版本:vue3版?还是 vue2版?
|
||||
|
||||
##### 前端版本: vue3版?还是 vue2版?
|
||||
|
||||
##### 问题描述:
|
||||
|
||||
@ -13,9 +14,9 @@
|
||||
|
||||
|
||||
#### 友情提示(为了提高issue处理效率):
|
||||
- 未按格式要求发帖,会被直接删掉;
|
||||
- 描述过于简单或模糊,导致无法处理的,会被直接删掉;
|
||||
- 未按格式要求发帖、描述过于简抽象的,会被直接删掉;
|
||||
- 请自己初判问题描述是否清楚,是否方便我们调查处理;
|
||||
- 针对问题请说明是Online在线功能(需说明用的主题模板),还是生成的代码功能;
|
||||
- springboot3_sas分支采用 `Spring Authorization Server` 替换 `Shiro`,目前是beta版不稳定,生产项目不要使用;
|
||||
|
||||
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@ -9,4 +9,7 @@ rebel.xml
|
||||
|
||||
## front
|
||||
**/*.lock
|
||||
os_del.cmd
|
||||
os_del.cmd
|
||||
os_del_doc.cmd
|
||||
.svn
|
||||
derby.log
|
||||
|
||||
20
README-EN.md
20
README-EN.md
@ -7,13 +7,13 @@
|
||||
JEECG BOOT Low Code Development Platform
|
||||
===============
|
||||
|
||||
当前最新版本: 3.6.0(发布日期:2023-10-23)
|
||||
当前最新版本: 3.6.3(发布日期:2024-03-11)
|
||||
|
||||
|
||||
[](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)
|
||||
|
||||
@ -58,13 +58,12 @@ Download the source code
|
||||
| `jeecg-boot` | SpringBoot background source code (support microservices) |
|
||||
| `jeecgboot-vue3` | Vue3+TS new front-end source code|
|
||||
| `jeecg-uniapp` | [APP development framework, a code multi terminal adaptation, and support APP, small program, H5](https://github.com/jeecgboot/jeecg-uniapp) |
|
||||
| `jeecg-boot-starter` | [Stater relies on the project to be maintained separately. Click Download](https://gitee.com/jeecg/jeecg-boot-starter) |
|
||||
| `SpringBoot3+JDK17` | [BranchSourceCode](https://github.com/jeecgboot/jeecg-boot/tree/springboot3) [UpgradeBlog](https://blog.csdn.net/zhangdaiscott/article/details/134805602) |
|
||||
| `More` | [Download more source code](http://jeecg.com/download) |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
For the project
|
||||
-----------------------------------
|
||||
Jeecg-Boot low code development platform can be applied in the development of any J2EE project, especially for SAAS projects, enterprise information management system (MIS), internal office system (OA), enterprise resource planning system (ERP), customer relationship management system (CRM), etc. Its semi-intelligent manual Merge development method, Can significantly improve the development efficiency of more than 70%, greatly reduce the development cost.
|
||||
@ -77,7 +76,7 @@ Docker starts the project
|
||||
- [Docker starts the monomer background](https://help.jeecg.com/java/setup/docker/up.html)
|
||||
- [Docker starts the Vue3 front-end](http://help.jeecg.com/publish/docker.html)
|
||||
- [Docker starts the micro-service background](https://help.jeecg.com/java/springcloud/docker.html)
|
||||
|
||||
- [ChatGPT AI Config](https://help.jeecg.com/java/chatgpt.html)
|
||||
|
||||
|
||||
|
||||
@ -88,12 +87,17 @@ Technical documentation
|
||||
- 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 : ⑦791696430、⑥730954414、683903138、⑤860162132(full)、④774126647(full)、③816531124(full)、②769925425(full)、①284271917(full)
|
||||
- QQ group : ⑨808791225、⑧825232878、⑦791696430、⑥730954414(full)、683903138(full)、⑤860162132(full)、④774126647(full)、③816531124(full)、②769925425(full)、①284271917(full)
|
||||
- Demo : [Vue3](http://boot3.jeecg.com) | [Vue2](http://boot.jeecg.com) | [APP](http://jeecg.com/appIndex)
|
||||
> [please click obtain account password to obtain](http://jeecg.com/doc/demo)
|
||||
|
||||
|
||||
|
||||
Thinking
|
||||
-----------------------------------
|
||||
> We are pursuing the goal of implementing complex business systems without writing code! That has been done so far
|
||||
- https://www.qiaoqiaoyun.com
|
||||
|
||||
|
||||
Star charts
|
||||
-----------------------------------
|
||||
@ -437,6 +441,10 @@ Technical Architecture:
|
||||
|
||||
### Effect of system
|
||||
|
||||
##### ChatGPT AI Dialog
|
||||
> Go to the JeecgBoot background home page and click "AI Assistant" in the middle of the right side of the home page. The AI Assistant dialog screen is displayed.
|
||||

|
||||
|
||||
|
||||
##### PC
|
||||

|
||||
|
||||
36
README.md
36
README.md
@ -7,13 +7,13 @@
|
||||
JEECG BOOT 低代码开发平台
|
||||
===============
|
||||
|
||||
当前最新版本: 3.6.0(发布日期:2023-10-23)
|
||||
当前最新版本: 3.6.3(发布日期:2024-03-11)
|
||||
|
||||
|
||||
[](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/zhangdaiscott/jeecg-boot)
|
||||
|
||||
@ -49,16 +49,17 @@ Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中,
|
||||
| Github | [jeecgboot-vue3](https://github.com/jeecgboot/jeecgboot-vue3) | [jeecg-boot](https://github.com/jeecgboot/jeecg-boot) |
|
||||
| 码云 | [jeecgboot-vue3](https://gitee.com/jeecg/jeecgboot-vue3) | [jeecg-boot](https://gitee.com/jeecg/jeecg-boot) |
|
||||
|
||||
> 官方已推出 `SpringBoot3+JDK17版本` [分支源码下载](https://github.com/jeecgboot/jeecg-boot/tree/springboot3) | [升级SpringBoot3博客](https://blog.csdn.net/zhangdaiscott/article/details/134805602)
|
||||
|
||||
#### 项目说明
|
||||
|
||||
| 项目名 | 说明 |
|
||||
|--------------------|------------------------|
|
||||
| `jeecg-boot` | JAVA后台源码(支持微服务) |
|
||||
| `jeecgboot-vue3` | 前端源码 (Vue3版本) |
|
||||
| `jeecg-boot` | 后端JAVA源码(支持微服务) |
|
||||
| `jeecg-uniapp` | [APP开发框架,一份代码多终端适配,同时支持APP、小程序、H5](https://github.com/jeecgboot/jeecg-uniapp) |
|
||||
| `jeecg-boot-starter` | [Stater依赖项目单独维护,点击下载](https://gitee.com/jeecg/jeecg-boot-starter) |
|
||||
| `更多开源项目` | [更多源码下载](http://jeecg.com/download) |
|
||||
| `更多开源项目` | [更多底层源码下载](http://jeecg.com/download) |
|
||||
|
||||
|
||||
|
||||
快速搭建开发环境
|
||||
@ -68,7 +69,7 @@ Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中,
|
||||
- [通过IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup.html)
|
||||
- [Vue3前端项目快速启动](http://help.jeecg.com/setup/startup.html)
|
||||
- [单体快速切换为微服务版](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
|
||||
|
||||
- [ChatGPT AI助手配置文档](https://help.jeecg.com/java/chatgpt.html)
|
||||
|
||||
Docker快速启动项目
|
||||
-----------------------------------
|
||||
@ -82,16 +83,22 @@ Docker快速启动项目
|
||||
-----------------------------------
|
||||
|
||||
- 项目官网: [http://www.jeecg.com](http://www.jeecg.com)
|
||||
- 开发文档: [http://help.jeecg.com](http://help.jeecg.com)
|
||||
- 开发文档: [https://help.jeecg.com](https://help.jeecg.com)
|
||||
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | [常见问题 ](http://www.jeecg.com/doc/qa) | [视频教程](https://space.bilibili.com/454617261/channel/series) | [1分钟低代码体验](https://my.oschina.net/jeecg/blog/3083313)
|
||||
|
||||
- 在线演示 : [Vue3演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex) | [敲敲云零代码](https://qiaoqiaoyun.com)
|
||||
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取
|
||||
>
|
||||
- QQ交流群 : ⑦791696430、⑥730954414、VUE3群683903138、⑤860162132(满)、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
|
||||
- QQ交流群 : ⑨808791225、⑧825232878、⑦791696430(满)、⑥730954414(满)、683903138(满)、⑤860162132(满)、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
|
||||
> ` 提醒:【QQ群是自助服务群,建议给帮助您解决问题的同学发送指定红包,表示感谢!】 `
|
||||
|
||||
|
||||
大龄码农的思考
|
||||
-----------------------------------
|
||||
> 作为码农年纪大了写不动代码了怎么办??哎!!
|
||||
所以我们团队在追求不写代码也可实现复杂业务系统!目前已经做到了,不信你到敲敲云零代码试试(通过流程串联修改业务数据)
|
||||
|
||||
- https://www.qiaoqiaoyun.com
|
||||
|
||||
|
||||
技术支持
|
||||
@ -104,8 +111,6 @@ Docker快速启动项目
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
VUE2版本专题介绍
|
||||
-----------------------------------
|
||||
#### 项目介绍
|
||||
@ -191,8 +196,8 @@ Star走势图
|
||||
* 17.支持SAAS服务模式,提供SaaS多租户架构方案。
|
||||
* 18.分布式文件服务,集成minio、阿里OSS等优秀的第三方,提供便捷的文件上传与管理,同时也支持本地存储。
|
||||
* 19.主流数据库兼容,一套代码完全兼容Mysql、Postgresql、Oracle、Sqlserver、MariaDB、达梦等主流数据库。
|
||||
* 20.集成工作流activiti、flowable,并实现了只需在页面配置流程转向,可极大的简化bpm工作流的开发;用bpm的流程设计器画出了流程走向,一个工作流基本就完成了,只需写很少量的java代码;
|
||||
* 21.低代码能力:在线流程设计,采用开源Activiti流程引擎,实现在线画流程,自定义表单,表单挂靠,业务流转
|
||||
* 20.集成工作流flowable、activiti,并实现了只需在页面配置流程转向,可极大的简化bpm工作流的开发;用bpm的流程设计器画出了流程走向,一个工作流基本就完成了,只需写很少量的java代码;
|
||||
* 21.低代码能力:在线流程设计,采用开源flowable、activiti流程引擎,实现在线画流程,自定义表单,表单挂靠,业务流转
|
||||
* 22.多数据源:及其简易的使用方式,在线配置数据源配置,便捷的从其他数据抓取数据;
|
||||
* 23.提供单点登录CAS集成方案,项目中已经提供完善的对接代码
|
||||
* 24.低代码能力:表单设计器,支持用户自定义表单布局,支持单表,一对多表单、支持select、radio、checkbox、textarea、date、popup、列表、宏等控件
|
||||
@ -462,13 +467,20 @@ Star走势图
|
||||
|
||||
```
|
||||
|
||||
### 流程引擎推荐
|
||||
|
||||
JeecgBoot企业版本默认集成了activiti和flowable两套方案,大家在使用本开源项目时,如果想进一步集成流程引擎,推荐结合贺波老师的书 [《深入Activiti流程引擎:核心原理与高阶实战》](https://item.m.jd.com/product/13928958.html?gx=RnAomTM2bmCImZxDqYAkVCoIHuIYVqc)
|
||||
|
||||
<img src="https://jeecgos.oss-cn-beijing.aliyuncs.com/files/tuijian20231220161656.png" width="25%" height="auto">
|
||||
|
||||
|
||||
### 系统效果
|
||||
|
||||
|
||||
##### ChatGPT AI交互
|
||||
> 进入JeecgBoot后台首页,点击首页右侧中间“AI助手”,弹出AI助手对话界面。
|
||||

|
||||
|
||||
|
||||
##### PC端
|
||||

|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,155 +0,0 @@
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- 新增用户职位表关系表
|
||||
CREATE TABLE sys_user_position (
|
||||
id varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
|
||||
user_id varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户id',
|
||||
position_id varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '职位id',
|
||||
create_by varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人',
|
||||
create_time datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
|
||||
update_by varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人',
|
||||
update_time datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
|
||||
PRIMARY KEY (id) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
ALTER TABLE sys_user_position
|
||||
ADD INDEX idx_sup_user_id(user_id) USING BTREE,
|
||||
ADD INDEX idx_sup_position_id(position_id) USING BTREE,
|
||||
ADD INDEX idx_sup_user_position_id(user_id, position_id) USING BTREE;
|
||||
|
||||
-- 删除用户表的职位
|
||||
ALTER TABLE sys_user DROP COLUMN post;
|
||||
|
||||
|
||||
|
||||
-- 用户租户关系表修改索引
|
||||
ALTER TABLE `sys_user_tenant`
|
||||
DROP INDEX `uniq_sut_user_rel_tenant`,
|
||||
ADD INDEX `idx_sut_user_rel_tenant`(`user_id`, `tenant_id`) USING BTREE;
|
||||
|
||||
ALTER TABLE `sys_user_depart`
|
||||
DROP INDEX `idx_sud_user_dep_id`,
|
||||
ADD UNIQUE INDEX `idx_sud_user_dep_id`(`user_id`, `dep_id`) USING BTREE;
|
||||
|
||||
|
||||
-- 新增企业微信和钉钉配置表,通过租户模式隔离
|
||||
CREATE TABLE sys_third_app_config (
|
||||
id varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
tenant_id int(10) NOT NULL DEFAULT 0 COMMENT '租户id',
|
||||
agent_id varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '钉钉/企业微信应用id',
|
||||
client_id varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '钉钉/企业微信 应用id',
|
||||
client_secret varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '钉钉/企业微信应用id对应的秘钥',
|
||||
third_type varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '第三方类别(dingtalk 钉钉 wechat_enterprise 企业微信)',
|
||||
agent_app_secret varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '自建应用Secret',
|
||||
status int(1) NULL DEFAULT 1 COMMENT '是否启用(0-否,1-是)',
|
||||
create_time datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
|
||||
update_time datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (id) USING BTREE,
|
||||
UNIQUE INDEX uniq_stac_third_type_tenant_id(tenant_id, third_type) USING BTREE,
|
||||
INDEX idx_stac_tenant_id(tenant_id) USING BTREE,
|
||||
INDEX idx_stac_third_type(third_type) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '租户第三方配置表' ROW_FORMAT = Dynamic;
|
||||
|
||||
ALTER TABLE sys_third_account
|
||||
ADD UNIQUE INDEX uniq_sta_user_id_third_type(sys_user_id, third_type) USING BTREE,
|
||||
ADD UNIQUE INDEX uniq_sta_third_user_id_third_type(third_user_id, third_type) USING BTREE,
|
||||
ADD UNIQUE INDEX uniq_sta_third_user_uuid_third_type(third_user_uuid, third_type) USING BTREE;
|
||||
|
||||
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1629109281748291586', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '第三方配置', '/third/app', 'system/appconfig/ThirdAppConfigList', 1, '', NULL, 1, NULL, '0', 13.00, 0, 'ant-design:setting-outlined', 1, 0, 0, 0, NULL, 'admin', '2023-02-24 21:21:35', 'admin', '2023-02-24 21:51:05', 0, 0, NULL, 0);
|
||||
|
||||
ALTER TABLE sys_third_account
|
||||
ADD COLUMN tenant_id int(10) NULL DEFAULT 0 COMMENT '租户id' AFTER realname;
|
||||
update sys_third_account set tenant_id = 0;
|
||||
|
||||
ALTER TABLE sys_third_account
|
||||
DROP INDEX uniq_sta_third_user_id_third_type,
|
||||
DROP INDEX uniq_sta_third_user_uuid_third_type,
|
||||
DROP INDEX uniq_sta_user_id_third_type,
|
||||
ADD UNIQUE INDEX uniq_sta_third_user_id_third_type(third_user_id, third_type, tenant_id) USING BTREE,
|
||||
ADD UNIQUE INDEX uniq_sta_third_user_uuid_third_type(third_user_uuid, third_type, tenant_id) USING BTREE;
|
||||
|
||||
ALTER TABLE `sys_third_app_config`
|
||||
DROP INDEX `uniq_stac_third_type_tenant_id`;
|
||||
|
||||
|
||||
-- 新增租户默认产品包
|
||||
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1674708136602542082', '', '我的租户', '/mytenant', 'layouts/RouteView', 1, '', NULL, 0, NULL, '0', 4.20, 0, 'ant-design:user-outlined', 0, 0, 0, 0, NULL, 'admin', '2023-06-30 17:15:09', 'admin', '2023-06-30 18:35:40', 0, 0, NULL, 0);
|
||||
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1663816667704500225', '1674708136602542082', '我的租户', '/tenant/MyTenantList', 'system/tenant/MyTenantList', 1, '', NULL, 1, NULL, '0', 1.00, 0, 'ant-design:user-outlined', 1, 0, 0, 0, NULL, 'admin', '2023-05-31 15:56:20', 'admin', '2023-06-30 18:37:26', 0, 0, NULL, 0);
|
||||
UPDATE sys_permission SET parent_id = '1674708136602542082' WHERE component = 'system/user/TenantUserList';
|
||||
UPDATE sys_permission SET parent_id = '1674708136602542082' WHERE component = 'system/role/TenantRoleList';
|
||||
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1661572802889007106', '', '租户管理', '/tenant/setting', 'layouts/RouteView', 1, NULL, NULL, 0, NULL, '1', 4.10, 0, 'ant-design:setting-outlined', 0, 0, 0, 0, NULL, 'admin', '2023-05-25 11:20:01', 'admin', '2023-06-30 18:37:04', 0, 0, '1', 0);
|
||||
UPDATE sys_permission SET parent_id = '1661572802889007106' WHERE component = 'system/tenant/index';
|
||||
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1668174661456171010', '1661572802889007106', '租户默认套餐', '/tenant/TenantDefaultPack', 'system/tenant/TenantDefaultPackList', 1, '', NULL, 1, NULL, '0', 5.00, 0, 'ant-design:folder-filled', 1, 0, 0, 0, NULL, 'admin', '2023-06-12 16:33:27', 'admin', '2023-06-30 19:09:24', 0, 0, NULL, 0);
|
||||
ALTER TABLE sys_tenant_pack
|
||||
ADD COLUMN pack_type varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'custom' COMMENT '产品包类型(default 默认产品包 custom 自定义产品包)' AFTER pack_code;
|
||||
update sys_tenant_pack set pack_type = 'custom';
|
||||
|
||||
ALTER TABLE sys_user_tenant
|
||||
MODIFY COLUMN status varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '状态(1 正常 2 离职 3 待审核 4 拒绝 5 邀请加入)' AFTER tenant_id;
|
||||
|
||||
UPDATE sys_permission SET component = 'system/tenant/my/MyTenantList' WHERE component = 'system/tenant/MyTenantList';
|
||||
UPDATE sys_permission SET component = 'system/tenant/pack/TenantDefaultPackList' WHERE component = 'system/tenant/TenantDefaultPackList';
|
||||
UPDATE sys_permission SET component = 'system/tenant/TenantUserList', url='/system/tenant/TenantUserList' WHERE component = 'system/user/TenantUserList';
|
||||
|
||||
|
||||
-- 系统通知类型新增租户邀请
|
||||
ALTER TABLE sys_announcement
|
||||
MODIFY COLUMN bus_type varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '业务类型(email:邮件 bpm:流程 tenant_invite:租户邀请)' AFTER del_flag;
|
||||
|
||||
|
||||
-- 修改部门表org_category字段的注释
|
||||
ALTER TABLE `sys_depart`
|
||||
MODIFY COLUMN `org_category` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '1' COMMENT '机构类别 1公司,2组织机构,3岗位' AFTER `description`;
|
||||
|
||||
|
||||
-- 日志显示实际名称 ---
|
||||
ALTER TABLE `sys_data_log`
|
||||
ADD COLUMN `create_name` varchar(100) NULL COMMENT '创建人真实名称' AFTER `create_by`;
|
||||
|
||||
UPDATE sys_data_log
|
||||
SET create_name = (SELECT sys_user.realname FROM sys_user WHERE sys_user.username = sys_data_log.create_by)
|
||||
WHERE create_name = '' OR create_name IS NULL;
|
||||
|
||||
|
||||
-- 新增表字典白名单配置表
|
||||
CREATE TABLE `sys_table_white_list` (
|
||||
`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键id',
|
||||
`table_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '允许的表名',
|
||||
`field_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '允许的字段名,多个用逗号分割',
|
||||
`status` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '1' COMMENT '状态,1=启用,0=禁用',
|
||||
`create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
|
||||
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
|
||||
`update_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',
|
||||
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uniq_sys_table_white_list_table_name`(`table_name`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典表白名单' ROW_FORMAT = DYNAMIC;
|
||||
-- 默认数据
|
||||
INSERT INTO `sys_table_white_list` (`id`, `table_name`, `field_name`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1701578033271521282', 'sys_user', 'id,realname,username', '1', 'admin', '2023-09-12 10:46:32', NULL, NULL);
|
||||
INSERT INTO `sys_table_white_list` (`id`, `table_name`, `field_name`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1701581935488385025', 'oa_officialdoc_organcode', 'id,organ_name', '1', 'admin', '2023-09-12 11:02:02', NULL, NULL);
|
||||
INSERT INTO `sys_table_white_list` (`id`, `table_name`, `field_name`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1701581977733414913', 'demo', 'id,name', '1', 'admin', '2023-09-12 11:02:12', NULL, NULL);
|
||||
INSERT INTO `sys_table_white_list` (`id`, `table_name`, `field_name`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1701582035472203777', 'sys_permission', 'id,name', '1', 'admin', '2023-09-12 11:02:26', NULL, NULL);
|
||||
INSERT INTO `sys_table_white_list` (`id`, `table_name`, `field_name`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1701582087619985409', 'onl_drag_comp', 'id,comp_name', '1', 'admin', '2023-09-12 11:02:38', NULL, NULL);
|
||||
INSERT INTO `sys_table_white_list` (`id`, `table_name`, `field_name`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1701582136420712450', 'sys_depart', 'id,depart_name', '1', 'admin', '2023-09-12 11:02:50', NULL, NULL);
|
||||
INSERT INTO `sys_table_white_list` (`id`, `table_name`, `field_name`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1701582163599802370', 'design_form', 'id,desform_name,desform_code', '1', 'admin', '2023-09-12 11:02:56', NULL, NULL);
|
||||
INSERT INTO `sys_table_white_list` (`id`, `table_name`, `field_name`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1701582190187495426', 'onl_cgform_head', 'table_txt,table_name', '1', 'admin', '2023-09-12 11:03:03', NULL, NULL);
|
||||
INSERT INTO `sys_table_white_list` (`id`, `table_name`, `field_name`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1701582254301626370', 'oa_wps_file', 'id,name', '1', 'admin', '2023-09-12 11:03:18', NULL, NULL);
|
||||
|
||||
INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1701575168519839746', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '字典表白名单', '/system/tableWhiteList', 'system/tableWhiteList/SysTableWhiteListList', 1, '', NULL, 1, NULL, '0', 13.00, 0, 'ant-design:table-outlined', 1, 0, 0, 0, NULL, 'admin', '2023-09-12 20:35:09', 'admin', '2023-09-12 20:45:08', 0, 0, NULL, 0);
|
||||
|
||||
|
||||
-- 系统通知卡顿问题性能优化 ---
|
||||
ALTER TABLE `sys_announcement_send`
|
||||
MODIFY COLUMN `read_flag` int(2) NULL DEFAULT NULL COMMENT '阅读状态(0未读,1已读)' AFTER `user_id`;
|
||||
|
||||
ALTER TABLE `sys_announcement`
|
||||
MODIFY COLUMN `msg_abstract` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '摘要/扩展业务参数' AFTER `user_ids`;
|
||||
|
||||
|
||||
-- 字典表 加颜色配置---
|
||||
ALTER TABLE sys_dict_item
|
||||
ADD COLUMN item_color varchar(10) NULL COMMENT '字典项颜色' AFTER item_value;
|
||||
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@ -1,11 +0,0 @@
|
||||
版本升级方法?
|
||||
|
||||
JeecgBoot属于平台级产品,每次升级改动内容较多,目前做不到平滑升级。
|
||||
|
||||
升级方案建议:
|
||||
1.代码升级 => 本地版本通过svn或者git做好主干,在分支上做业务开发,jeecg每次版本发布,可以手工覆盖主干的代码,对比合并代码;
|
||||
2.数据库升级 => 针对数据库我们每次发布会提供增量升级SQL,可以通过执行增量SQL实现数据库的升级。
|
||||
3.兼容问题 => 每次版本发布会针对不兼容地方标注说明,需要手工修改不兼容的代码。
|
||||
|
||||
注意: 升级sql目前只提供mysql版本,执行完脚步后,新菜单需要手工进行角色授权,刷新首页才会出现。
|
||||
【20230820 放开了系统管理等模块权限注解,如果没权限请通过角色授权授权对应的按钮权限】
|
||||
15
db/版本升级说明.md
Normal file
15
db/版本升级说明.md
Normal file
@ -0,0 +1,15 @@
|
||||
# 版本升级方法
|
||||
|
||||
> JeecgBoot属于平台级产品,每次升级改动较大,目前做不到平滑升级。
|
||||
|
||||
### 增量升级方案
|
||||
#### 1.代码合并
|
||||
本地通过svn或git做好主干,在分支上做业务开发,jeecg每次版本发布,可以手工覆盖主干的代码,对比合并代码;
|
||||
|
||||
#### 2.数据库升级
|
||||
- 从3.6.2+版本增加flyway自动升级数据库机制,支持 mysql5.7、mysql8;
|
||||
- 其他库请手工执行SQL, 目录: `jeecg-module-system\jeecg-system-start\src\main\resources\flyway\sql\mysql`
|
||||
> 注意: 升级sql只提供mysql版本;如果有权限升级, 还需要手工角色授权,退出重新登录才好使。
|
||||
|
||||
#### 3.兼容问题
|
||||
每次发版,会针对不兼容地方重点说明。
|
||||
@ -19,6 +19,8 @@ services:
|
||||
--default-authentication-plugin=caching_sha2_password
|
||||
ports:
|
||||
- 3306:3306
|
||||
networks:
|
||||
- jeecg-boot
|
||||
|
||||
jeecg-boot-redis:
|
||||
image: redis:5.0
|
||||
@ -27,6 +29,8 @@ services:
|
||||
restart: always
|
||||
hostname: jeecg-boot-redis
|
||||
container_name: jeecg-boot-redis
|
||||
networks:
|
||||
- jeecg-boot
|
||||
|
||||
jeecg-boot-system:
|
||||
build:
|
||||
@ -39,4 +43,10 @@ services:
|
||||
image: jeecg-boot-system
|
||||
hostname: jeecg-boot-system
|
||||
ports:
|
||||
- 8080:8080
|
||||
- 8080:8080
|
||||
networks:
|
||||
- jeecg-boot
|
||||
|
||||
networks:
|
||||
jeecg-boot:
|
||||
name: jeecg_boot
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-parent</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.6.3</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jeecg-boot-base-core</artifactId>
|
||||
@ -82,7 +82,7 @@
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.version}</version>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
@ -145,7 +145,7 @@
|
||||
<version>${postgresql.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Quartz定时任务 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@ -183,9 +183,14 @@
|
||||
</dependency>
|
||||
|
||||
<!-- knife4j -->
|
||||
<dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||
<version>3.0.3</version>
|
||||
</dependency>-->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
|
||||
<version>${knife4j-spring-boot-starter.version}</version>
|
||||
</dependency>
|
||||
|
||||
@ -256,6 +261,15 @@
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
</dependency>
|
||||
<!--加载hutool-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@ -22,10 +22,10 @@ public interface CommonAPI {
|
||||
|
||||
/**
|
||||
* 2查询用户权限信息
|
||||
* @param username
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
Set<String> queryUserAuths(String username);
|
||||
Set<String> queryUserAuths(String userId);
|
||||
|
||||
/**
|
||||
* 3根据 id 查询数据库中存储的 DynamicDataSourceModel
|
||||
@ -117,14 +117,17 @@ public interface CommonAPI {
|
||||
*/
|
||||
Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys);
|
||||
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
/**
|
||||
* 15 字典表的 翻译,可批量
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keys 多个用逗号分割
|
||||
* @param dataSource 数据源
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys);
|
||||
List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys, String dataSource);
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
|
||||
}
|
||||
|
||||
@ -17,6 +17,8 @@ public class DataLogDTO {
|
||||
|
||||
private String type;
|
||||
|
||||
private String createName;
|
||||
|
||||
public DataLogDTO(){
|
||||
|
||||
}
|
||||
|
||||
@ -30,6 +30,13 @@ public class OnlineAuthDTO implements Serializable {
|
||||
*/
|
||||
private String onlineFormUrl;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240123 for:[QQYUN-7992]【online】工单申请下的online表单,未配置online表单开发菜单,操作报错无权限------------
|
||||
/**
|
||||
* online工单的地址
|
||||
*/
|
||||
private String onlineWorkOrderUrl;
|
||||
//update-end---author:chenrui ---date:20240123 for:[QQYUN-7992]【online】工单申请下的online表单,未配置online表单开发菜单,操作报错无权限------------
|
||||
|
||||
public OnlineAuthDTO(){
|
||||
|
||||
}
|
||||
|
||||
@ -158,6 +158,9 @@ public class AutoLogAspect {
|
||||
if(value!=null && value.toString().length()>length){
|
||||
return false;
|
||||
}
|
||||
if(value instanceof MultipartFile){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -140,11 +140,15 @@ public class DictAspect {
|
||||
String code = field.getAnnotation(Dict.class).dicCode();
|
||||
String text = field.getAnnotation(Dict.class).dicText();
|
||||
String table = field.getAnnotation(Dict.class).dictTable();
|
||||
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
String dataSource = field.getAnnotation(Dict.class).ds();
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
List<String> dataList;
|
||||
String dictCode = code;
|
||||
if (!StringUtils.isEmpty(table)) {
|
||||
dictCode = String.format("%s,%s,%s", table, text, code);
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
dictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource);
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
}
|
||||
dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(",")));
|
||||
@ -169,10 +173,15 @@ public class DictAspect {
|
||||
String code = field.getAnnotation(Dict.class).dicCode();
|
||||
String text = field.getAnnotation(Dict.class).dicText();
|
||||
String table = field.getAnnotation(Dict.class).dictTable();
|
||||
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
// 自定义的字典表数据源
|
||||
String dataSource = field.getAnnotation(Dict.class).ds();
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
String fieldDictCode = code;
|
||||
if (!StringUtils.isEmpty(table)) {
|
||||
fieldDictCode = String.format("%s,%s,%s", table, text, code);
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
fieldDictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource);
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
}
|
||||
|
||||
String value = record.getString(field.getName());
|
||||
@ -274,9 +283,25 @@ public class DictAspect {
|
||||
String[] arr = dictCode.split(",");
|
||||
String table = arr[0], text = arr[1], code = arr[2];
|
||||
String values = String.join(",", needTranslDataTable);
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
// 自定义的数据源
|
||||
String dataSource = null;
|
||||
if (arr.length > 3) {
|
||||
dataSource = arr[3];
|
||||
}
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
log.debug("translateDictFromTableByKeys.dictCode:" + dictCode);
|
||||
log.debug("translateDictFromTableByKeys.values:" + values);
|
||||
List<DictModel> texts = commonApi.translateDictFromTableByKeys(table, text, code, values);
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
|
||||
//update-begin---author:wangshuai---date:2024-01-09---for:微服务下为空报错没有参数需要传递空字符串---
|
||||
if(null == dataSource){
|
||||
dataSource = "";
|
||||
}
|
||||
//update-end---author:wangshuai---date:2024-01-09---for:微服务下为空报错没有参数需要传递空字符串---
|
||||
|
||||
List<DictModel> texts = commonApi.translateDictFromTableByKeys(table, text, code, values, dataSource);
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
log.debug("translateDictFromTableByKeys.result:" + texts);
|
||||
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
|
||||
list.addAll(texts);
|
||||
|
||||
@ -39,4 +39,16 @@ public @interface Dict {
|
||||
* @return 返回类型: String
|
||||
*/
|
||||
String dictTable() default "";
|
||||
|
||||
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
/**
|
||||
* 方法描述: 数据字典表所在数据源名称
|
||||
* 作 者: chenrui
|
||||
* 日 期: 2023年12月20日-下午4:58
|
||||
*
|
||||
* @return 返回类型: String
|
||||
*/
|
||||
String ds() default "";
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
}
|
||||
|
||||
@ -69,6 +69,8 @@ public interface CommonConstant {
|
||||
|
||||
/** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
|
||||
Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
|
||||
/** {@code 404 Not Found} (HTTP/1.0 - RFC 1945) */
|
||||
Integer SC_INTERNAL_NOT_FOUND_404 = 404;
|
||||
/** {@code 200 OK} (HTTP/1.0 - RFC 1945) */
|
||||
Integer SC_OK_200 = 200;
|
||||
|
||||
@ -375,6 +377,8 @@ public interface CommonConstant {
|
||||
/**前端vue3版本Header参数名*/
|
||||
String VERSION="X-Version";
|
||||
|
||||
String VERSION_V3 = "v3";
|
||||
|
||||
/**存储在线程变量里的动态表名*/
|
||||
String DYNAMIC_TABLE_NAME="DYNAMIC_TABLE_NAME";
|
||||
/**
|
||||
|
||||
@ -17,6 +17,9 @@ public interface DataBaseConstant {
|
||||
|
||||
/**postgreSQL达梦数据库*/
|
||||
public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL";
|
||||
|
||||
/**人大金仓数据库*/
|
||||
public static final String DB_TYPE_KINGBASEES = "KINGBASEES";
|
||||
|
||||
/**sqlserver数据库*/
|
||||
public static final String DB_TYPE_SQLSERVER = "SQLSERVER";
|
||||
|
||||
@ -13,12 +13,16 @@ import java.util.List;
|
||||
public enum RoleIndexConfigEnum {
|
||||
|
||||
/**首页自定义 admin*/
|
||||
ADMIN("admin", "dashboard/Analysis"),
|
||||
// ADMIN("admin", "dashboard/Analysis"),
|
||||
//TEST("test", "dashboard/IndexChart"),
|
||||
/**首页自定义 hr*/
|
||||
HR("hr", "dashboard/IndexBdc");
|
||||
// HR("hr", "dashboard/IndexBdc");
|
||||
|
||||
//DM("dm", "dashboard/IndexTask"),
|
||||
|
||||
// 注:此值仅为防止报错,无任何实际意义
|
||||
ROLE_INDEX_CONFIG_ENUM("RoleIndexConfigEnumDefault", "dashboard/Analysis");
|
||||
|
||||
/**
|
||||
* 角色编码
|
||||
*/
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package org.jeecg.common.exception;
|
||||
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
|
||||
/**
|
||||
* @Description: jeecg-boot自定义异常
|
||||
* @author: jeecg-boot
|
||||
@ -7,10 +9,24 @@ package org.jeecg.common.exception;
|
||||
public class JeecgBootException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 返回给前端的错误code
|
||||
*/
|
||||
private int errCode = CommonConstant.SC_INTERNAL_SERVER_ERROR_500;
|
||||
|
||||
public JeecgBootException(String message){
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public JeecgBootException(String message, int errCode){
|
||||
super(message);
|
||||
this.errCode = errCode;
|
||||
}
|
||||
|
||||
public int getErrCode() {
|
||||
return errCode;
|
||||
}
|
||||
|
||||
public JeecgBootException(Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
|
||||
@ -33,7 +33,7 @@ public class JeecgBootExceptionHandler {
|
||||
@ExceptionHandler(JeecgBootException.class)
|
||||
public Result<?> handleJeecgBootException(JeecgBootException e){
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.error(e.getMessage());
|
||||
return Result.error(e.getErrCode(), e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -19,6 +19,8 @@ public class SysFilesModel {
|
||||
private String storeType;
|
||||
/**文件大小(kb)*/
|
||||
private Double fileSize;
|
||||
/**租户id*/
|
||||
private String tenantId;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
@ -67,4 +69,12 @@ public class SysFilesModel {
|
||||
public void setFileSize(Double fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
|
||||
public String getTenantId() {
|
||||
return tenantId;
|
||||
}
|
||||
|
||||
public void setTenantId(String tenantId) {
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
}
|
||||
@ -28,7 +28,9 @@ import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -302,7 +304,7 @@ public class CommonUtils {
|
||||
DB_TYPE = DataBaseConstant.DB_TYPE_ORACLE;
|
||||
}else if(dbType.indexOf(DataBaseConstant.DB_TYPE_SQLSERVER)>=0||dbType.indexOf(sqlserver)>=0) {
|
||||
DB_TYPE = DataBaseConstant.DB_TYPE_SQLSERVER;
|
||||
}else if(dbType.indexOf(DataBaseConstant.DB_TYPE_POSTGRESQL)>=0) {
|
||||
}else if(dbType.indexOf(DataBaseConstant.DB_TYPE_POSTGRESQL)>=0 || dbType.indexOf(DataBaseConstant.DB_TYPE_KINGBASEES)>=0) {
|
||||
DB_TYPE = DataBaseConstant.DB_TYPE_POSTGRESQL;
|
||||
}else if(dbType.indexOf(DataBaseConstant.DB_TYPE_MARIADB)>=0) {
|
||||
DB_TYPE = DataBaseConstant.DB_TYPE_MARIADB;
|
||||
@ -346,8 +348,11 @@ public class CommonUtils {
|
||||
|
||||
//返回 host domain
|
||||
String baseDomainPath = null;
|
||||
int length = 80;
|
||||
if(length == serverPort){
|
||||
//update-begin---author:wangshuai---date:2024-03-15---for:【QQYUN-8561】企业微信登陆请求接口设置上下文不一致,导致接口404---
|
||||
int httpPort = 80;
|
||||
int httpsPort = 443;
|
||||
if(httpPort == serverPort || httpsPort == serverPort){
|
||||
//update-end---author:wangshuai---date:2024-03-15---for:【QQYUN-8561】企业微信登陆请求接口设置上下文不一致,导致接口404---~
|
||||
baseDomainPath = scheme + "://" + serverName + contextPath ;
|
||||
}else{
|
||||
baseDomainPath = scheme + "://" + serverName + ":" + serverPort + contextPath ;
|
||||
@ -467,4 +472,19 @@ public class CommonUtils {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出info日志,会捕获异常,防止因为日志问题导致程序异常
|
||||
*
|
||||
* @param msg
|
||||
* @param objects
|
||||
*/
|
||||
public static void logInfo(String msg, Object... objects) {
|
||||
try {
|
||||
log.info(msg, objects);
|
||||
} catch (Exception e) {
|
||||
log.warn("{} —— {}", msg, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -62,8 +62,8 @@ public class DySmsHelper {
|
||||
|
||||
//update-begin-author:taoyan date:20200811 for:配置类数据获取
|
||||
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
|
||||
logger.info("阿里大鱼短信秘钥 accessKeyId:" + staticConfig.getAccessKeyId());
|
||||
logger.info("阿里大鱼短信秘钥 accessKeySecret:"+ staticConfig.getAccessKeySecret());
|
||||
//logger.info("阿里大鱼短信秘钥 accessKeyId:" + staticConfig.getAccessKeyId());
|
||||
//logger.info("阿里大鱼短信秘钥 accessKeySecret:"+ staticConfig.getAccessKeySecret());
|
||||
setAccessKeyId(staticConfig.getAccessKeyId());
|
||||
setAccessKeySecret(staticConfig.getAccessKeySecret());
|
||||
//update-end-author:taoyan date:20200811 for:配置类数据获取
|
||||
|
||||
@ -29,6 +29,17 @@ public class SqlInjectionUtil {
|
||||
* 字典专用—sql注入关键词
|
||||
*/
|
||||
private static String specialDictSqlXssStr = "exec |peformance_schema|information_schema|extractvalue|updatexml|geohash|gtid_subset|gtid_subtract|insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|+|--";
|
||||
/**
|
||||
* 完整匹配的key,不需要考虑前空格
|
||||
*/
|
||||
private static List<String> FULL_MATCHING_KEYWRODS = new ArrayList<>();
|
||||
static {
|
||||
FULL_MATCHING_KEYWRODS.add(";");
|
||||
FULL_MATCHING_KEYWRODS.add("+");
|
||||
FULL_MATCHING_KEYWRODS.add("--");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sql注入风险的 正则关键字
|
||||
*
|
||||
@ -50,6 +61,8 @@ public class SqlInjectionUtil {
|
||||
* sql注释的正则
|
||||
*/
|
||||
private final static Pattern SQL_ANNOTATION = Pattern.compile("/\\*[\\s\\S]*\\*/");
|
||||
private final static String SQL_ANNOTATION2 = "--";
|
||||
|
||||
/**
|
||||
* sql注入提示语
|
||||
*/
|
||||
@ -128,7 +141,13 @@ public class SqlInjectionUtil {
|
||||
if (sql.startsWith(keyword.trim())) {
|
||||
return true;
|
||||
} else if (sql.contains(keyword)) {
|
||||
if (sql.contains(" " + keyword)) {
|
||||
// 需要匹配的,sql注入关键词
|
||||
String matchingText = " " + keyword;
|
||||
if(FULL_MATCHING_KEYWRODS.contains(keyword)){
|
||||
matchingText = keyword;
|
||||
}
|
||||
|
||||
if (sql.contains(matchingText)) {
|
||||
return true;
|
||||
} else {
|
||||
String regularStr = "\\s+\\S+" + keyword;
|
||||
@ -244,6 +263,13 @@ public class SqlInjectionUtil {
|
||||
* @return
|
||||
*/
|
||||
public static void checkSqlAnnotation(String str){
|
||||
if(str.contains(SQL_ANNOTATION2)){
|
||||
String error = "请注意,SQL中不允许含注释,有安全风险!";
|
||||
log.error(error);
|
||||
throw new RuntimeException(error);
|
||||
}
|
||||
|
||||
|
||||
Matcher matcher = SQL_ANNOTATION.matcher(str);
|
||||
if(matcher.find()){
|
||||
String error = "请注意,值可能存在SQL注入风险---> \\*.*\\";
|
||||
@ -260,7 +286,7 @@ public class SqlInjectionUtil {
|
||||
*
|
||||
* @param table
|
||||
*/
|
||||
private static Pattern tableNamePattern = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_]{0,63}$");
|
||||
private static Pattern tableNamePattern = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_\\$]{0,63}$");
|
||||
public static String getSqlInjectTableName(String table) {
|
||||
if(oConvertUtils.isEmpty(table)){
|
||||
return table;
|
||||
|
||||
@ -61,6 +61,10 @@ public class SsrfFileTypeFilter {
|
||||
FILE_TYPE_WHITE_LIST.add("7z");
|
||||
FILE_TYPE_WHITE_LIST.add("tar");
|
||||
|
||||
//app文件后缀
|
||||
FILE_TYPE_WHITE_LIST.add("apk");
|
||||
FILE_TYPE_WHITE_LIST.add("wgt");
|
||||
|
||||
//设置禁止文件的头部标记
|
||||
FILE_TYPE_MAP.put("3c25402070616765206c", "jsp");
|
||||
FILE_TYPE_MAP.put("3c3f7068700a0a2f2a2a0a202a205048", "php");
|
||||
|
||||
@ -1,55 +1,6 @@
|
||||
package org.jeecg.common.util.sqlInjection.parse;
|
||||
|
||||
import net.sf.jsqlparser.expression.AllValue;
|
||||
import net.sf.jsqlparser.expression.AnalyticExpression;
|
||||
import net.sf.jsqlparser.expression.AnyComparisonExpression;
|
||||
import net.sf.jsqlparser.expression.ArrayConstructor;
|
||||
import net.sf.jsqlparser.expression.ArrayExpression;
|
||||
import net.sf.jsqlparser.expression.BinaryExpression;
|
||||
import net.sf.jsqlparser.expression.CaseExpression;
|
||||
import net.sf.jsqlparser.expression.CastExpression;
|
||||
import net.sf.jsqlparser.expression.CollateExpression;
|
||||
import net.sf.jsqlparser.expression.ConnectByRootOperator;
|
||||
import net.sf.jsqlparser.expression.DateTimeLiteralExpression;
|
||||
import net.sf.jsqlparser.expression.DateValue;
|
||||
import net.sf.jsqlparser.expression.DoubleValue;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.ExpressionVisitor;
|
||||
import net.sf.jsqlparser.expression.ExtractExpression;
|
||||
import net.sf.jsqlparser.expression.Function;
|
||||
import net.sf.jsqlparser.expression.HexValue;
|
||||
import net.sf.jsqlparser.expression.IntervalExpression;
|
||||
import net.sf.jsqlparser.expression.JdbcNamedParameter;
|
||||
import net.sf.jsqlparser.expression.JdbcParameter;
|
||||
import net.sf.jsqlparser.expression.JsonAggregateFunction;
|
||||
import net.sf.jsqlparser.expression.JsonExpression;
|
||||
import net.sf.jsqlparser.expression.JsonFunction;
|
||||
import net.sf.jsqlparser.expression.JsonFunctionExpression;
|
||||
import net.sf.jsqlparser.expression.KeepExpression;
|
||||
import net.sf.jsqlparser.expression.LongValue;
|
||||
import net.sf.jsqlparser.expression.MySQLGroupConcat;
|
||||
import net.sf.jsqlparser.expression.NextValExpression;
|
||||
import net.sf.jsqlparser.expression.NotExpression;
|
||||
import net.sf.jsqlparser.expression.NullValue;
|
||||
import net.sf.jsqlparser.expression.NumericBind;
|
||||
import net.sf.jsqlparser.expression.OracleHierarchicalExpression;
|
||||
import net.sf.jsqlparser.expression.OracleHint;
|
||||
import net.sf.jsqlparser.expression.OracleNamedFunctionParameter;
|
||||
import net.sf.jsqlparser.expression.Parenthesis;
|
||||
import net.sf.jsqlparser.expression.RowConstructor;
|
||||
import net.sf.jsqlparser.expression.RowGetExpression;
|
||||
import net.sf.jsqlparser.expression.SignedExpression;
|
||||
import net.sf.jsqlparser.expression.StringValue;
|
||||
import net.sf.jsqlparser.expression.TimeKeyExpression;
|
||||
import net.sf.jsqlparser.expression.TimeValue;
|
||||
import net.sf.jsqlparser.expression.TimestampValue;
|
||||
import net.sf.jsqlparser.expression.TimezoneExpression;
|
||||
import net.sf.jsqlparser.expression.TryCastExpression;
|
||||
import net.sf.jsqlparser.expression.UserVariable;
|
||||
import net.sf.jsqlparser.expression.ValueListExpression;
|
||||
import net.sf.jsqlparser.expression.VariableAssignment;
|
||||
import net.sf.jsqlparser.expression.WhenClause;
|
||||
import net.sf.jsqlparser.expression.XMLSerializeExpr;
|
||||
import net.sf.jsqlparser.expression.*;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
|
||||
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
|
||||
@ -215,6 +166,23 @@ public class ConstAnalyzer implements ExpressionVisitor, ItemsListVisitor {
|
||||
expr.getBetweenExpressionEnd().accept(this);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 用于处理 OverlapsCondition 类型的表达式
|
||||
// * @param overlapsCondition
|
||||
// */
|
||||
// @Override
|
||||
// public void visit(OverlapsCondition overlapsCondition) {
|
||||
// constFlag.set(false);
|
||||
// }
|
||||
// /**
|
||||
// * 用于处理 SafeCastExpression 类型的表达式。
|
||||
// * @param safeCastExpression
|
||||
// */
|
||||
// @Override
|
||||
// public void visit(SafeCastExpression safeCastExpression) {
|
||||
// constFlag.set(false);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void visit(EqualsTo expr) {
|
||||
visitBinaryExpression(expr);
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
package org.jeecg.config;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.SpringApplicationRunListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 启动程序修改DruidWallConfig配置
|
||||
* 允许SELECT语句的WHERE子句是一个永真条件
|
||||
* @author eightmonth@qq.com
|
||||
* @date 2024/4/8 11:37
|
||||
*/
|
||||
public class DruidWallConfigRegister implements SpringApplicationRunListener {
|
||||
|
||||
public SpringApplication application;
|
||||
|
||||
private String[] args;
|
||||
|
||||
|
||||
/**
|
||||
* 必备,否则启动报错
|
||||
* @param application
|
||||
* @param args
|
||||
*/
|
||||
public DruidWallConfigRegister(SpringApplication application, String[] args) {
|
||||
this.application = application;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextLoaded(ConfigurableApplicationContext context) {
|
||||
ConfigurableEnvironment env = context.getEnvironment();
|
||||
Map<String, Object> props = new HashMap<>();
|
||||
props.put("spring.datasource.dynamic.druid.wall.selectWhereAlwayTrueCheck", false);
|
||||
|
||||
MutablePropertySources propertySources = env.getPropertySources();
|
||||
|
||||
PropertySource<Map<String, Object>> propertySource = new MapPropertySource("jeecg-datasource-config", props);
|
||||
|
||||
propertySources.addLast(propertySource);
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
package org.jeecg.config;
|
||||
|
||||
|
||||
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.springframework.beans.BeansException;
|
||||
@ -19,15 +18,13 @@ import springfox.documentation.builders.ApiInfoBuilder;
|
||||
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 +36,7 @@ import java.util.stream.Collectors;
|
||||
* @Author scott
|
||||
*/
|
||||
@Configuration
|
||||
@EnableSwagger2 //开启 Swagger2
|
||||
@EnableKnife4j //开启 knife4j,可以不写
|
||||
@EnableSwagger2WebMvc
|
||||
@Import(BeanValidatorPluginsConfiguration.class)
|
||||
public class Swagger2Config implements WebMvcConfigurer {
|
||||
|
||||
@ -152,7 +148,7 @@ public class Swagger2Config implements WebMvcConfigurer {
|
||||
|
||||
@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;
|
||||
|
||||
@ -31,7 +31,7 @@ public class WebSocketConfig {
|
||||
FilterRegistrationBean bean = new FilterRegistrationBean();
|
||||
bean.setFilter(websocketFilter());
|
||||
//TODO 临时注释掉,测试下线上socket总断的问题
|
||||
bean.addUrlPatterns("/websocket/*","/eoaSocket/*","/eoaNewChatSocket/*", "/newsWebsocket/*", "/vxeSocket/*");
|
||||
bean.addUrlPatterns("/taskCountSocket/*", "/websocket/*","/eoaSocket/*","/eoaNewChatSocket/*", "/newsWebsocket/*", "/vxeSocket/*");
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package org.jeecg.config.shiro;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 免认证注解,认证系统结合spring MVC的@RequestMapping获取请求路径进行免登录配置
|
||||
* @author eightmonth@qq.com
|
||||
* @date 2024/2/28 9:58
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface IgnoreAuth {
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package org.jeecg.config.shiro;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
|
||||
@ -9,10 +10,7 @@ import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.crazycake.shiro.IRedisManager;
|
||||
import org.crazycake.shiro.RedisCacheManager;
|
||||
import org.crazycake.shiro.RedisClusterManager;
|
||||
import org.crazycake.shiro.RedisManager;
|
||||
import org.crazycake.shiro.*;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.JeecgBaseConfig;
|
||||
@ -20,17 +18,26 @@ import org.jeecg.config.shiro.filters.CustomShiroFilterFactoryBean;
|
||||
import org.jeecg.config.shiro.filters.JwtFilter;
|
||||
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
import redis.clients.jedis.HostAndPort;
|
||||
import redis.clients.jedis.JedisCluster;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -49,7 +56,8 @@ public class ShiroConfig {
|
||||
private Environment env;
|
||||
@Resource
|
||||
private JeecgBaseConfig jeecgBaseConfig;
|
||||
|
||||
@Autowired(required = false)
|
||||
private RedisProperties redisProperties;
|
||||
/**
|
||||
* Filter Chain定义说明
|
||||
*
|
||||
@ -74,6 +82,7 @@ public class ShiroConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 配置不会被拦截的链接 顺序判断
|
||||
filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录
|
||||
filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除
|
||||
@ -92,6 +101,9 @@ public class ShiroConfig {
|
||||
filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码
|
||||
filterChainDefinitionMap.put("/sys/common/static/**", "anon");//图片预览 &下载文件不限制token
|
||||
filterChainDefinitionMap.put("/sys/common/pdf/**", "anon");//pdf预览
|
||||
|
||||
//filterChainDefinitionMap.put("/sys/common/view/**", "anon");//图片预览不限制token
|
||||
//filterChainDefinitionMap.put("/sys/common/download/**", "anon");//文件下载不限制token
|
||||
filterChainDefinitionMap.put("/generic/**", "anon");//pdf预览需要文件
|
||||
|
||||
filterChainDefinitionMap.put("/sys/getLoginQrcode/**", "anon"); //登录二维码
|
||||
@ -99,6 +111,7 @@ public class ShiroConfig {
|
||||
filterChainDefinitionMap.put("/sys/checkAuth", "anon"); //授权接口排除
|
||||
|
||||
|
||||
//update-begin--Author:scott Date:20221116 for:排除静态资源后缀
|
||||
filterChainDefinitionMap.put("/", "anon");
|
||||
filterChainDefinitionMap.put("/doc.html", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.js", "anon");
|
||||
@ -113,14 +126,17 @@ public class ShiroConfig {
|
||||
filterChainDefinitionMap.put("/**/*.ttf", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.woff", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.woff2", "anon");
|
||||
//update-end--Author:scott Date:20221116 for:排除静态资源后缀
|
||||
|
||||
filterChainDefinitionMap.put("/druid/**", "anon");
|
||||
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
|
||||
filterChainDefinitionMap.put("/swagger**/**", "anon");
|
||||
filterChainDefinitionMap.put("/webjars/**", "anon");
|
||||
filterChainDefinitionMap.put("/v2/**", "anon");
|
||||
|
||||
|
||||
// update-begin--Author:sunjianlei Date:20210510 for:排除消息通告查看详情页面(用于第三方APP)
|
||||
filterChainDefinitionMap.put("/sys/annountCement/show/**", "anon");
|
||||
// update-end--Author:sunjianlei Date:20210510 for:排除消息通告查看详情页面(用于第三方APP)
|
||||
|
||||
//积木报表排除
|
||||
filterChainDefinitionMap.put("/jmreport/**", "anon");
|
||||
@ -136,7 +152,7 @@ public class ShiroConfig {
|
||||
//大屏模板例子
|
||||
filterChainDefinitionMap.put("/test/bigScreen/**", "anon");
|
||||
filterChainDefinitionMap.put("/bigscreen/template1/**", "anon");
|
||||
filterChainDefinitionMap.put("/bigscreen/template1/**", "anon");
|
||||
filterChainDefinitionMap.put("/bigscreen/template2/**", "anon");
|
||||
//filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试
|
||||
//filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面
|
||||
//filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试
|
||||
@ -151,10 +167,10 @@ public class ShiroConfig {
|
||||
//测试模块排除
|
||||
filterChainDefinitionMap.put("/test/seata/**", "anon");
|
||||
|
||||
// update-begin--author:liusq Date:20230522 for:[issues/4829]访问不存在的url时会提示Token失效,请重新登录呢
|
||||
//错误路径排除
|
||||
filterChainDefinitionMap.put("/error", "anon");
|
||||
// update-end--author:liusq Date:20230522 for:[issues/4829]访问不存在的url时会提示Token失效,请重新登录呢
|
||||
// 企业微信证书排除
|
||||
filterChainDefinitionMap.put("/WW_verify*", "anon");
|
||||
|
||||
// 添加自己的过滤器并且取名为jwt
|
||||
Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
|
||||
@ -172,6 +188,20 @@ public class ShiroConfig {
|
||||
return shiroFilterFactoryBean;
|
||||
}
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@Bean
|
||||
public FilterRegistrationBean shiroFilterRegistration() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setFilter(new DelegatingFilterProxy("shiroFilterFactoryBean"));
|
||||
registration.setEnabled(true);
|
||||
registration.addUrlPatterns("/*");
|
||||
//支持异步
|
||||
registration.setAsyncSupported(true);
|
||||
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
|
||||
return registration;
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
|
||||
@Bean("securityManager")
|
||||
public DefaultWebSecurityManager securityManager(ShiroRealm myRealm) {
|
||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||
@ -249,6 +279,19 @@ public class ShiroConfig {
|
||||
public IRedisManager redisManager() {
|
||||
log.info("===============(2)创建RedisManager,连接Redis..");
|
||||
IRedisManager manager;
|
||||
// sentinel cluster redis(【issues/5569】shiro集成 redis 不支持 sentinel 方式部署的redis集群 #5569)
|
||||
if (Objects.nonNull(redisProperties)
|
||||
&& Objects.nonNull(redisProperties.getSentinel())
|
||||
&& !CollectionUtils.isEmpty(redisProperties.getSentinel().getNodes())) {
|
||||
RedisSentinelManager sentinelManager = new RedisSentinelManager();
|
||||
sentinelManager.setMasterName(redisProperties.getSentinel().getMaster());
|
||||
sentinelManager.setHost(String.join(",", redisProperties.getSentinel().getNodes()));
|
||||
sentinelManager.setPassword(redisProperties.getSentinel().getPassword());
|
||||
sentinelManager.setDatabase(redisProperties.getDatabase());
|
||||
|
||||
return sentinelManager;
|
||||
}
|
||||
|
||||
// redis 单机支持,在集群为空,或者集群无机器时候使用 add by jzyadmin@163.com
|
||||
if (lettuceConnectionFactory.getClusterConfiguration() == null || lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().isEmpty()) {
|
||||
RedisManager redisManager = new RedisManager();
|
||||
|
||||
@ -62,9 +62,11 @@ public class ShiroRealm extends AuthorizingRealm {
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
|
||||
log.debug("===============Shiro权限认证开始============ [ roles、permissions]==========");
|
||||
String username = null;
|
||||
String userId = null;
|
||||
if (principals != null) {
|
||||
LoginUser sysUser = (LoginUser) principals.getPrimaryPrincipal();
|
||||
username = sysUser.getUsername();
|
||||
userId = sysUser.getId();
|
||||
}
|
||||
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||
|
||||
@ -74,7 +76,7 @@ public class ShiroRealm extends AuthorizingRealm {
|
||||
info.setRoles(roleSet);
|
||||
|
||||
// 设置用户拥有的权限集合,比如“sys:role:add,sys:user:add”
|
||||
Set<String> permissionSet = commonApi.queryUserAuths(username);
|
||||
Set<String> permissionSet = commonApi.queryUserAuths(userId);
|
||||
info.addStringPermissions(permissionSet);
|
||||
//System.out.println(permissionSet);
|
||||
log.info("===============Shiro权限认证成功==============");
|
||||
|
||||
@ -8,6 +8,7 @@ import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.shiro.JwtToken;
|
||||
import org.jeecg.config.shiro.ignore.InMemoryIgnoreAuth;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
@ -47,6 +48,10 @@ public class JwtFilter extends BasicHttpAuthenticationFilter {
|
||||
@Override
|
||||
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
|
||||
try {
|
||||
// 判断当前路径是不是注解了@IngoreAuth路径,如果是,则放开验证
|
||||
if (InMemoryIgnoreAuth.contains(((HttpServletRequest) request).getServletPath())) {
|
||||
return true;
|
||||
}
|
||||
executeLogin(request, response);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
package org.jeecg.config.shiro.ignore;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.jeecg.config.shiro.IgnoreAuth;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 在spring boot初始化时,根据@RestController注解获取当前spring容器中的bean
|
||||
* @author eightmonth@qq.com
|
||||
* @date 2024/4/18 11:35
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class IgnoreAuthPostProcessor implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
List<String> ignoreAuthUrls = new ArrayList<>();
|
||||
if (event.getApplicationContext().getParent() == null) {
|
||||
// 只处理根应用上下文的事件,避免在子上下文中重复处理
|
||||
Map<String, Object> restControllers = applicationContext.getBeansWithAnnotation(RestController.class);
|
||||
for (Object restController : restControllers.values()) {
|
||||
// 如 online系统的controller并不是spring 默认生成
|
||||
if (restController instanceof Advised) {
|
||||
ignoreAuthUrls.addAll(postProcessRestController(restController));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(ignoreAuthUrls)) {
|
||||
InMemoryIgnoreAuth.set(ignoreAuthUrls);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> postProcessRestController(Object restController) {
|
||||
List<String> ignoreAuthUrls = new ArrayList<>();
|
||||
Class<?> clazz = ((Advised) restController).getTargetClass();
|
||||
RequestMapping base = clazz.getAnnotation(RequestMapping.class);
|
||||
String[] baseUrl = Objects.nonNull(base) ? base.value() : new String[]{};
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
|
||||
for (Method method : methods) {
|
||||
if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(RequestMapping.class)) {
|
||||
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
|
||||
String[] uri = requestMapping.value();
|
||||
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
|
||||
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(GetMapping.class)) {
|
||||
GetMapping requestMapping = method.getAnnotation(GetMapping.class);
|
||||
String[] uri = requestMapping.value();
|
||||
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
|
||||
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PostMapping.class)) {
|
||||
PostMapping requestMapping = method.getAnnotation(PostMapping.class);
|
||||
String[] uri = requestMapping.value();
|
||||
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
|
||||
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PutMapping.class)) {
|
||||
PutMapping requestMapping = method.getAnnotation(PutMapping.class);
|
||||
String[] uri = requestMapping.value();
|
||||
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
|
||||
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(DeleteMapping.class)) {
|
||||
DeleteMapping requestMapping = method.getAnnotation(DeleteMapping.class);
|
||||
String[] uri = requestMapping.value();
|
||||
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
|
||||
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PatchMapping.class)) {
|
||||
PatchMapping requestMapping = method.getAnnotation(PatchMapping.class);
|
||||
String[] uri = requestMapping.value();
|
||||
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
|
||||
}
|
||||
}
|
||||
|
||||
return ignoreAuthUrls;
|
||||
}
|
||||
|
||||
private List<String> rebuildUrl(String[] bases, String[] uris) {
|
||||
List<String> urls = new ArrayList<>();
|
||||
if (bases.length > 0) {
|
||||
for (String base : bases) {
|
||||
for (String uri : uris) {
|
||||
urls.add(prefix(base) + prefix(uri));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Arrays.stream(uris).forEach(uri -> {
|
||||
urls.add(prefix(uri));
|
||||
});
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
private String prefix(String seg) {
|
||||
return seg.startsWith("/") ? seg : "/"+seg;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package org.jeecg.config.shiro.ignore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 使用内存存储通过@IgnoreAuth注解的url,配合JwtFilter进行免登录校验
|
||||
* PS:无法使用ThreadLocal进行存储,因为ThreadLocal装载时,JwtFilter已经初始化完毕,导致该类获取ThreadLocal为空
|
||||
* @author eightmonth@qq.com
|
||||
* @date 2024/4/18 15:02
|
||||
*/
|
||||
public class InMemoryIgnoreAuth {
|
||||
private static final List<String> IGNORE_AUTH_LIST = new ArrayList<>();
|
||||
|
||||
public InMemoryIgnoreAuth() {}
|
||||
|
||||
public static void set(List<String> list) {
|
||||
IGNORE_AUTH_LIST.addAll(list);
|
||||
}
|
||||
|
||||
public static List<String> get() {
|
||||
return IGNORE_AUTH_LIST;
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
IGNORE_AUTH_LIST.clear();
|
||||
}
|
||||
|
||||
public static boolean contains(String url) {
|
||||
for (String ignoreAuth : IGNORE_AUTH_LIST) {
|
||||
if (url.endsWith(ignoreAuth)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -172,7 +172,11 @@ public class HttpUtils {
|
||||
String[] params = param.split("&");
|
||||
for (String s : params) {
|
||||
int index = s.indexOf("=");
|
||||
result.put(s.substring(0, index), s.substring(index + 1));
|
||||
//update-begin---author:chenrui ---date:20240222 for:[issues/5879]数据查询传ds=“”造成的异常------------
|
||||
if (index != -1) {
|
||||
result.put(s.substring(0, index), s.substring(index + 1));
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240222 for:[issues/5879]数据查询传ds=“”造成的异常------------
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -196,7 +200,11 @@ public class HttpUtils {
|
||||
String[] params = param.split("&");
|
||||
for (String s : params) {
|
||||
int index = s.indexOf("=");
|
||||
result.put(s.substring(0, index), s.substring(index + 1));
|
||||
//update-begin---author:chenrui ---date:20240222 for:[issues/5879]数据查询传ds=“”造成的异常------------
|
||||
if (index != -1) {
|
||||
result.put(s.substring(0, index), s.substring(index + 1));
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240222 for:[issues/5879]数据查询传ds=“”造成的异常------------
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -35,4 +35,5 @@ public class Firewall {
|
||||
public void setLowCodeMode(String lowCodeMode) {
|
||||
this.lowCodeMode = lowCodeMode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
org.springframework.boot.SpringApplicationRunListener=\
|
||||
org.jeecg.config.DruidWallConfigRegister
|
||||
@ -56,7 +56,7 @@
|
||||
</div>
|
||||
<div style="width: 600px; margin: 0 auto; margin-top: 50px; font-size: 12px; -webkit-font-smoothing: subpixel-antialiased; text-size-adjust: 100%;">
|
||||
<p style="text-align: center; line-height: 20.4px; text-size-adjust: 100%; font-family: 'Microsoft YaHei'!important; padding: 0px !important; margin: 0px !important; color: #7e8890 !important;">
|
||||
<span class="appleLinks">Copyright © 2023-2024 北京国炬科技股份有限公司. 保留所有权利。</span>
|
||||
<span class="appleLinks">Copyright © 2023-2024 北京国炬信息技术有限公司. 保留所有权利。</span>
|
||||
</p>
|
||||
<p style="text-align: center;line-height: 20.4px; text-size-adjust: 100%; font-family: 'Microsoft YaHei'!important; padding: 0px !important; margin: 0px; color: #7e8890 !important; margin-top: 10px;">
|
||||
<span class="appleLinks">邮件由系统自动发送,请勿直接回复本邮件!</span>
|
||||
|
||||
@ -6,7 +6,10 @@
|
||||
<body>
|
||||
<div class="box-content">
|
||||
<div class="info-top">
|
||||
<img src="https://jeecgdev.oss-cn-beijing.aliyuncs.com/temp/logo(1)_1697180761742.png" style="float: left; margin: 0 10px 0 0; width: 32px;height:32px" /><div style="color:#fff"><strong>【重要】新数据提醒</strong></div>
|
||||
<img src="https://qiaoqiaoyun.oss-cn-beijing.aliyuncs.com/site/qqyunemaillogo.png" style="width: 35px;height:35px; background: #5e8ee5; border-radius: 5px;" />
|
||||
<div style="color:#fff;">
|
||||
<strong>【重要】新数据提醒</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-wrap">
|
||||
<div class="tips" style="padding:15px;">
|
||||
@ -23,12 +26,12 @@
|
||||
<a style="color: #006eff;" href="${moreLink}" target="_blank" rel="noopener">[查看所有数据]</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="footer">北京国炬平台</div>
|
||||
<div class="footer">敲敲云平台</div>
|
||||
<div class="footer" id="currentTime"></div>
|
||||
</div>
|
||||
<div style="width: 600px; margin: 0 auto; margin-top: 50px; font-size: 12px; -webkit-font-smoothing: subpixel-antialiased; text-size-adjust: 100%;">
|
||||
<p style="text-align: center; line-height: 20.4px; text-size-adjust: 100%; font-family: 'Microsoft YaHei'!important; padding: 0px !important; margin: 0px !important; color: #7e8890 !important;">
|
||||
<span class="appleLinks">Copyright © 2023-2024 北京国炬科技股份有限公司. 保留所有权利。</span>
|
||||
<span class="appleLinks">Copyright © 2023-2024 北京敲敲云科技有限公司. 保留所有权利。</span>
|
||||
</p>
|
||||
<p style="text-align: center;line-height: 20.4px; text-size-adjust: 100%; font-family: 'Microsoft YaHei'!important; padding: 0px !important; margin: 0px; color: #7e8890 !important; margin-top: 10px;">
|
||||
<span class="appleLinks">邮件由系统自动发送,请勿直接回复本邮件!</span>
|
||||
@ -46,6 +49,8 @@
|
||||
}
|
||||
|
||||
.info-top{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px 25px;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>jeecg-boot-parent</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.6.3</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -16,6 +16,12 @@
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-base-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- chatgpt -->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-starter-chatgpt</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@ -24,7 +24,7 @@ public class JcloudDemoProviderController {
|
||||
private JcloudDemoService jcloudDemoService;
|
||||
|
||||
@GetMapping("/getMessage")
|
||||
public String getMessage(@RequestParam String name) {
|
||||
public String getMessage(@RequestParam(name = "name") String name) {
|
||||
String msg = jcloudDemoService.getMessage(name);
|
||||
log.info(" 微服务被调用:{} ",msg);
|
||||
return msg;
|
||||
|
||||
34
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/gpt/cache/LocalCache.java
vendored
Normal file
34
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/gpt/cache/LocalCache.java
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
package org.jeecg.modules.demo.gpt.cache;
|
||||
|
||||
import cn.hutool.cache.CacheUtil;
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.core.date.DateUnit;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
|
||||
/**
|
||||
* 聊天记录本地缓存
|
||||
* @author chenrui
|
||||
* @date 2024/1/26 20:06
|
||||
*/
|
||||
public class LocalCache {
|
||||
/**
|
||||
* 缓存时长
|
||||
*/
|
||||
public static final long TIMEOUT = 5 * DateUnit.MINUTE.getMillis();
|
||||
/**
|
||||
* 清理间隔
|
||||
*/
|
||||
private static final long CLEAN_TIMEOUT = 5 * DateUnit.MINUTE.getMillis();
|
||||
/**
|
||||
* 缓存对象
|
||||
*/
|
||||
public static final TimedCache<String, Object> CACHE = CacheUtil.newTimedCache(TIMEOUT);
|
||||
|
||||
static {
|
||||
//启动定时任务
|
||||
CACHE.schedulePrune(CLEAN_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@ -0,0 +1,74 @@
|
||||
package org.jeecg.modules.demo.gpt.controller;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.modules.demo.gpt.service.ChatService;
|
||||
import org.jeecg.modules.demo.gpt.vo.ChatHistoryVO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
|
||||
/**
|
||||
* @Description: chatGpt-聊天接口
|
||||
* @Author: chenrui
|
||||
* @Date: 2024/1/9 16:30
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/ai/chat")
|
||||
public class ChatController {
|
||||
|
||||
@Autowired
|
||||
ChatService chatService;
|
||||
|
||||
/**
|
||||
* 创建sse连接
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/send")
|
||||
public SseEmitter createConnect(@RequestParam(name = "topicId", required = false) String topicId, @RequestParam(name = "message", required = true) String message) {
|
||||
SseEmitter sse = chatService.createChat();
|
||||
chatService.sendMessage(topicId, message);
|
||||
return sse;
|
||||
}
|
||||
|
||||
//update-begin---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
/**
|
||||
* 保存聊天记录
|
||||
* @param chatHistoryVO
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/2/22 13:54
|
||||
*/
|
||||
@PostMapping(value = "/history/save")
|
||||
@ResponseBody
|
||||
public Result<?> saveHistory(@RequestBody ChatHistoryVO chatHistoryVO) {
|
||||
return chatService.saveHistory(chatHistoryVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询聊天记录
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/2/22 14:03
|
||||
*/
|
||||
@GetMapping(value = "/history/get")
|
||||
@ResponseBody
|
||||
public Result<ChatHistoryVO> getHistoryByTopic() {
|
||||
return chatService.getHistoryByTopic();
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
|
||||
/**
|
||||
* 关闭连接
|
||||
*/
|
||||
@GetMapping(value = "/close")
|
||||
public void closeConnect() {
|
||||
chatService.closeChat();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@ -0,0 +1,136 @@
|
||||
package org.jeecg.modules.demo.gpt.listeners;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse;
|
||||
import com.unfbx.chatgpt.entity.chat.Message;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okhttp3.sse.EventSource;
|
||||
import okhttp3.sse.EventSourceListener;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
/**
|
||||
* OpenAI的SSE监听
|
||||
* @author chenrui
|
||||
* @date 2024/1/26 20:06
|
||||
*/
|
||||
@Slf4j
|
||||
public class OpenAISSEEventSourceListener extends EventSourceListener {
|
||||
|
||||
private long tokens;
|
||||
|
||||
private SseEmitter sseEmitter;
|
||||
|
||||
private String topicId;
|
||||
|
||||
public OpenAISSEEventSourceListener(SseEmitter sseEmitter) {
|
||||
this.sseEmitter = sseEmitter;
|
||||
}
|
||||
|
||||
public OpenAISSEEventSourceListener(String topicId,SseEmitter sseEmitter){
|
||||
this.topicId = topicId;
|
||||
this.sseEmitter = sseEmitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onOpen(@NotNull EventSource eventSource, @NotNull Response response) {
|
||||
log.info("OpenAI建立sse连接...");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void onEvent(@NotNull EventSource eventSource, String id, String type, @NotNull String data) {
|
||||
log.debug("OpenAI返回数据:{}", data);
|
||||
tokens += 1;
|
||||
if (data.equals("[DONE]")) {
|
||||
log.info("OpenAI返回数据结束了");
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[TOKENS]")
|
||||
.data("<br/><br/>tokens:" + tokens())
|
||||
.reconnectTime(3000));
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[DONE]")
|
||||
.data("[DONE]")
|
||||
.reconnectTime(3000));
|
||||
// 传输完成后自动关闭sse
|
||||
sseEmitter.complete();
|
||||
return;
|
||||
}
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
ChatCompletionResponse completionResponse = mapper.readValue(data, ChatCompletionResponse.class); // 读取Json
|
||||
try {
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id(this.topicId)
|
||||
.data(completionResponse.getChoices().get(0).getDelta())
|
||||
.reconnectTime(3000));
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(),e);
|
||||
eventSource.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClosed(@NotNull EventSource eventSource) {
|
||||
log.info("流式输出返回值总共{}tokens", tokens() - 2);
|
||||
log.info("OpenAI关闭sse连接...");
|
||||
}
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void onFailure(@NotNull EventSource eventSource, Throwable t, Response response) {
|
||||
String errMsg = "";
|
||||
ResponseBody body = null == response ? null:response.body();
|
||||
if (Objects.nonNull(body)) {
|
||||
log.error("OpenAI sse连接异常data:{},异常:{}", body.string(), t.getMessage());
|
||||
errMsg = body.string();
|
||||
} else {
|
||||
log.error("OpenAI sse连接异常data:{},异常:{}", response, t.getMessage());
|
||||
errMsg = t.getMessage();
|
||||
}
|
||||
eventSource.cancel();
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[ERR]")
|
||||
.data(Message.builder().content(explainErr(errMsg)).build())
|
||||
.reconnectTime(3000));
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[DONE]")
|
||||
.data("[DONE]")
|
||||
.reconnectTime(3000));
|
||||
sseEmitter.complete();
|
||||
}
|
||||
|
||||
private String explainErr(String errMsg){
|
||||
if(StringUtils.isEmpty(errMsg)){
|
||||
return "";
|
||||
}
|
||||
if(errMsg.contains("Rate limit")){
|
||||
return "请求频率太快了,请等待20秒再试.";
|
||||
}
|
||||
return errMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* tokens
|
||||
* @return
|
||||
*/
|
||||
public long tokens() {
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@ -0,0 +1,56 @@
|
||||
package org.jeecg.modules.demo.gpt.service;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.modules.demo.gpt.vo.ChatHistoryVO;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
|
||||
/**
|
||||
* AI助手聊天Service
|
||||
* @author chenrui
|
||||
* @date 2024/1/26 20:08
|
||||
*/
|
||||
public interface ChatService {
|
||||
/**
|
||||
* 创建SSE
|
||||
* @return
|
||||
*/
|
||||
SseEmitter createChat();
|
||||
|
||||
/**
|
||||
* 关闭SSE
|
||||
*/
|
||||
void closeChat();
|
||||
|
||||
/**
|
||||
* 客户端发送消息到服务端
|
||||
*
|
||||
* @param topicId
|
||||
* @param message
|
||||
* @author chenrui
|
||||
* @date 2024/1/26 20:01
|
||||
*/
|
||||
void sendMessage(String topicId, String message);
|
||||
|
||||
//update-begin---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
/**
|
||||
* 保存聊天记录
|
||||
* @param chatHistoryVO
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/2/22 13:37
|
||||
*/
|
||||
Result<?> saveHistory(ChatHistoryVO chatHistoryVO);
|
||||
|
||||
/**
|
||||
* 查询聊天记录
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/2/22 13:59
|
||||
*/
|
||||
Result<ChatHistoryVO> getHistoryByTopic();
|
||||
//update-end---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
}
|
||||
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@ -0,0 +1,199 @@
|
||||
package org.jeecg.modules.demo.gpt.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.unfbx.chatgpt.OpenAiStreamClient;
|
||||
import com.unfbx.chatgpt.entity.chat.ChatCompletion;
|
||||
import com.unfbx.chatgpt.entity.chat.Message;
|
||||
import com.unfbx.chatgpt.exception.BaseException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.UUIDGenerator;
|
||||
import org.jeecg.modules.demo.gpt.cache.LocalCache;
|
||||
import org.jeecg.modules.demo.gpt.listeners.OpenAISSEEventSourceListener;
|
||||
import org.jeecg.modules.demo.gpt.service.ChatService;
|
||||
import org.jeecg.modules.demo.gpt.vo.ChatHistoryVO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
|
||||
/**
|
||||
* AI助手聊天Service
|
||||
* @author chenrui
|
||||
* @date 2024/1/26 20:07
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ChatServiceImpl implements ChatService {
|
||||
|
||||
//update-begin---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
private static final String CACHE_KEY_PREFIX = "ai:chart:";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String CACHE_KEY_MSG_CONTEXT = "msg_content";
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String CACHE_KEY_MSG_HISTORY = "msg_history";
|
||||
|
||||
@Autowired
|
||||
RedisTemplate redisTemplate;
|
||||
//update-end---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
|
||||
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不能成功注入
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2024/2/3 23:08
|
||||
*/
|
||||
private OpenAiStreamClient ensureClient(){
|
||||
if(null == this.openAiStreamClient){
|
||||
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
|
||||
}
|
||||
return this.openAiStreamClient;
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240131 for:[QQYUN-8212]fix 没有配置启动报错------------
|
||||
|
||||
private String getUserId() {
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
return sysUser.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SseEmitter createChat() {
|
||||
String uid = getUserId();
|
||||
//默认30秒超时,设置为0L则永不超时
|
||||
SseEmitter sseEmitter = new SseEmitter(-0L);
|
||||
//完成后回调
|
||||
sseEmitter.onCompletion(() -> {
|
||||
log.info("[{}]结束连接...................",uid);
|
||||
LocalCache.CACHE.remove(uid);
|
||||
});
|
||||
//超时回调
|
||||
sseEmitter.onTimeout(() -> {
|
||||
log.info("[{}]连接超时...................", uid);
|
||||
});
|
||||
//异常回调
|
||||
sseEmitter.onError(
|
||||
throwable -> {
|
||||
try {
|
||||
log.info("[{}]连接异常,{}", uid, throwable.toString());
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id(uid)
|
||||
.name("发生异常!")
|
||||
.data(Message.builder().content("发生异常请重试!").build())
|
||||
.reconnectTime(3000));
|
||||
LocalCache.CACHE.put(uid, sseEmitter);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(),e);
|
||||
}
|
||||
}
|
||||
);
|
||||
try {
|
||||
sseEmitter.send(SseEmitter.event().reconnectTime(5000));
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(),e);
|
||||
}
|
||||
LocalCache.CACHE.put(uid, sseEmitter);
|
||||
log.info("[{}]创建sse连接成功!", uid);
|
||||
return sseEmitter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeChat() {
|
||||
String uid = getUserId();
|
||||
SseEmitter sse = (SseEmitter) LocalCache.CACHE.get(uid);
|
||||
if (sse != null) {
|
||||
sse.complete();
|
||||
//移除
|
||||
LocalCache.CACHE.remove(uid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String topicId, String message) {
|
||||
String uid = getUserId();
|
||||
if (StrUtil.isBlank(message)) {
|
||||
log.info("参数异常,message为null");
|
||||
throw new BaseException("参数异常,message不能为空~");
|
||||
}
|
||||
if (StrUtil.isBlank(topicId)) {
|
||||
topicId = UUIDGenerator.generate();
|
||||
}
|
||||
//update-begin---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
log.info("话题id:{}", topicId);
|
||||
String cacheKey = CACHE_KEY_PREFIX + uid + "_" + topicId;
|
||||
String messageContext = (String) redisTemplate.opsForHash().get(cacheKey, CACHE_KEY_MSG_CONTEXT);
|
||||
List<Message> msgHistory = new ArrayList<>();
|
||||
if (StrUtil.isNotBlank(messageContext)) {
|
||||
List<Message> messages = JSONArray.parseArray(messageContext, Message.class);
|
||||
msgHistory = messages == null ? new ArrayList<>() : messages;
|
||||
}
|
||||
Message currentMessage = Message.builder().content(message).role(Message.Role.USER).build();
|
||||
msgHistory.add(currentMessage);
|
||||
|
||||
SseEmitter sseEmitter = (SseEmitter) LocalCache.CACHE.get(uid);
|
||||
if (sseEmitter == null) {
|
||||
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:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
@Override
|
||||
public Result<?> saveHistory(ChatHistoryVO chatHistoryVO) {
|
||||
String uid = getUserId();
|
||||
String cacheKey = CACHE_KEY_PREFIX + CACHE_KEY_MSG_HISTORY + ":" + uid;
|
||||
redisTemplate.opsForValue().set(cacheKey, chatHistoryVO.getContent());
|
||||
return Result.OK("保存成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<ChatHistoryVO> getHistoryByTopic() {
|
||||
String uid = getUserId();
|
||||
String cacheKey = CACHE_KEY_PREFIX + CACHE_KEY_MSG_HISTORY + ":" + uid;
|
||||
String historyContent = (String) redisTemplate.opsForValue().get(cacheKey);
|
||||
ChatHistoryVO chatHistoryVO = new ChatHistoryVO();
|
||||
chatHistoryVO.setContent(historyContent);
|
||||
return Result.OK(chatHistoryVO);
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
}
|
||||
|
||||
//update-end---author:chenrui ---date:20240126 for:【QQYUN-7932】AI助手------------
|
||||
@ -0,0 +1,25 @@
|
||||
package org.jeecg.modules.demo.gpt.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Description: 聊天记录
|
||||
* @Author: chenrui
|
||||
* @Date: 2024/2/22 13:36
|
||||
*/
|
||||
@Data
|
||||
public class ChatHistoryVO implements Serializable {
|
||||
private static final long serialVersionUID = 3238429500037511283L;
|
||||
|
||||
/**
|
||||
* 话题id
|
||||
*/
|
||||
String topicId;
|
||||
|
||||
/**
|
||||
* 聊天记录内容
|
||||
*/
|
||||
String content;
|
||||
}
|
||||
@ -45,11 +45,11 @@ public class JeecgDemo extends JeecgEntity implements Serializable {
|
||||
private java.util.Date punchTime;
|
||||
/** 工资 */
|
||||
@ApiModelProperty(value = "工资",example = "0")
|
||||
@Excel(name="工资",width=15)
|
||||
@Excel(name="工资",type = 4,width=15)
|
||||
private java.math.BigDecimal salaryMoney;
|
||||
/** 奖金 */
|
||||
@ApiModelProperty(value = "奖金",example = "0")
|
||||
@Excel(name="奖金",width=15)
|
||||
@Excel(name="奖金",type = 4,width=15)
|
||||
private java.lang.Double bonusMoney;
|
||||
/** 性别 {男:1,女:2} */
|
||||
@ApiModelProperty(value = "性别")
|
||||
@ -57,7 +57,7 @@ public class JeecgDemo extends JeecgEntity implements Serializable {
|
||||
private java.lang.String sex;
|
||||
/** 年龄 */
|
||||
@ApiModelProperty(value = "年龄",example = "0")
|
||||
@Excel(name="年龄",width=15)
|
||||
@Excel(name="年龄",type = 4,width=15)
|
||||
private java.lang.Integer age;
|
||||
/** 生日 */
|
||||
@ApiModelProperty(value = "生日")
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>jeecg-system-api</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.6.3</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -94,6 +94,22 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
@GetMapping("/sys/api/getDepartIdsByUsername")
|
||||
List<String> getDepartIdsByUsername(@RequestParam("username") String username);
|
||||
|
||||
/**
|
||||
* 8.2 通过用户账号查询部门父ID集合
|
||||
* @param username
|
||||
* @return 部门 parentIds
|
||||
*/
|
||||
@GetMapping("/sys/api/getDepartParentIdsByUsername")
|
||||
Set<String> getDepartParentIdsByUsername(@RequestParam("username")String username);
|
||||
|
||||
/**
|
||||
* 8.3 查询部门父ID集合
|
||||
* @param depIds
|
||||
* @return 部门 parentIds
|
||||
*/
|
||||
@GetMapping("/sys/api/getDepartParentIdsByDepIds")
|
||||
Set<String> getDepartParentIdsByDepIds(@RequestParam("depIds") Set<String> depIds);
|
||||
|
||||
/**
|
||||
* 9通过用户账号查询部门 name
|
||||
* @param username
|
||||
@ -197,7 +213,7 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryAllUser")
|
||||
public JSONObject queryAllUser(@RequestParam(name="userIds",required=false)String userIds, @RequestParam(name="pageNo",required=false) Integer pageNo,@RequestParam(name="pageSize",required=false) int pageSize);
|
||||
public JSONObject queryAllUser(@RequestParam(name="userIds",required=false)String userIds, @RequestParam(name="pageNo",required=false) Integer pageNo,@RequestParam(name="pageSize",required=false) Integer pageSize);
|
||||
|
||||
|
||||
/**
|
||||
@ -291,11 +307,11 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
|
||||
/**
|
||||
* 31获取用户的权限集合
|
||||
* @param username
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/getUserPermissionSet")
|
||||
Set<String> getUserPermissionSet(@RequestParam("username") String username);
|
||||
Set<String> getUserPermissionSet(@RequestParam("userId") String userId);
|
||||
|
||||
/**
|
||||
* 32判断是否有online访问的权限
|
||||
@ -335,12 +351,12 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
|
||||
/**
|
||||
* 36查询用户权限信息
|
||||
* @param username
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/sys/api/queryUserAuths")
|
||||
Set<String> queryUserAuths(@RequestParam("username")String username);
|
||||
Set<String> queryUserAuths(@RequestParam("userId")String userId);
|
||||
|
||||
/**
|
||||
* 37根据 id 查询数据库中存储的 DynamicDataSourceModel
|
||||
@ -481,6 +497,14 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
@GetMapping("/sys/api/loadCategoryDictItem")
|
||||
List<String> loadCategoryDictItem(@RequestParam("ids") String ids);
|
||||
|
||||
/**
|
||||
* 44 反向翻译分类字典,用于导入
|
||||
*
|
||||
* @param names 名称,逗号分割
|
||||
*/
|
||||
@GetMapping("/sys/api/loadCategoryDictItemByNames")
|
||||
List<String> loadCategoryDictItemByNames(@RequestParam("names") String names, @RequestParam("delNotExist") boolean delNotExist);
|
||||
|
||||
/**
|
||||
* 43 根据字典code加载字典text
|
||||
*
|
||||
@ -551,17 +575,20 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
@GetMapping("/sys/api/translateManyDict")
|
||||
Map<String, List<DictModel>> translateManyDict(@RequestParam("dictCodes") String dictCodes, @RequestParam("keys") String keys);
|
||||
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
/**
|
||||
* 49 字典表的 翻译,可批量
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keys 多个用逗号分割
|
||||
* @param ds
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/sys/api/translateDictFromTableByKeys")
|
||||
List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys);
|
||||
List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys, @RequestParam("ds") String ds);
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
|
||||
/**
|
||||
* 发送模板消息
|
||||
@ -584,20 +611,6 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
@PostMapping("/sys/api/saveDataLog")
|
||||
void saveDataLog(DataLogDTO dataLogDto);
|
||||
|
||||
/**
|
||||
* 添加文件到知识库
|
||||
* @param sysFilesModel
|
||||
*/
|
||||
@PostMapping("/sys/api/addSysFiles")
|
||||
void addSysFiles(SysFilesModel sysFilesModel);
|
||||
|
||||
/**
|
||||
* 通过文件路径获取文件id
|
||||
* @param fileId
|
||||
*/
|
||||
@GetMapping("/sys/api/getFileUrl")
|
||||
String getFileUrl(@RequestParam(name="fileId") String fileId);
|
||||
|
||||
/**
|
||||
* 更新头像
|
||||
* @param loginUser
|
||||
@ -734,7 +747,7 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
@GetMapping("/sys/api/dictTableWhiteListCheckByDict")
|
||||
boolean dictTableWhiteListCheckByDict(
|
||||
@RequestParam("tableOrDictCode") String tableOrDictCode,
|
||||
@RequestParam(value = "fields", required = false) String[] fields
|
||||
@RequestParam(value = "fields", required = false) String... fields
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ -65,6 +65,16 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getDepartParentIdsByUsername(String username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getDepartParentIdsByDepIds(Set<String> depIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDepartNamesByUsername(String username) {
|
||||
return null;
|
||||
@ -123,7 +133,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject queryAllUser(String userIds, Integer pageNo, int pageSize) {
|
||||
public JSONObject queryAllUser(String userIds, Integer pageNo, Integer pageSize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -184,7 +194,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getUserPermissionSet(String username) {
|
||||
public Set<String> getUserPermissionSet(String userId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -209,7 +219,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> queryUserAuths(String username) {
|
||||
public Set<String> queryUserAuths(String userId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -275,10 +285,12 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
@Override
|
||||
public List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys) {
|
||||
public List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys, String dataSource) {
|
||||
return null;
|
||||
}
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
|
||||
@Override
|
||||
public void sendTemplateMessage(MessageDTO message) {
|
||||
@ -319,6 +331,11 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> loadCategoryDictItemByNames(String names, boolean delNotExist) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> loadDictItem(String dictCode, String keys) {
|
||||
return null;
|
||||
@ -344,17 +361,6 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addSysFiles(SysFilesModel sysFilesModel) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileUrl(String fileId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAvatar(LoginUser loginUser) { }
|
||||
|
||||
@ -429,7 +435,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dictTableWhiteListCheckByDict(String tableOrDictCode, String[] fields) {
|
||||
public boolean dictTableWhiteListCheckByDict(String tableOrDictCode, String... fields) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>jeecg-system-api</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.6.3</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -89,6 +89,20 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
*/
|
||||
List<String> getDepartIdsByUsername(String username);
|
||||
|
||||
/**
|
||||
* 8.2 通过用户账号查询部门父ID集合
|
||||
* @param username
|
||||
* @return 部门 parentIds
|
||||
*/
|
||||
Set<String> getDepartParentIdsByUsername(String username);
|
||||
|
||||
/**
|
||||
* 8.2 查询部门父ID集合
|
||||
* @param depIds
|
||||
* @return 部门 parentIds
|
||||
*/
|
||||
Set<String> getDepartParentIdsByDepIds(Set<String> depIds);
|
||||
|
||||
/**
|
||||
* 9通过用户账号查询部门 name
|
||||
* @param username
|
||||
@ -288,10 +302,10 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
|
||||
/**
|
||||
* 32获取用户的权限集合
|
||||
* @param username
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
Set<String> getUserPermissionSet(String username);
|
||||
Set<String> getUserPermissionSet(String userId);
|
||||
|
||||
/**
|
||||
* 33判断是否有online访问的权限
|
||||
@ -373,6 +387,13 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
*/
|
||||
List<String> loadCategoryDictItem(String ids);
|
||||
|
||||
/**
|
||||
* 反向翻译分类字典,用于导入
|
||||
*
|
||||
* @param names 名称,逗号分割
|
||||
*/
|
||||
List<String> loadCategoryDictItemByNames(String names, boolean delNotExist);
|
||||
|
||||
/**
|
||||
* 根据字典code加载字典text
|
||||
*
|
||||
@ -424,19 +445,6 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
* @param dataLogDto
|
||||
*/
|
||||
void saveDataLog(DataLogDTO dataLogDto);
|
||||
|
||||
/**
|
||||
* 添加文件到知识库
|
||||
* @param sysFilesModel
|
||||
*/
|
||||
void addSysFiles(SysFilesModel sysFilesModel);
|
||||
|
||||
/**
|
||||
* 通过文件路径获取文件id
|
||||
* @param fileId
|
||||
*/
|
||||
String getFileUrl(String fileId);
|
||||
|
||||
/**
|
||||
* 更新头像
|
||||
* @param loginUser
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>jeecg-module-system</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.6.3</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-module-system</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.6.3</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -29,15 +29,15 @@
|
||||
<groupId>org.jeecgframework</groupId>
|
||||
<artifactId>jeewx-api</artifactId>
|
||||
</dependency>
|
||||
<!-- 积木报表 -->
|
||||
<!-- 积木报表设计 -->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.jimureport</groupId>
|
||||
<artifactId>jimureport-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- 积木仪表盘 -->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>drag-free</artifactId>
|
||||
<version>1.0.2</version>
|
||||
<groupId>org.jeecgframework.jimureport</groupId>
|
||||
<artifactId>jimureport-drag</artifactId>
|
||||
</dependency>
|
||||
<!-- 积木报表 mongo redis 支持包
|
||||
<dependency>
|
||||
|
||||
@ -100,8 +100,8 @@ public class DictTableWhiteListHandlerImpl implements IDictTableWhiteListHandler
|
||||
// 针对转义字符进行解码
|
||||
dictCodeString = URLDecoder.decode(dictCodeString, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
this.throwException("字典code解码失败,可能是使用了非法字符,请检查!");
|
||||
log.warn(e.getMessage());
|
||||
//this.throwException("字典code解码失败,可能是使用了非法字符,请检查!");
|
||||
}
|
||||
dictCodeString = dictCodeString.trim();
|
||||
String[] arr = dictCodeString.split(SymbolConstant.COMMA);
|
||||
|
||||
@ -140,6 +140,26 @@ public class SystemApiController {
|
||||
return sysBaseApi.getDepartIdsByUsername(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户账号查询部门父ID集合
|
||||
* @param username
|
||||
* @return 部门 id
|
||||
*/
|
||||
@GetMapping("/getDepartParentIdsByUsername")
|
||||
Set<String> getDepartParentIdsByUsername(@RequestParam("username") String username){
|
||||
return sysBaseApi.getDepartParentIdsByUsername(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部门父ID集合
|
||||
* @param depIds
|
||||
* @return 部门 id
|
||||
*/
|
||||
@GetMapping("/getDepartParentIdsByDepIds")
|
||||
Set<String> getDepartParentIdsByDepIds(@RequestParam("depIds") Set<String> depIds){
|
||||
return sysBaseApi.getDepartParentIdsByDepIds(depIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户账号查询部门 name
|
||||
* @param username
|
||||
@ -327,7 +347,7 @@ public class SystemApiController {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryAllUser")
|
||||
public JSONObject queryAllUser(@RequestParam(name="userIds",required=false)String userIds, @RequestParam(name="pageNo",required=false) Integer pageNo,@RequestParam(name="pageSize",required=false) int pageSize){
|
||||
public JSONObject queryAllUser(@RequestParam(name="userIds",required=false)String userIds, @RequestParam(name="pageNo",required=false) Integer pageNo,@RequestParam(name="pageSize",required=false) Integer pageSize){
|
||||
return sysBaseApi.queryAllUser(userIds, pageNo, pageSize);
|
||||
}
|
||||
|
||||
@ -366,12 +386,12 @@ public class SystemApiController {
|
||||
|
||||
/**
|
||||
* 获取用户的权限集合
|
||||
* @param username
|
||||
* @param userId 用户表ID
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/getUserPermissionSet")
|
||||
public Set<String> getUserPermissionSet(@RequestParam("username") String username){
|
||||
return sysBaseApi.getUserPermissionSet(username);
|
||||
public Set<String> getUserPermissionSet(@RequestParam("userId") String userId){
|
||||
return sysBaseApi.getUserPermissionSet(userId);
|
||||
}
|
||||
|
||||
//-----
|
||||
@ -399,12 +419,12 @@ public class SystemApiController {
|
||||
|
||||
/**
|
||||
* 查询用户权限信息
|
||||
* @param username
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/queryUserAuths")
|
||||
public Set<String> queryUserAuths(@RequestParam("username") String username){
|
||||
return sysUserService.getUserPermissionsSet(username);
|
||||
public Set<String> queryUserAuths(@RequestParam("userId") String userId){
|
||||
return sysUserService.getUserPermissionsSet(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -527,6 +547,17 @@ public class SystemApiController {
|
||||
return sysBaseApi.loadCategoryDictItem(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 反向翻译分类字典,用于导入
|
||||
*
|
||||
* @param names 名称,逗号分割
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/loadCategoryDictItemByNames")
|
||||
List<String> loadCategoryDictItemByNames(@RequestParam("names") String names, @RequestParam("delNotExist") boolean delNotExist) {
|
||||
return sysBaseApi.loadCategoryDictItemByNames(names, delNotExist);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典code加载字典text
|
||||
*
|
||||
@ -547,7 +578,7 @@ public class SystemApiController {
|
||||
* @param tenantId 新的租户ID
|
||||
* @return Map<String, String> Map<原字典编码, 新字典编码>
|
||||
*/
|
||||
@GetMapping("/sys/api/copyLowAppDict")
|
||||
@GetMapping("/copyLowAppDict")
|
||||
Map<String, String> copyLowAppDict(@RequestParam("originalAppId") String originalAppId, @RequestParam("appId") String appId, @RequestParam("tenantId") String tenantId) {
|
||||
return sysBaseApi.copyLowAppDict(originalAppId, appId, tenantId);
|
||||
}
|
||||
@ -655,6 +686,7 @@ public class SystemApiController {
|
||||
}
|
||||
|
||||
|
||||
//update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
/**
|
||||
* 【接口签名验证】
|
||||
* 49 字典表的 翻译,可批量
|
||||
@ -663,12 +695,14 @@ public class SystemApiController {
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keys 多个用逗号分割
|
||||
* @param ds 数据源
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/translateDictFromTableByKeys")
|
||||
public List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys) {
|
||||
return this.sysBaseApi.translateDictFromTableByKeys(table, text, code, keys);
|
||||
public List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys, @RequestParam("ds") String ds) {
|
||||
return this.sysBaseApi.translateDictFromTableByKeys(table, text, code, keys, ds);
|
||||
}
|
||||
//update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------
|
||||
|
||||
/**
|
||||
* 发送模板信息
|
||||
@ -698,14 +732,6 @@ public class SystemApiController {
|
||||
this.sysBaseApi.saveDataLog(dataLogDto);
|
||||
}
|
||||
|
||||
@PostMapping("/addSysFiles")
|
||||
public void addSysFiles(@RequestBody SysFilesModel sysFilesModel){this.sysBaseApi.addSysFiles(sysFilesModel);}
|
||||
|
||||
@GetMapping("/getFileUrl")
|
||||
public String getFileUrl(@RequestParam(name="fileId") String fileId){
|
||||
return this.sysBaseApi.getFileUrl(fileId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新头像
|
||||
* @param loginUser
|
||||
@ -824,7 +850,7 @@ public class SystemApiController {
|
||||
* @param deptIds
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryUserIdsByDeptIds")
|
||||
@GetMapping("/queryUserIdsByDeptIds")
|
||||
public List<String> queryUserIdsByDeptIds(@RequestParam("deptIds") List<String> deptIds){
|
||||
return sysBaseApi.queryUserIdsByDeptIds(deptIds);
|
||||
}
|
||||
@ -834,7 +860,7 @@ public class SystemApiController {
|
||||
* @param deptIds
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryUserAccountsByDeptIds")
|
||||
@GetMapping("/queryUserAccountsByDeptIds")
|
||||
public List<String> queryUserAccountsByDeptIds(@RequestParam("deptIds") List<String> deptIds){
|
||||
return sysBaseApi.queryUserAccountsByDeptIds(deptIds);
|
||||
}
|
||||
@ -844,7 +870,7 @@ public class SystemApiController {
|
||||
* @param roleCodes
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryUserIdsByRoleds")
|
||||
@GetMapping("/queryUserIdsByRoleds")
|
||||
public List<String> queryUserIdsByRoleds(@RequestParam("roleCodes") List<String> roleCodes){
|
||||
return sysBaseApi.queryUserIdsByRoleds(roleCodes);
|
||||
}
|
||||
@ -854,7 +880,7 @@ public class SystemApiController {
|
||||
* @param positionIds
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryUserIdsByPositionIds")
|
||||
@GetMapping("/queryUserIdsByPositionIds")
|
||||
public List<String> queryUserIdsByPositionIds(@RequestParam("positionIds") List<String> positionIds){
|
||||
return sysBaseApi.queryUserIdsByPositionIds(positionIds);
|
||||
}
|
||||
@ -866,7 +892,7 @@ public class SystemApiController {
|
||||
* @param orgCode 部门编码
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/getUserAccountsByDepCode")
|
||||
@GetMapping("/getUserAccountsByDepCode")
|
||||
public List<String> getUserAccountsByDepCode(String orgCode){
|
||||
return sysBaseApi.getUserAccountsByDepCode(orgCode);
|
||||
}
|
||||
@ -877,7 +903,7 @@ public class SystemApiController {
|
||||
* @param selectSql
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/dictTableWhiteListCheckBySql")
|
||||
@GetMapping("/dictTableWhiteListCheckBySql")
|
||||
public boolean dictTableWhiteListCheckBySql(@RequestParam("selectSql") String selectSql) {
|
||||
return sysBaseApi.dictTableWhiteListCheckBySql(selectSql);
|
||||
}
|
||||
@ -889,10 +915,10 @@ public class SystemApiController {
|
||||
* @param fields 如果传的是dictCode,则该参数必须传null
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/dictTableWhiteListCheckByDict")
|
||||
@GetMapping("/dictTableWhiteListCheckByDict")
|
||||
public boolean dictTableWhiteListCheckByDict(
|
||||
@RequestParam("tableOrDictCode") String tableOrDictCode,
|
||||
@RequestParam(value = "fields", required = false) String[] fields
|
||||
@RequestParam(value = "fields", required = false) String... fields
|
||||
) {
|
||||
return sysBaseApi.dictTableWhiteListCheckByDict(tableOrDictCode, fields);
|
||||
}
|
||||
|
||||
@ -79,6 +79,7 @@ public enum RangeDateEnum {
|
||||
//本周
|
||||
calendar1.set(Calendar.DAY_OF_WEEK, 2);
|
||||
|
||||
calendar2.set(Calendar.DAY_OF_WEEK,2);
|
||||
calendar2.add(Calendar.WEEK_OF_MONTH,1);
|
||||
calendar2.add(Calendar.DAY_OF_WEEK,-1);
|
||||
} else if(SZ.key.equals(key)){
|
||||
|
||||
@ -79,7 +79,7 @@ public class QuartzJobController {
|
||||
* @param quartzJob
|
||||
* @return
|
||||
*/
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:add")
|
||||
@RequestMapping(value = "/add", method = RequestMethod.POST)
|
||||
public Result<?> add(@RequestBody QuartzJob quartzJob) {
|
||||
@ -93,7 +93,7 @@ public class QuartzJobController {
|
||||
* @param quartzJob
|
||||
* @return
|
||||
*/
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:edit")
|
||||
@RequestMapping(value = "/edit", method ={RequestMethod.PUT, RequestMethod.POST})
|
||||
public Result<?> eidt(@RequestBody QuartzJob quartzJob) {
|
||||
@ -112,7 +112,7 @@ public class QuartzJobController {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:delete")
|
||||
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
|
||||
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
|
||||
@ -131,7 +131,7 @@ public class QuartzJobController {
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:deleteBatch")
|
||||
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
|
||||
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
|
||||
@ -151,7 +151,7 @@ public class QuartzJobController {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:pause")
|
||||
@GetMapping(value = "/pause")
|
||||
@ApiOperation(value = "停止定时任务")
|
||||
@ -170,7 +170,7 @@ public class QuartzJobController {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:resume")
|
||||
@GetMapping(value = "/resume")
|
||||
@ApiOperation(value = "启动定时任务")
|
||||
@ -271,7 +271,7 @@ public class QuartzJobController {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@RequiresPermissions("system:quartzJob:execute")
|
||||
@GetMapping("/execute")
|
||||
public Result<?> execute(@RequestParam(name = "id", required = true) String id) {
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
package org.jeecg.modules.system.constant;
|
||||
|
||||
/**
|
||||
* 默认首页常量
|
||||
*/
|
||||
public interface DefIndexConst {
|
||||
|
||||
/**
|
||||
* 默认首页的roleCode
|
||||
*/
|
||||
String DEF_INDEX_ALL = "DEF_INDEX_ALL";
|
||||
|
||||
/**
|
||||
* 默认首页的缓存key
|
||||
*/
|
||||
String CACHE_KEY = "sys:cache:def_index";
|
||||
|
||||
/**
|
||||
* 默认首页的初始值
|
||||
*/
|
||||
String DEF_INDEX_NAME = "首页";
|
||||
String DEF_INDEX_URL = "/dashboard/analysis";
|
||||
String DEF_INDEX_COMPONENT = "dashboard/Analysis";
|
||||
|
||||
}
|
||||
@ -9,8 +9,6 @@ import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.util.CommonUtils;
|
||||
import org.jeecg.common.util.filter.SsrfFileTypeFilter;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.system.service.ISysFilesService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
@ -72,32 +72,24 @@ public class LoginController {
|
||||
|
||||
@ApiOperation("登录接口")
|
||||
@RequestMapping(value = "/login", method = RequestMethod.POST)
|
||||
public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel){
|
||||
public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel, HttpServletRequest request){
|
||||
Result<JSONObject> result = new Result<JSONObject>();
|
||||
String username = sysLoginModel.getUsername();
|
||||
String password = sysLoginModel.getPassword();
|
||||
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
|
||||
if(isLoginFailOvertimes(username)){
|
||||
return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!");
|
||||
}
|
||||
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
|
||||
//update-begin--Author:scott Date:20190805 for:暂时注释掉密码加密逻辑,有点问题
|
||||
//前端密码加密,后端进行密码解密
|
||||
//password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim();//密码解密
|
||||
//update-begin--Author:scott Date:20190805 for:暂时注释掉密码加密逻辑,有点问题
|
||||
|
||||
//update-begin-author:taoyan date:20190828 for:校验验证码
|
||||
// step.1 验证码check
|
||||
String captcha = sysLoginModel.getCaptcha();
|
||||
if(captcha==null){
|
||||
result.error500("验证码无效");
|
||||
return result;
|
||||
}
|
||||
String lowerCaseCaptcha = captcha.toLowerCase();
|
||||
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
|
||||
// 加入密钥作为混淆,避免简单的拼接,被外部利用,用户自定义该密钥即可
|
||||
String origin = lowerCaseCaptcha+sysLoginModel.getCheckKey()+jeecgBaseConfig.getSignatureSecret();
|
||||
String realKey = Md5Util.md5Encode(origin, "utf-8");
|
||||
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
|
||||
Object checkCode = redisUtil.get(realKey);
|
||||
//当进入登录页时,有一定几率出现验证码错误 #1714
|
||||
if(checkCode==null || !checkCode.toString().equals(lowerCaseCaptcha)) {
|
||||
@ -107,40 +99,36 @@ public class LoginController {
|
||||
result.setCode(HttpStatus.PRECONDITION_FAILED.value());
|
||||
return result;
|
||||
}
|
||||
//update-end-author:taoyan date:20190828 for:校验验证码
|
||||
|
||||
//1. 校验用户是否有效
|
||||
//update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false
|
||||
// step.2 校验用户是否存在且有效
|
||||
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysUser::getUsername,username);
|
||||
SysUser sysUser = sysUserService.getOne(queryWrapper);
|
||||
//update-end-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false
|
||||
result = sysUserService.checkUserIsEffective(sysUser);
|
||||
if(!result.isSuccess()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//2. 校验用户名或密码是否正确
|
||||
// step.3 校验用户名或密码是否正确
|
||||
String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
|
||||
String syspassword = sysUser.getPassword();
|
||||
if (!syspassword.equals(userpassword)) {
|
||||
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
|
||||
addLoginFailOvertimes(username);
|
||||
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
|
||||
result.error500("用户名或密码错误");
|
||||
return result;
|
||||
}
|
||||
|
||||
//用户登录信息
|
||||
userInfo(sysUser, result);
|
||||
//update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码
|
||||
|
||||
// step.4 登录成功获取用户信息
|
||||
userInfo(sysUser, result, request);
|
||||
|
||||
// step.5 登录成功删除验证码
|
||||
redisUtil.del(realKey);
|
||||
//update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码
|
||||
redisUtil.del(CommonConstant.LOGIN_FAIL + username);
|
||||
|
||||
// step.6 记录用户登录日志
|
||||
LoginUser loginUser = new LoginUser();
|
||||
BeanUtils.copyProperties(sysUser, loginUser);
|
||||
baseCommonService.addLog("用户名: " + username + ",登录成功!", CommonConstant.LOG_TYPE_1, null,loginUser);
|
||||
//update-end--Author:wangshuai Date:20200714 for:登录日志没有记录人员
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -150,18 +138,20 @@ public class LoginController {
|
||||
*/
|
||||
@GetMapping("/user/getUserInfo")
|
||||
public Result<JSONObject> getUserInfo(HttpServletRequest request){
|
||||
long start = System.currentTimeMillis();
|
||||
Result<JSONObject> result = new Result<JSONObject>();
|
||||
String username = JwtUtil.getUserNameByToken(request);
|
||||
if(oConvertUtils.isNotEmpty(username)) {
|
||||
// 根据用户名查询用户信息
|
||||
SysUser sysUser = sysUserService.getUserByName(username);
|
||||
JSONObject obj=new JSONObject();
|
||||
log.info("1 获取用户信息耗时(用户基础信息)" + (System.currentTimeMillis() - start) + "毫秒");
|
||||
|
||||
//update-begin---author:scott ---date:2022-06-20 for:vue3前端,支持自定义首页-----------
|
||||
String version = request.getHeader(CommonConstant.VERSION);
|
||||
String vue3Version = request.getHeader(CommonConstant.VERSION);
|
||||
//update-begin---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑-----------
|
||||
SysRoleIndex roleIndex = sysUserService.getDynamicIndexByUserRole(username, version);
|
||||
if (oConvertUtils.isNotEmpty(version) && roleIndex != null && oConvertUtils.isNotEmpty(roleIndex.getUrl())) {
|
||||
SysRoleIndex roleIndex = sysUserService.getDynamicIndexByUserRole(username, vue3Version);
|
||||
if (oConvertUtils.isNotEmpty(vue3Version) && roleIndex != null && oConvertUtils.isNotEmpty(roleIndex.getUrl())) {
|
||||
String homePath = roleIndex.getUrl();
|
||||
if (!homePath.startsWith(SymbolConstant.SINGLE_SLASH)) {
|
||||
homePath = SymbolConstant.SINGLE_SLASH + homePath;
|
||||
@ -170,12 +160,16 @@ public class LoginController {
|
||||
}
|
||||
//update-begin---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑-----------
|
||||
//update-end---author:scott ---date::2022-06-20 for:vue3前端,支持自定义首页--------------
|
||||
log.info("2 获取用户信息耗时 (首页面配置)" + (System.currentTimeMillis() - start) + "毫秒");
|
||||
|
||||
obj.put("userInfo",sysUser);
|
||||
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
|
||||
log.info("3 获取用户信息耗时 (字典数据)" + (System.currentTimeMillis() - start) + "毫秒");
|
||||
|
||||
result.setResult(obj);
|
||||
result.success("");
|
||||
}
|
||||
log.info("end 获取用户信息耗时 " + (System.currentTimeMillis() - start) + "毫秒");
|
||||
return result;
|
||||
|
||||
}
|
||||
@ -397,7 +391,7 @@ public class LoginController {
|
||||
*/
|
||||
@ApiOperation("手机号登录接口")
|
||||
@PostMapping("/phoneLogin")
|
||||
public Result<JSONObject> phoneLogin(@RequestBody JSONObject jsonObject) {
|
||||
public Result<JSONObject> phoneLogin(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
|
||||
Result<JSONObject> result = new Result<JSONObject>();
|
||||
String phone = jsonObject.getString("mobile");
|
||||
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
|
||||
@ -423,11 +417,10 @@ public class LoginController {
|
||||
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
|
||||
addLoginFailOvertimes(phone);
|
||||
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
|
||||
result.setMessage("手机验证码错误");
|
||||
return result;
|
||||
return Result.error("手机验证码错误");
|
||||
}
|
||||
//用户信息
|
||||
userInfo(sysUser, result);
|
||||
userInfo(sysUser, result, request);
|
||||
//添加日志
|
||||
baseCommonService.addLog("用户名: " + sysUser.getUsername() + ",登录成功!", CommonConstant.LOG_TYPE_1, null);
|
||||
|
||||
@ -442,7 +435,7 @@ public class LoginController {
|
||||
* @param result
|
||||
* @return
|
||||
*/
|
||||
private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
|
||||
private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result, HttpServletRequest request) {
|
||||
String username = sysUser.getUsername();
|
||||
String syspassword = sysUser.getPassword();
|
||||
// 获取用户部门信息
|
||||
@ -482,7 +475,15 @@ public class LoginController {
|
||||
// update-end--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去
|
||||
obj.put("multi_depart", 2);
|
||||
}
|
||||
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
|
||||
|
||||
//update-begin---author:scott ---date:2024-01-05 for:【QQYUN-7802】前端在登录时加载了两次数据字典,建议优化下,避免数据字典太多时可能产生的性能问题 #956---
|
||||
// login接口,在vue3前端下不加载字典数据,vue2下加载字典
|
||||
String vue3Version = request.getHeader(CommonConstant.VERSION);
|
||||
if(oConvertUtils.isEmpty(vue3Version)){
|
||||
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
|
||||
}
|
||||
//end-begin---author:scott ---date:2024-01-05 for:【QQYUN-7802】前端在登录时加载了两次数据字典,建议优化下,避免数据字典太多时可能产生的性能问题 #956---
|
||||
|
||||
result.setResult(obj);
|
||||
result.success("登录成功");
|
||||
return result;
|
||||
@ -543,7 +544,7 @@ public class LoginController {
|
||||
@RequiresRoles({"admin"})
|
||||
@GetMapping(value = "/switchVue3Menu")
|
||||
public Result<String> switchVue3Menu(HttpServletResponse response) {
|
||||
Result<String> res = new Result<String>();
|
||||
Result<String> res = new Result<String>();
|
||||
sysPermissionService.switchVue3Menu();
|
||||
return res;
|
||||
}
|
||||
@ -588,10 +589,12 @@ public class LoginController {
|
||||
String orgCode = sysUser.getOrgCode();
|
||||
if(oConvertUtils.isEmpty(orgCode)) {
|
||||
//如果当前用户无选择部门 查看部门关联信息
|
||||
|
||||
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
|
||||
//update-begin-author:taoyan date:20220117 for: JTC-1068【app】新建用户,没有设置部门及角色,点击登录提示暂未归属部,一直在登录页面 使用手机号登录 可正常
|
||||
if (departs == null || departs.size() == 0) {
|
||||
/*result.error500("用户暂未归属部门,不可登录!");
|
||||
|
||||
return result;*/
|
||||
}else{
|
||||
orgCode = departs.get(0).getOrgCode();
|
||||
@ -727,8 +730,8 @@ public class LoginController {
|
||||
if(failTime!=null){
|
||||
val = Integer.parseInt(failTime.toString());
|
||||
}
|
||||
// 10分钟
|
||||
redisUtil.set(key, ++val, 10);
|
||||
// 10分钟,一分钟为60s
|
||||
redisUtil.set(key, ++val, 600);
|
||||
}
|
||||
|
||||
}
|
||||
@ -333,6 +333,7 @@ public class SysAnnouncementController {
|
||||
*/
|
||||
@RequestMapping(value = "/listByUser", method = RequestMethod.GET)
|
||||
public Result<Map<String, Object>> listByUser(@RequestParam(required = false, defaultValue = "5") Integer pageSize) {
|
||||
long start = System.currentTimeMillis();
|
||||
Result<Map<String,Object>> result = new Result<Map<String,Object>>();
|
||||
Map<String,Object> sysMsgMap = new HashMap(5);
|
||||
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
|
||||
@ -349,12 +350,16 @@ public class SysAnnouncementController {
|
||||
anntMsgList = sysAnnouncementService.querySysCementPageByUserId(anntMsgList,userId,"1");
|
||||
sysMsgMap.put("anntMsgList", anntMsgList.getRecords());
|
||||
sysMsgMap.put("anntMsgTotal", anntMsgList.getTotal());
|
||||
|
||||
log.info("begin 获取用户系统公告 (通知)" + (System.currentTimeMillis() - start) + "毫秒");
|
||||
|
||||
//系统消息
|
||||
Page<SysAnnouncement> sysMsgList = new Page<SysAnnouncement>(0, pageSize);
|
||||
sysMsgList = sysAnnouncementService.querySysCementPageByUserId(sysMsgList,userId,"2");
|
||||
sysMsgMap.put("sysMsgList", sysMsgList.getRecords());
|
||||
sysMsgMap.put("sysMsgTotal", sysMsgList.getTotal());
|
||||
|
||||
log.info("end 获取用户系统公告 (系统消息)" + (System.currentTimeMillis() - start) + "毫秒");
|
||||
|
||||
result.setSuccess(true);
|
||||
result.setResult(sysMsgMap);
|
||||
|
||||
@ -25,6 +25,7 @@ import org.jeecg.modules.system.model.SysDepartTreeModel;
|
||||
import org.jeecg.modules.system.service.ISysDepartService;
|
||||
import org.jeecg.modules.system.service.ISysUserDepartService;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import org.jeecg.modules.system.vo.SysDepartExportVo;
|
||||
import org.jeecg.modules.system.vo.lowapp.ExportDepartVo;
|
||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||
@ -350,25 +351,35 @@ public class SysDepartController {
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
|
||||
// Step.1 组装查询条件
|
||||
QueryWrapper<SysDepart> queryWrapper = QueryGenerator.initQueryWrapper(sysDepart, request.getParameterMap());
|
||||
//Step.2 AutoPoi 导出Excel
|
||||
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
|
||||
List<SysDepart> pageList = sysDepartService.list(queryWrapper);
|
||||
//update-begin---author:wangshuai---date:2023-10-19---for:【QQYUN-5482】系统的部门导入导出也可以改成敲敲云模式的部门路径---
|
||||
//// Step.1 组装查询条件
|
||||
//QueryWrapper<SysDepart> queryWrapper = QueryGenerator.initQueryWrapper(sysDepart, request.getParameterMap());
|
||||
//Step.1 AutoPoi 导出Excel
|
||||
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
|
||||
//List<SysDepart> pageList = sysDepartService.list(queryWrapper);
|
||||
//按字典排序
|
||||
Collections.sort(pageList, new Comparator<SysDepart>() {
|
||||
@Override
|
||||
public int compare(SysDepart arg0, SysDepart arg1) {
|
||||
return arg0.getOrgCode().compareTo(arg1.getOrgCode());
|
||||
}
|
||||
});
|
||||
//Collections.sort(pageList, new Comparator<SysDepart>() {
|
||||
//@Override
|
||||
//public int compare(SysDepart arg0, SysDepart arg1) {
|
||||
//return arg0.getOrgCode().compareTo(arg1.getOrgCode());
|
||||
//}
|
||||
//});
|
||||
//step.2 组装导出数据
|
||||
Integer tenantId = sysDepart == null ? null : sysDepart.getTenantId();
|
||||
List<SysDepartExportVo> sysDepartExportVos = sysDepartService.getExportDepart(tenantId);
|
||||
//导出文件名称
|
||||
mv.addObject(NormalExcelConstants.FILE_NAME, "部门列表");
|
||||
mv.addObject(NormalExcelConstants.CLASS, SysDepart.class);
|
||||
mv.addObject(NormalExcelConstants.CLASS, SysDepartExportVo.class);
|
||||
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("部门列表数据", "导出人:"+user.getRealname(), "导出信息"));
|
||||
mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
|
||||
return mv;
|
||||
mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("导入规则:\n" +
|
||||
"1、标题为第三行,部门路径和部门名称的标题不允许修改,否则会匹配失败;第四行为数据填写范围;\n" +
|
||||
"2、部门路径用英文字符/分割,部门名称为部门路径的最后一位;\n" +
|
||||
"3、部门从一级名称开始创建,如果有同级就需要多添加一行,如研发部/研发一部;研发部/研发二部;\n" +
|
||||
"4、自定义的部门编码需要满足规则才能导入。如一级部门编码为A01,那么子部门为A01A01,同级子部门为A01A02,编码固定为三位,首字母为A-Z,后两位为数字0-99,依次递增;", "导出人:"+user.getRealname(), "导出信息"));
|
||||
mv.addObject(NormalExcelConstants.DATA_LIST, sysDepartExportVos);
|
||||
//update-end---author:wangshuai---date:2023-10-19---for:【QQYUN-5482】系统的部门导入导出也可以改成敲敲云模式的部门路径---
|
||||
|
||||
return mv;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -386,7 +397,8 @@ public class SysDepartController {
|
||||
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
|
||||
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
|
||||
List<String> errorMessageList = new ArrayList<>();
|
||||
List<SysDepart> listSysDeparts = null;
|
||||
//List<SysDepart> listSysDeparts = null;
|
||||
List<SysDepartExportVo> listSysDeparts = null;
|
||||
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
|
||||
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
|
||||
// 获取上传文件对象
|
||||
@ -396,51 +408,59 @@ public class SysDepartController {
|
||||
params.setHeadRows(1);
|
||||
params.setNeedSave(true);
|
||||
try {
|
||||
// orgCode编码长度
|
||||
int codeLength = YouBianCodeUtil.ZHANWEI_LENGTH;
|
||||
listSysDeparts = ExcelImportUtil.importExcel(file.getInputStream(), SysDepart.class, params);
|
||||
//按长度排序
|
||||
Collections.sort(listSysDeparts, new Comparator<SysDepart>() {
|
||||
@Override
|
||||
public int compare(SysDepart arg0, SysDepart arg1) {
|
||||
return arg0.getOrgCode().length() - arg1.getOrgCode().length();
|
||||
}
|
||||
});
|
||||
|
||||
int num = 0;
|
||||
for (SysDepart sysDepart : listSysDeparts) {
|
||||
String orgCode = sysDepart.getOrgCode();
|
||||
if(orgCode.length() > codeLength) {
|
||||
String parentCode = orgCode.substring(0, orgCode.length()-codeLength);
|
||||
QueryWrapper<SysDepart> queryWrapper = new QueryWrapper<SysDepart>();
|
||||
queryWrapper.eq("org_code", parentCode);
|
||||
try {
|
||||
SysDepart parentDept = sysDepartService.getOne(queryWrapper);
|
||||
if(!parentDept.equals(null)) {
|
||||
sysDepart.setParentId(parentDept.getId());
|
||||
//更新父级部门不是叶子结点
|
||||
sysDepartService.updateIzLeaf(parentDept.getId(),CommonConstant.NOT_LEAF);
|
||||
} else {
|
||||
sysDepart.setParentId("");
|
||||
}
|
||||
}catch (Exception e) {
|
||||
//没有查找到parentDept
|
||||
}
|
||||
}else{
|
||||
sysDepart.setParentId("");
|
||||
}
|
||||
//update-begin---author:liusq Date:20210223 for:批量导入部门以后,不能追加下一级部门 #2245------------
|
||||
sysDepart.setOrgType(sysDepart.getOrgCode().length()/codeLength+"");
|
||||
//update-end---author:liusq Date:20210223 for:批量导入部门以后,不能追加下一级部门 #2245------------
|
||||
sysDepart.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
|
||||
//update-begin---author:wangshuai ---date:20220105 for:[JTC-363]部门导入 机构类别没有时导入失败,赋默认值------------
|
||||
if(oConvertUtils.isEmpty(sysDepart.getOrgCategory())){
|
||||
sysDepart.setOrgCategory("1");
|
||||
}
|
||||
//update-end---author:wangshuai ---date:20220105 for:[JTC-363]部门导入 机构类别没有时导入失败,赋默认值------------
|
||||
ImportExcelUtil.importDateSaveOne(sysDepart, ISysDepartService.class, errorMessageList, num, CommonConstant.SQL_INDEX_UNIQ_DEPART_ORG_CODE);
|
||||
num++;
|
||||
}
|
||||
//update-begin---author:wangshuai---date:2023-10-20---for: 注释掉原来的导入部门的逻辑---
|
||||
// // orgCode编码长度
|
||||
// int codeLength = YouBianCodeUtil.ZHANWEI_LENGTH;
|
||||
// listSysDeparts = ExcelImportUtil.importExcel(file.getInputStream(), SysDepart.class, params);
|
||||
// //按长度排序
|
||||
// Collections.sort(listSysDeparts, new Comparator<SysDepart>() {
|
||||
// @Override
|
||||
// public int compare(SysDepart arg0, SysDepart arg1) {
|
||||
// return arg0.getOrgCode().length() - arg1.getOrgCode().length();
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// int num = 0;
|
||||
// for (SysDepart sysDepart : listSysDeparts) {
|
||||
// String orgCode = sysDepart.getOrgCode();
|
||||
// if(orgCode.length() > codeLength) {
|
||||
// String parentCode = orgCode.substring(0, orgCode.length()-codeLength);
|
||||
// QueryWrapper<SysDepart> queryWrapper = new QueryWrapper<SysDepart>();
|
||||
// queryWrapper.eq("org_code", parentCode);
|
||||
// try {
|
||||
// SysDepart parentDept = sysDepartService.getOne(queryWrapper);
|
||||
// if(!parentDept.equals(null)) {
|
||||
// sysDepart.setParentId(parentDept.getId());
|
||||
// //更新父级部门不是叶子结点
|
||||
// sysDepartService.updateIzLeaf(parentDept.getId(),CommonConstant.NOT_LEAF);
|
||||
// } else {
|
||||
// sysDepart.setParentId("");
|
||||
// }
|
||||
// }catch (Exception e) {
|
||||
// //没有查找到parentDept
|
||||
// }
|
||||
// }else{
|
||||
// sysDepart.setParentId("");
|
||||
// }
|
||||
// //update-begin---author:liusq Date:20210223 for:批量导入部门以后,不能追加下一级部门 #2245------------
|
||||
// sysDepart.setOrgType(sysDepart.getOrgCode().length()/codeLength+"");
|
||||
// //update-end---author:liusq Date:20210223 for:批量导入部门以后,不能追加下一级部门 #2245------------
|
||||
// sysDepart.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
|
||||
// //update-begin---author:wangshuai ---date:20220105 for:[JTC-363]部门导入 机构类别没有时导入失败,赋默认值------------
|
||||
// if(oConvertUtils.isEmpty(sysDepart.getOrgCategory())){
|
||||
// sysDepart.setOrgCategory("1");
|
||||
// }
|
||||
// //update-end---author:wangshuai ---date:20220105 for:[JTC-363]部门导入 机构类别没有时导入失败,赋默认值------------
|
||||
// ImportExcelUtil.importDateSaveOne(sysDepart, ISysDepartService.class, errorMessageList, num, CommonConstant.SQL_INDEX_UNIQ_DEPART_ORG_CODE);
|
||||
// num++;
|
||||
// }
|
||||
//update-end---author:wangshuai---date:2023-10-20---for: 注释掉原来的导入部门的逻辑---
|
||||
|
||||
//update-begin---author:wangshuai---date:2023-10-19---for:【QQYUN-5482】系统的部门导入导出也可以改成敲敲云模式的部门路径---
|
||||
listSysDeparts = ExcelImportUtil.importExcel(file.getInputStream(), SysDepartExportVo.class, params);
|
||||
sysDepartService.importSysDepart(listSysDeparts,errorMessageList);
|
||||
//update-end---author:wangshuai---date:2023-10-19---for:【QQYUN-5482】系统的部门导入导出也可以改成敲敲云模式的部门路径---
|
||||
|
||||
//清空部门缓存
|
||||
Set keys3 = redisTemplate.keys(CacheConstant.SYS_DEPARTS_CACHE + "*");
|
||||
Set keys4 = redisTemplate.keys(CacheConstant.SYS_DEPART_IDS_CACHE + "*");
|
||||
@ -544,7 +564,7 @@ public class SysDepartController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/queryByIds", method = RequestMethod.GET)
|
||||
public Result<Collection<SysDepart>> queryByIds(@RequestParam String deptIds) {
|
||||
public Result<Collection<SysDepart>> queryByIds(@RequestParam(name = "deptIds") String deptIds) {
|
||||
Result<Collection<SysDepart>> result = new Result<>();
|
||||
String[] ids = deptIds.split(",");
|
||||
Collection<String> idList = Arrays.asList(ids);
|
||||
|
||||
@ -79,8 +79,8 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
|
||||
HttpServletRequest req) {
|
||||
QueryWrapper<SysDepartRole> queryWrapper = QueryGenerator.initQueryWrapper(sysDepartRole, req.getParameterMap());
|
||||
Page<SysDepartRole> page = new Page<SysDepartRole>(pageNo, pageSize);
|
||||
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
List<String> deptIds = null;
|
||||
// LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
// List<String> deptIds = null;
|
||||
// if(oConvertUtils.isEmpty(deptId)){
|
||||
// if(oConvertUtils.isNotEmpty(user.getUserIdentity()) && user.getUserIdentity().equals(CommonConstant.USER_IDENTITY_2) ){
|
||||
// deptIds = sysDepartService.getMySubDepIdsByDepId(user.getDepartIds());
|
||||
@ -93,7 +93,10 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
|
||||
// queryWrapper.in("depart_id",deptIds);
|
||||
|
||||
//我的部门,选中部门只能看当前部门下的角色
|
||||
queryWrapper.eq("depart_id",deptId);
|
||||
if(oConvertUtils.isNotEmpty(deptId)){
|
||||
queryWrapper.eq("depart_id",deptId);
|
||||
}
|
||||
|
||||
IPage<SysDepartRole> pageList = sysDepartRoleService.page(page, queryWrapper);
|
||||
return Result.ok(pageList);
|
||||
}
|
||||
|
||||
@ -600,9 +600,10 @@ public class SysDictController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/deleteList", method = RequestMethod.GET)
|
||||
public Result<List<SysDict>> deleteList() {
|
||||
public Result<List<SysDict>> deleteList(HttpServletRequest request) {
|
||||
Result<List<SysDict>> result = new Result<List<SysDict>>();
|
||||
List<SysDict> list = this.sysDictService.queryDeleteList();
|
||||
String tenantId = TokenUtils.getTenantIdByRequest(request);
|
||||
List<SysDict> list = this.sysDictService.queryDeleteList(tenantId);
|
||||
result.setSuccess(true);
|
||||
result.setResult(list);
|
||||
return result;
|
||||
|
||||
@ -1,152 +0,0 @@
|
||||
package org.jeecg.modules.system.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.modules.system.entity.SysFiles;
|
||||
import org.jeecg.modules.system.service.ISysFilesService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @Description: 知识库-文档管理
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2022-07-21
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Api(tags = "知识库-文档管理")
|
||||
@RestController
|
||||
@RequestMapping("/sys/files")
|
||||
public class SysFilesController extends JeecgController<SysFiles, ISysFilesService> {
|
||||
@Autowired
|
||||
private ISysFilesService sysFilesService;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
* @param sysFiles
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "知识库-文档管理-分页列表查询")
|
||||
@ApiOperation(value = "知识库-文档管理-分页列表查询", notes = "知识库-文档管理-分页列表查询")
|
||||
@GetMapping(value = "/list")
|
||||
public Result<?> queryPageList(SysFiles sysFiles,
|
||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
QueryWrapper<SysFiles> queryWrapper = QueryGenerator.initQueryWrapper(sysFiles, req.getParameterMap());
|
||||
Page<SysFiles> page = new Page<SysFiles>(pageNo, pageSize);
|
||||
IPage<SysFiles> pageList = sysFilesService.page(page, queryWrapper);
|
||||
return Result.OK(pageList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @param sysFiles
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "知识库-文档管理-添加")
|
||||
@ApiOperation(value = "知识库-文档管理-添加", notes = "知识库-文档管理-添加")
|
||||
@PostMapping(value = "/add")
|
||||
public Result<?> add(@RequestBody SysFiles sysFiles) {
|
||||
sysFilesService.save(sysFiles);
|
||||
return Result.OK("添加成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @param sysFiles
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "知识库-文档管理-编辑")
|
||||
@ApiOperation(value = "知识库-文档管理-编辑", notes = "知识库-文档管理-编辑")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
|
||||
public Result<?> edit(@RequestBody SysFiles sysFiles) {
|
||||
sysFilesService.updateById(sysFiles);
|
||||
return Result.OK("编辑成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id删除
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "知识库-文档管理-通过id删除")
|
||||
@ApiOperation(value = "知识库-文档管理-通过id删除", notes = "知识库-文档管理-通过id删除")
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
|
||||
sysFilesService.removeById(id);
|
||||
return Result.OK("删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "知识库-文档管理-批量删除")
|
||||
@ApiOperation(value = "知识库-文档管理-批量删除", notes = "知识库-文档管理-批量删除")
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
|
||||
this.sysFilesService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.OK("批量删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "知识库-文档管理-通过id查询")
|
||||
@ApiOperation(value = "知识库-文档管理-通过id查询", notes = "知识库-文档管理-通过id查询")
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||
SysFiles sysFiles = sysFilesService.getById(id);
|
||||
return Result.OK(sysFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出excel
|
||||
*
|
||||
* @param request
|
||||
* @param sysFiles
|
||||
*/
|
||||
@RequestMapping(value = "/exportXls")
|
||||
public ModelAndView exportXls(HttpServletRequest request, SysFiles sysFiles) {
|
||||
return super.exportXls(request, sysFiles, SysFiles.class, "知识库-文档管理");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过excel导入数据
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
|
||||
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
|
||||
return super.importExcel(request, response, SysFiles.class);
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@ import java.util.Arrays;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
@ -54,6 +55,7 @@ public class SysLogController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/list", method = RequestMethod.GET)
|
||||
//@RequiresPermissions("system:log:list")
|
||||
public Result<IPage<SysLog>> queryPageList(SysLog syslog,@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,HttpServletRequest req) {
|
||||
Result<IPage<SysLog>> result = new Result<IPage<SysLog>>();
|
||||
@ -84,6 +86,7 @@ public class SysLogController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
|
||||
//@RequiresPermissions("system:log:delete")
|
||||
public Result<SysLog> delete(@RequestParam(name="id",required=true) String id) {
|
||||
Result<SysLog> result = new Result<SysLog>();
|
||||
SysLog sysLog = sysLogService.getById(id);
|
||||
@ -104,6 +107,7 @@ public class SysLogController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
|
||||
//@RequiresPermissions("system:log:deleteBatch")
|
||||
public Result<SysRole> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
|
||||
Result<SysRole> result = new Result<SysRole>();
|
||||
if(ids==null || "".equals(ids.trim())) {
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
package org.jeecg.modules.system.controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.SymbolConstant;
|
||||
@ -19,6 +16,7 @@ import org.jeecg.common.util.Md5Util;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.JeecgBaseConfig;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.modules.system.constant.DefIndexConst;
|
||||
import org.jeecg.modules.system.entity.*;
|
||||
import org.jeecg.modules.system.model.SysPermissionTree;
|
||||
import org.jeecg.modules.system.model.TreeModel;
|
||||
@ -246,38 +244,66 @@ public class SysPermissionController {
|
||||
if (oConvertUtils.isEmpty(loginUser)) {
|
||||
return Result.error("请登录系统!");
|
||||
}
|
||||
List<SysPermission> metaList = sysPermissionService.queryByUser(loginUser.getUsername());
|
||||
List<SysPermission> metaList = sysPermissionService.queryByUser(loginUser.getId());
|
||||
//添加首页路由
|
||||
//update-begin-author:taoyan date:20200211 for: TASK #3368 【路由缓存】首页的缓存设置有问题,需要根据后台的路由配置来实现是否缓存
|
||||
if(!PermissionDataUtil.hasIndexPage(metaList)){
|
||||
SysPermission indexMenu = sysPermissionService.list(new LambdaQueryWrapper<SysPermission>().eq(SysPermission::getName,"首页")).get(0);
|
||||
metaList.add(0,indexMenu);
|
||||
}
|
||||
//update-end-author:taoyan date:20200211 for: TASK #3368 【路由缓存】首页的缓存设置有问题,需要根据后台的路由配置来实现是否缓存
|
||||
|
||||
//update-begin--Author:zyf Date:20220425 for:自定义首页地址 LOWCOD-1578
|
||||
String version = request.getHeader(CommonConstant.VERSION);
|
||||
//update-begin---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑-----------
|
||||
SysRoleIndex roleIndex= sysUserService.getDynamicIndexByUserRole(loginUser.getUsername(),version);
|
||||
//update-end---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑-----------
|
||||
SysRoleIndex defIndexCfg = sysUserService.getDynamicIndexByUserRole(loginUser.getUsername(), version);
|
||||
if (defIndexCfg == null) {
|
||||
defIndexCfg = sysRoleIndexService.initDefaultIndex();
|
||||
}
|
||||
//update-end--Author:zyf Date:20220425 for:自定义首页地址 LOWCOD-1578
|
||||
|
||||
if(roleIndex!=null){
|
||||
List<SysPermission> menus = metaList.stream().filter(sysPermission -> "首页".equals(sysPermission.getName())).collect(Collectors.toList());
|
||||
//update-begin---author:liusq ---date:2022-06-29 for:设置自定义首页地址和组件----------
|
||||
String component = roleIndex.getComponent();
|
||||
String routeUrl = roleIndex.getUrl();
|
||||
boolean route = roleIndex.isRoute();
|
||||
if(oConvertUtils.isNotEmpty(routeUrl)){
|
||||
// 如果没有授权角色首页,则自动添加首页路由
|
||||
if (!PermissionDataUtil.hasIndexPage(metaList, defIndexCfg)) {
|
||||
LambdaQueryWrapper<SysPermission> indexQueryWrapper = new LambdaQueryWrapper<>();
|
||||
indexQueryWrapper.eq(SysPermission::getUrl, defIndexCfg.getUrl());
|
||||
SysPermission indexMenu = sysPermissionService.getOne(indexQueryWrapper);
|
||||
if (indexMenu == null) {
|
||||
indexMenu = new SysPermission();
|
||||
indexMenu.setUrl(defIndexCfg.getUrl());
|
||||
indexMenu.setComponent(defIndexCfg.getComponent());
|
||||
indexMenu.setRoute(defIndexCfg.isRoute());
|
||||
indexMenu.setName(DefIndexConst.DEF_INDEX_NAME);
|
||||
indexMenu.setMenuType(0);
|
||||
}
|
||||
// 如果没有授权一级菜单,则自身变为一级菜单
|
||||
if (indexMenu.getParentId() != null && !PermissionDataUtil.hasMenuById(metaList, indexMenu.getParentId())) {
|
||||
indexMenu.setMenuType(0);
|
||||
indexMenu.setParentId(null);
|
||||
}
|
||||
if (oConvertUtils.isEmpty(indexMenu.getIcon())) {
|
||||
indexMenu.setIcon("ant-design:home");
|
||||
}
|
||||
metaList.add(0, indexMenu);
|
||||
}
|
||||
//update-end-author:taoyan date:20200211 for: TASK #3368 【路由缓存】首页的缓存设置有问题,需要根据后台的路由配置来实现是否缓存
|
||||
|
||||
/* TODO 注: 这段代码的主要作用是:把首页菜单的组件替换成角色菜单的组件,由于现在的逻辑如果角色菜单不存在则自动插入一条,所以这段代码暂时不需要
|
||||
List<SysPermission> menus = metaList.stream().filter(sysPermission -> {
|
||||
if (defIndexCfg.getUrl().equals(sysPermission.getUrl())) {
|
||||
return true;
|
||||
}
|
||||
return defIndexCfg.getUrl().equals(sysPermission.getUrl());
|
||||
}).collect(Collectors.toList());
|
||||
//update-begin---author:liusq ---date:2022-06-29 for:设置自定义首页地址和组件----------
|
||||
if (menus.size() == 1) {
|
||||
String component = defIndexCfg.getComponent();
|
||||
String routeUrl = defIndexCfg.getUrl();
|
||||
boolean route = defIndexCfg.isRoute();
|
||||
if (oConvertUtils.isNotEmpty(routeUrl)) {
|
||||
menus.get(0).setComponent(component);
|
||||
menus.get(0).setRoute(route);
|
||||
menus.get(0).setUrl(routeUrl);
|
||||
}else{
|
||||
} else {
|
||||
menus.get(0).setComponent(component);
|
||||
}
|
||||
//update-end---author:liusq ---date:2022-06-29 for:设置自定义首页地址和组件-----------
|
||||
}
|
||||
|
||||
//update-end---author:liusq ---date:2022-06-29 for:设置自定义首页地址和组件-----------
|
||||
*/
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
JSONArray menujsonArray = new JSONArray();
|
||||
this.getPermissionJsonArray(menujsonArray, metaList, null);
|
||||
@ -287,7 +313,7 @@ public class SysPermissionController {
|
||||
JSONArray authjsonArray = new JSONArray();
|
||||
this.getAuthJsonArray(authjsonArray, metaList);
|
||||
//查询所有的权限
|
||||
LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>();
|
||||
LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>().select( SysPermission::getName, SysPermission::getPermsType, SysPermission::getPerms, SysPermission::getStatus);
|
||||
query.eq(SysPermission::getDelFlag, CommonConstant.DEL_FLAG_0);
|
||||
query.eq(SysPermission::getMenuType, CommonConstant.MENU_TYPE_2);
|
||||
//query.eq(SysPermission::getStatus, "1");
|
||||
@ -298,6 +324,12 @@ public class SysPermissionController {
|
||||
json.put("menu", menujsonArray);
|
||||
//按钮权限(用户拥有的权限集合)
|
||||
json.put("auth", authjsonArray);
|
||||
// 按钮权限(用户拥有的权限集合)
|
||||
List<String> codeList = metaList.stream()
|
||||
.filter((permission) -> CommonConstant.MENU_TYPE_2.equals(permission.getMenuType()) && CommonConstant.STATUS_1.equals(permission.getStatus()))
|
||||
.collect(ArrayList::new, (list, permission) -> list.add(permission.getPerms()), ArrayList::addAll);
|
||||
// 所拥有的权限编码(vue3专用)
|
||||
json.put("codeList", codeList);
|
||||
//全部权限配置集合(按钮权限,访问权限)
|
||||
json.put("allAuth", allauthjsonArray);
|
||||
//数据源安全模式
|
||||
@ -325,7 +357,7 @@ public class SysPermissionController {
|
||||
return Result.error("请登录系统!");
|
||||
}
|
||||
// 获取当前用户的权限集合
|
||||
List<SysPermission> metaList = sysPermissionService.queryByUser(loginUser.getUsername());
|
||||
List<SysPermission> metaList = sysPermissionService.queryByUser(loginUser.getId());
|
||||
// 按钮权限(用户拥有的权限集合)
|
||||
List<String> codeList = metaList.stream()
|
||||
.filter((permission) -> CommonConstant.MENU_TYPE_2.equals(permission.getMenuType()) && CommonConstant.STATUS_1.equals(permission.getStatus()))
|
||||
@ -334,7 +366,7 @@ public class SysPermissionController {
|
||||
JSONArray authArray = new JSONArray();
|
||||
this.getAuthJsonArray(authArray, metaList);
|
||||
// 查询所有的权限
|
||||
LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<>();
|
||||
LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>().select( SysPermission::getName, SysPermission::getPermsType, SysPermission::getPerms, SysPermission::getStatus);
|
||||
query.eq(SysPermission::getDelFlag, CommonConstant.DEL_FLAG_0);
|
||||
query.eq(SysPermission::getMenuType, CommonConstant.MENU_TYPE_2);
|
||||
List<SysPermission> allAuthList = sysPermissionService.list(query);
|
||||
|
||||
@ -123,7 +123,6 @@ public class SysRoleController {
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
Result<IPage<SysRole>> result = new Result<IPage<SysRole>>();
|
||||
//------------------------------------------------------------------------------------------------
|
||||
//此接口必须通过租户来隔离查询
|
||||
role.setTenantId(oConvertUtils.getInt(!"0".equals(TenantContext.getTenant()) ? TenantContext.getTenant() : "", -1));
|
||||
|
||||
@ -216,6 +215,12 @@ public class SysRoleController {
|
||||
return Result.error("删除角色失败,当前角色不在此租户中。");
|
||||
}
|
||||
}
|
||||
|
||||
//update-begin---author:wangshuai---date:2024-01-16---for:【QQYUN-7974】禁止删除 admin 角色---
|
||||
//是否存在admin角色
|
||||
sysRoleService.checkAdminRoleRejectDel(id);
|
||||
//update-end---author:wangshuai---date:2024-01-16---for:【QQYUN-7974】禁止删除 admin 角色---
|
||||
|
||||
sysRoleService.deleteRole(id);
|
||||
return Result.ok("删除角色成功");
|
||||
}
|
||||
@ -248,6 +253,8 @@ public class SysRoleController {
|
||||
}
|
||||
}
|
||||
}
|
||||
//验证是否为admin角色
|
||||
sysRoleService.checkAdminRoleRejectDel(ids);
|
||||
sysRoleService.deleteBatchRole(ids.split(","));
|
||||
result.success("删除角色成功!");
|
||||
}
|
||||
@ -527,7 +534,6 @@ public class SysRoleController {
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO 权限未完成(敲敲云接口,租户应用)
|
||||
* 分页获取全部角色列表(包含每个角色的数量)
|
||||
* @return
|
||||
*/
|
||||
|
||||
@ -1,29 +1,26 @@
|
||||
package org.jeecg.modules.system.controller;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.jeecg.modules.system.entity.SysRoleIndex;
|
||||
import org.jeecg.modules.system.service.ISysRoleIndexService;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.modules.system.entity.SysRoleIndex;
|
||||
import org.jeecg.modules.system.service.ISysRoleIndexService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @Description: 角色首页配置
|
||||
@ -172,4 +169,32 @@ public class SysRoleIndexController extends JeecgController<SysRoleIndex, ISysRo
|
||||
SysRoleIndex sysRoleIndex = sysRoleIndexService.getOne(new LambdaQueryWrapper<SysRoleIndex>().eq(SysRoleIndex::getRoleCode, roleCode));
|
||||
return Result.OK(sysRoleIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询默认首页配置
|
||||
*/
|
||||
@GetMapping("/queryDefIndex")
|
||||
public Result<SysRoleIndex> queryDefIndex() {
|
||||
SysRoleIndex defIndexCfg = sysRoleIndexService.queryDefaultIndex();
|
||||
return Result.OK(defIndexCfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新默认首页配置
|
||||
*/
|
||||
@RequiresPermissions("system:permission:setDefIndex")
|
||||
@PutMapping("/updateDefIndex")
|
||||
public Result<?> updateDefIndex(
|
||||
@RequestParam("url") String url,
|
||||
@RequestParam("component") String component,
|
||||
@RequestParam("isRoute") Boolean isRoute
|
||||
) {
|
||||
boolean success = sysRoleIndexService.updateDefaultIndex(url, component, isRoute);
|
||||
if (success) {
|
||||
return Result.OK("设置成功");
|
||||
} else {
|
||||
return Result.error("设置失败");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@GetMapping(value = "/list")
|
||||
public Result<?> queryPageList(
|
||||
SysTableWhiteList sysTableWhiteList,
|
||||
@ -64,7 +64,7 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
||||
*/
|
||||
@AutoLog(value = "系统表白名单-添加")
|
||||
@ApiOperation(value = "系统表白名单-添加", notes = "系统表白名单-添加")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@PostMapping(value = "/add")
|
||||
public Result<?> add(@RequestBody SysTableWhiteList sysTableWhiteList) {
|
||||
if (sysTableWhiteListService.add(sysTableWhiteList)) {
|
||||
@ -82,7 +82,7 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
||||
*/
|
||||
@AutoLog(value = "系统表白名单-编辑")
|
||||
@ApiOperation(value = "系统表白名单-编辑", notes = "系统表白名单-编辑")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
|
||||
public Result<?> edit(@RequestBody SysTableWhiteList sysTableWhiteList) {
|
||||
if (sysTableWhiteListService.edit(sysTableWhiteList)) {
|
||||
@ -100,7 +100,7 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
||||
*/
|
||||
@AutoLog(value = "系统表白名单-通过id删除")
|
||||
@ApiOperation(value = "系统表白名单-通过id删除", notes = "系统表白名单-通过id删除")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<?> delete(@RequestParam(name = "id") String id) {
|
||||
if (sysTableWhiteListService.deleteByIds(id)) {
|
||||
@ -118,7 +118,7 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
||||
*/
|
||||
@AutoLog(value = "系统表白名单-批量删除")
|
||||
@ApiOperation(value = "系统表白名单-批量删除", notes = "系统表白名单-批量删除")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<?> deleteBatch(@RequestParam(name = "ids") String ids) {
|
||||
if (sysTableWhiteListService.deleteByIds(ids)) {
|
||||
@ -136,7 +136,7 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
||||
*/
|
||||
@AutoLog(value = "系统表白名单-通过id查询")
|
||||
@ApiOperation(value = "系统表白名单-通过id查询", notes = "系统表白名单-通过id查询")
|
||||
//@RequiresRoles("admin")
|
||||
@RequiresRoles("admin")
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||
SysTableWhiteList sysTableWhiteList = sysTableWhiteListService.getById(id);
|
||||
|
||||
@ -858,16 +858,19 @@ public class SysTenantController {
|
||||
@GetMapping("/getTenantCount")
|
||||
public Result<Map<String,Long>> getTenantCount(HttpServletRequest request){
|
||||
Map<String,Long> map = new HashMap<>();
|
||||
Integer tenantId = oConvertUtils.getInt(TokenUtils.getTenantIdByRequest(request),0);
|
||||
LambdaQueryWrapper<SysUserTenant> userTenantQuery = new LambdaQueryWrapper<>();
|
||||
userTenantQuery.eq(SysUserTenant::getTenantId,tenantId);
|
||||
userTenantQuery.eq(SysUserTenant::getStatus,CommonConstant.USER_TENANT_NORMAL);
|
||||
long userCount = relationService.count(userTenantQuery);
|
||||
//update-begin---author:wangshuai---date:2023-11-24---for:【QQYUN-7177】用户数量显示不正确---
|
||||
if(oConvertUtils.isEmpty(TokenUtils.getTenantIdByRequest(request))){
|
||||
return Result.error("当前租户为空,禁止访问!");
|
||||
}
|
||||
Integer tenantId = oConvertUtils.getInt(TokenUtils.getTenantIdByRequest(request));
|
||||
Long userCount = relationService.getUserCount(tenantId,CommonConstant.USER_TENANT_NORMAL);
|
||||
//update-end---author:wangshuai---date:2023-11-24---for:【QQYUN-7177】用户数量显示不正确---
|
||||
map.put("userCount",userCount);
|
||||
LambdaQueryWrapper<SysDepart> departQuery = new LambdaQueryWrapper<>();
|
||||
departQuery.eq(SysDepart::getDelFlag,String.valueOf(CommonConstant.DEL_FLAG_0));
|
||||
departQuery.eq(SysDepart::getTenantId,tenantId);
|
||||
departQuery.eq(SysDepart::getStatus,CommonConstant.STATUS_1);
|
||||
//部门状态暂时没用,先注释掉
|
||||
//departQuery.eq(SysDepart::getStatus,CommonConstant.STATUS_1);
|
||||
long departCount = sysDepartService.count(departQuery);
|
||||
map.put("departCount",departCount);
|
||||
return Result.ok(map);
|
||||
|
||||
@ -244,6 +244,7 @@ public class SysUserController {
|
||||
Result<SysUser> result = new Result<SysUser>();
|
||||
try {
|
||||
String ids = jsonObject.getString("ids");
|
||||
sysUserService.checkUserAdminRejectDel(ids);
|
||||
String status = jsonObject.getString("status");
|
||||
String[] arr = ids.split(",");
|
||||
for (String id : arr) {
|
||||
@ -437,12 +438,13 @@ public class SysUserController {
|
||||
@RequestParam(name = "departId", required = false) String departId,
|
||||
@RequestParam(name="realname",required=false) String realname,
|
||||
@RequestParam(name="username",required=false) String username,
|
||||
@RequestParam(name="isMultiTranslate",required=false) String isMultiTranslate,
|
||||
@RequestParam(name="id",required = false) String id) {
|
||||
//update-begin-author:taoyan date:2022-7-14 for: VUEN-1702【禁止问题】sql注入漏洞
|
||||
String[] arr = new String[]{departId, realname, username, id};
|
||||
SqlInjectionUtil.filterContent(arr, SymbolConstant.SINGLE_QUOTATION_MARK);
|
||||
//update-end-author:taoyan date:2022-7-14 for: VUEN-1702【禁止问题】sql注入漏洞
|
||||
IPage<SysUser> pageList = sysUserDepartService.queryDepartUserPageList(departId, username, realname, pageSize, pageNo,id);
|
||||
IPage<SysUser> pageList = sysUserDepartService.queryDepartUserPageList(departId, username, realname, pageSize, pageNo,id,isMultiTranslate);
|
||||
return Result.OK(pageList);
|
||||
}
|
||||
|
||||
@ -568,7 +570,7 @@ public class SysUserController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/queryByIds", method = RequestMethod.GET)
|
||||
public Result<Collection<SysUser>> queryByIds(@RequestParam String userIds) {
|
||||
public Result<Collection<SysUser>> queryByIds(@RequestParam(name = "userIds") String userIds) {
|
||||
Result<Collection<SysUser>> result = new Result<>();
|
||||
String[] userId = userIds.split(",");
|
||||
Collection<String> idList = Arrays.asList(userId);
|
||||
@ -585,7 +587,7 @@ public class SysUserController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/queryByNames", method = RequestMethod.GET)
|
||||
public Result<Collection<SysUser>> queryByNames(@RequestParam String userNames) {
|
||||
public Result<Collection<SysUser>> queryByNames(@RequestParam(name = "userNames") String userNames) {
|
||||
Result<Collection<SysUser>> result = new Result<>();
|
||||
String[] names = userNames.split(",");
|
||||
QueryWrapper<SysUser> queryWrapper=new QueryWrapper();
|
||||
@ -1427,7 +1429,7 @@ public class SysUserController {
|
||||
//------------------------------------------------------------------------------------------------
|
||||
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
||||
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
|
||||
String tenantId = TokenUtils.getTenantIdByRequest(request);
|
||||
String tenantId = oConvertUtils.getString(TokenUtils.getTenantIdByRequest(request),"-1");
|
||||
//update-begin---author:wangshuai ---date:20221223 for:[QQYUN-3371]租户逻辑改造,改成关系表------------
|
||||
List<String> userIds = userTenantService.getUserIdsByTenantId(Integer.valueOf(tenantId));
|
||||
if (oConvertUtils.listIsNotEmpty(userIds)) {
|
||||
@ -1548,7 +1550,8 @@ public class SysUserController {
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
||||
@RequestParam(name = "departId", required = false) String departId,
|
||||
@RequestParam(name = "roleId", required = false) String roleId,
|
||||
@RequestParam(name="keyword",required=false) String keyword) {
|
||||
@RequestParam(name="keyword",required=false) String keyword,
|
||||
@RequestParam(name="excludeUserIdList",required = false) String excludeUserIdList) {
|
||||
//------------------------------------------------------------------------------------------------
|
||||
Integer tenantId = null;
|
||||
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
||||
@ -1559,7 +1562,7 @@ public class SysUserController {
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
IPage<SysUser> pageList = sysUserDepartService.getUserInformation(tenantId, departId,roleId, keyword, pageSize, pageNo);
|
||||
IPage<SysUser> pageList = sysUserDepartService.getUserInformation(tenantId, departId,roleId, keyword, pageSize, pageNo,excludeUserIdList);
|
||||
return Result.OK(pageList);
|
||||
}
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ public class SysUserOnlineController {
|
||||
online.setToken(token);
|
||||
//TODO 改成一次性查询
|
||||
LoginUser loginUser = sysBaseApi.getUserByName(JwtUtil.getUsername(token));
|
||||
if (loginUser != null) {
|
||||
if (loginUser != null && !"_reserve_user_external".equals(loginUser.getUsername())) {
|
||||
//update-begin---author:wangshuai ---date:20220104 for:[JTC-382]在线用户查询无效------------
|
||||
//验证用户名是否与传过来的用户名相同
|
||||
boolean isMatchUsername=true;
|
||||
|
||||
@ -14,6 +14,7 @@ import org.jeecg.common.constant.SymbolConstant;
|
||||
import org.jeecg.common.constant.enums.MessageTypeEnum;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.TokenUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.modules.system.entity.SysThirdAccount;
|
||||
@ -22,6 +23,8 @@ import org.jeecg.modules.system.service.ISysThirdAccountService;
|
||||
import org.jeecg.modules.system.service.ISysThirdAppConfigService;
|
||||
import org.jeecg.modules.system.service.impl.ThirdAppDingtalkServiceImpl;
|
||||
import org.jeecg.modules.system.service.impl.ThirdAppWechatEnterpriseServiceImpl;
|
||||
import org.jeecg.modules.system.vo.thirdapp.JwSysUserDepartVo;
|
||||
import org.jeecg.modules.system.vo.thirdapp.JwUserDepartVo;
|
||||
import org.jeecg.modules.system.vo.thirdapp.SyncInfoVo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -424,10 +427,6 @@ public class ThirdAppController {
|
||||
@GetMapping("/getThirdConfigByTenantId")
|
||||
public Result<SysThirdAppConfig> getThirdAppByTenantId(@RequestParam(name = "tenantId", required = false) Integer tenantId,
|
||||
@RequestParam(name = "thirdType") String thirdType) {
|
||||
Result<SysThirdAppConfig> result = new Result<>();
|
||||
LambdaQueryWrapper<SysThirdAppConfig> query = new LambdaQueryWrapper<>();
|
||||
query.eq(SysThirdAppConfig::getThirdType,thirdType);
|
||||
|
||||
if (MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL) {
|
||||
if (tenantId == null) {
|
||||
return Result.error("开启多租户模式,租户ID参数不允许为空!");
|
||||
@ -438,7 +437,9 @@ public class ThirdAppController {
|
||||
tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
Result<SysThirdAppConfig> result = new Result<>();
|
||||
LambdaQueryWrapper<SysThirdAppConfig> query = new LambdaQueryWrapper<>();
|
||||
query.eq(SysThirdAppConfig::getThirdType,thirdType);
|
||||
query.eq(SysThirdAppConfig::getTenantId,tenantId);
|
||||
SysThirdAppConfig sysThirdAppConfig = appConfigService.getOne(query);
|
||||
result.setSuccess(true);
|
||||
@ -520,4 +521,46 @@ public class ThirdAppController {
|
||||
return Result.ok("解绑成功");
|
||||
}
|
||||
//========================end 应用低代码账号设置第三方账号绑定 ================================
|
||||
|
||||
/**
|
||||
* 获取企业微信绑定的用户信息
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/getThirdUserByWechat")
|
||||
public Result<JwSysUserDepartVo> getThirdUserByWechat(HttpServletRequest request){
|
||||
//获取企业微信配置
|
||||
Integer tenantId = oConvertUtils.getInt(TokenUtils.getTenantIdByRequest(request),0);
|
||||
SysThirdAppConfig config = appConfigService.getThirdConfigByThirdType(tenantId, MessageTypeEnum.QYWX.getType());
|
||||
if (null != config) {
|
||||
JwSysUserDepartVo list = wechatEnterpriseService.getThirdUserByWechat(tenantId);
|
||||
return Result.ok(list);
|
||||
}
|
||||
return Result.error("企业微信尚未配置,请配置企业微信");
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步企业微信部门和用户到本地
|
||||
* @param jwUserDepartJson
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sync/wechatEnterprise/departAndUser/toLocal")
|
||||
public Result<SyncInfoVo> syncWechatEnterpriseDepartAndUserToLocal(@RequestParam(name = "jwUserDepartJson") String jwUserDepartJson,HttpServletRequest request){
|
||||
int tenantId = oConvertUtils.getInt(TokenUtils.getTenantIdByRequest(request), 0);
|
||||
SyncInfoVo syncInfoVo = wechatEnterpriseService.syncWechatEnterpriseDepartAndUserToLocal(jwUserDepartJson,tenantId);
|
||||
return Result.ok(syncInfoVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询被绑定的企业微信用户
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/getThirdUserBindByWechat")
|
||||
public Result<List<JwUserDepartVo>> getThirdUserBindByWechat(HttpServletRequest request){
|
||||
int tenantId = oConvertUtils.getInt(TokenUtils.getTenantIdByRequest(request), 0);
|
||||
List<JwUserDepartVo> jwSysUserDepartVos = wechatEnterpriseService.getThirdUserBindByWechat(tenantId);
|
||||
return Result.ok(jwSysUserDepartVos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
package org.jeecg.modules.system.controller;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* @Description: 企业微信证书验证
|
||||
* @author: wangshuai
|
||||
* @date: 2023/12/6 10:42
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
public class WechatVerifyController {
|
||||
|
||||
/**
|
||||
* 企业微信验证
|
||||
*/
|
||||
@RequestMapping(value = "/WW_verify_{code}.txt")
|
||||
public void mpVerify(@PathVariable("code") String code, HttpServletResponse response) {
|
||||
try {
|
||||
PrintWriter writer = response.getWriter();
|
||||
writer.write(code);
|
||||
writer.close();
|
||||
} catch (Exception e) {
|
||||
log.error("企业微信证书验证失败!");
|
||||
log.error(e.getMessage(), e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,142 +0,0 @@
|
||||
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;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Description: 知识库-文档管理
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2022-07-21
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_files")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(value="sys_files对象", description="知识库-文档管理")
|
||||
public class SysFiles {
|
||||
|
||||
/**主键id*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@ApiModelProperty(value = "主键id")
|
||||
private String id;
|
||||
/**文件名称*/
|
||||
@Excel(name = "文件名称", width = 15)
|
||||
@ApiModelProperty(value = "文件名称")
|
||||
private String fileName;
|
||||
/**文件地址*/
|
||||
@Excel(name = "文件地址", width = 15)
|
||||
@ApiModelProperty(value = "文件地址")
|
||||
private String url;
|
||||
/**创建人登录名称*/
|
||||
@Excel(name = "创建人登录名称", width = 15)
|
||||
@Dict(dicCode = "username",dicText = "realname",dictTable = "sys_user")
|
||||
@ApiModelProperty(value = "创建人登录名称")
|
||||
private String createBy;
|
||||
/**创建日期*/
|
||||
@Excel(name = "创建日期", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "创建日期")
|
||||
private Date createTime;
|
||||
/**更新人登录名称*/
|
||||
@Excel(name = "更新人登录名称", width = 15)
|
||||
@ApiModelProperty(value = "更新人登录名称")
|
||||
private String updateBy;
|
||||
/**更新日期*/
|
||||
@Excel(name = "更新日期", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty(value = "更新日期")
|
||||
private Date updateTime;
|
||||
/**文档类型(folder:文件夹 excel:excel doc:word pp:ppt image:图片 archive:其他文档 video:视频)*/
|
||||
@Excel(name = "文档类型(folder:文件夹 excel:excel doc:word pp:ppt image:图片 archive:其他文档 video:视频)", width = 15)
|
||||
@ApiModelProperty(value = "文档类型(folder:文件夹 excel:excel doc:word pp:ppt image:图片 archive:其他文档 video:视频)")
|
||||
private String fileType;
|
||||
/**文件上传类型(temp/本地上传(临时文件) manage/知识库 comment)*/
|
||||
@Excel(name = "文件上传类型(temp/本地上传(临时文件) manage/知识库 common(通用上传))", width = 15)
|
||||
@ApiModelProperty(value = "文件上传类型(temp/本地上传(临时文件) manage/知识库)")
|
||||
private String storeType;
|
||||
/**父级id*/
|
||||
@Excel(name = "父级id", width = 15)
|
||||
@ApiModelProperty(value = "父级id")
|
||||
private String parentId;
|
||||
/**租户id*/
|
||||
@Excel(name = "租户id", width = 15)
|
||||
@ApiModelProperty(value = "租户id")
|
||||
private String tenantId;
|
||||
/**文件大小(kb)*/
|
||||
@Excel(name = "文件大小(kb)", width = 15)
|
||||
@ApiModelProperty(value = "文件大小(kb)")
|
||||
private Double fileSize;
|
||||
/**是否文件夹(1:是 0:否)*/
|
||||
@Excel(name = "是否文件夹(1:是 0:否)", width = 15)
|
||||
@ApiModelProperty(value = "是否文件夹(1:是 0:否)")
|
||||
private String izFolder;
|
||||
/**是否为1级文件夹,允许为空 (1:是 )*/
|
||||
@Excel(name = "是否为1级文件夹,允许为空 (1:是 )", width = 15)
|
||||
@ApiModelProperty(value = "是否为1级文件夹,允许为空 (1:是 )")
|
||||
private String izRootFolder;
|
||||
/**是否标星(1:是 0:否)*/
|
||||
@Excel(name = "是否标星(1:是 0:否)", width = 15)
|
||||
@ApiModelProperty(value = "是否标星(1:是 0:否)")
|
||||
private String izStar;
|
||||
/**下载次数*/
|
||||
@Excel(name = "下载次数", width = 15)
|
||||
@ApiModelProperty(value = "下载次数")
|
||||
private Integer downCount;
|
||||
/**阅读次数*/
|
||||
@Excel(name = "阅读次数", width = 15)
|
||||
@ApiModelProperty(value = "阅读次数")
|
||||
private Integer readCount;
|
||||
/**分享链接*/
|
||||
@Excel(name = "分享链接", width = 15)
|
||||
@ApiModelProperty(value = "分享链接")
|
||||
private String shareUrl;
|
||||
/**分享权限(1.关闭分享 2.允许所有联系人查看 3.允许任何人查看)*/
|
||||
@Excel(name = "分享权限(1.关闭分享 2.允许所有联系人查看 3.允许任何人查看)", width = 15)
|
||||
@ApiModelProperty(value = "分享权限(1.关闭分享 2.允许所有联系人查看 3.允许任何人查看)")
|
||||
private String sharePerms;
|
||||
/**是否允许下载(1:是 0:否)*/
|
||||
@Excel(name = "是否允许下载(1:是 0:否)", width = 15)
|
||||
@ApiModelProperty(value = "是否允许下载(1:是 0:否)")
|
||||
private String enableDown;
|
||||
/**是否允许修改(1:是 0:否)*/
|
||||
@Excel(name = "是否允许修改(1:是 0:否)", width = 15)
|
||||
@ApiModelProperty(value = "是否允许修改(1:是 0:否)")
|
||||
private String enableUpdat;
|
||||
/**删除状态(0-正常,1-删除至回收站)*/
|
||||
@Excel(name = "删除状态(0-正常,1-删除至回收站)", width = 15)
|
||||
@ApiModelProperty(value = "删除状态(0-正常,1-删除至回收站)")
|
||||
private String delFlag;
|
||||
|
||||
/**
|
||||
* 文件表不存在的字段:用户数据集合
|
||||
*/
|
||||
@TableField(exist=false)
|
||||
private String userData;
|
||||
|
||||
/**
|
||||
* 文件表不存在的字段:用户真实姓名
|
||||
*/
|
||||
@TableField(exist=false)
|
||||
private String realname;
|
||||
|
||||
/**
|
||||
* 文件表不存在的字段:压缩名称
|
||||
*/
|
||||
@TableField(exist=false)
|
||||
private String zipName;
|
||||
}
|
||||
@ -9,7 +9,7 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.jeecg.modules.system.constant.DefIndexConst;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -166,11 +166,11 @@ public class SysPermission implements Serializable {
|
||||
}
|
||||
public SysPermission(boolean index) {
|
||||
if(index) {
|
||||
this.id = "9502685863ab87f0ad1134142788a385";
|
||||
this.name="首页";
|
||||
this.component="dashboard/Analysis";
|
||||
this.componentName="dashboard-analysis";
|
||||
this.url="/dashboard/analysis";
|
||||
this.id = "9502685863ab87f0ad1134142788a385";
|
||||
this.name = DefIndexConst.DEF_INDEX_NAME;
|
||||
this.component = DefIndexConst.DEF_INDEX_COMPONENT;
|
||||
this.componentName = "dashboard-analysis";
|
||||
this.url = DefIndexConst.DEF_INDEX_URL;
|
||||
this.icon="home";
|
||||
this.menuType=0;
|
||||
this.sortNo=0.0;
|
||||
|
||||
@ -68,7 +68,7 @@ public class SysTenantPackUser implements Serializable {
|
||||
private transient String packCode;
|
||||
|
||||
/**
|
||||
* 状态(1 正常 2 离职 3 待审核 4 拒绝 5 邀请加入)
|
||||
* 状态(申请状态0 正常状态1)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
|
||||
@ -48,6 +48,4 @@ public class SysUserRole implements Serializable {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import org.jeecg.modules.system.entity.SysDepart;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.model.SysDepartTreeModel;
|
||||
import org.jeecg.modules.system.model.TreeModel;
|
||||
import org.jeecg.modules.system.vo.SysDepartExportVo;
|
||||
import org.jeecg.modules.system.vo.SysUserDepVo;
|
||||
import org.jeecg.modules.system.vo.lowapp.ExportDepartVo;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
@ -161,4 +162,12 @@ public interface SysDepartMapper extends BaseMapper<SysDepart> {
|
||||
* @return
|
||||
*/
|
||||
List<SysDepart> getDepartPageByName(@Param("page") Page<SysDepart> page, @Param("departName") String departName, @Param("tenantId") Integer tenantId, @Param("parentId") String parentId);
|
||||
|
||||
/**
|
||||
* 获取租户id和部门父id获取的部门数据
|
||||
* @param tenantId
|
||||
* @param parentId
|
||||
* @return
|
||||
*/
|
||||
List<SysDepartExportVo> getSysDepartList(@Param("parentId") String parentId,@Param("tenantId") Integer tenantId);
|
||||
}
|
||||
|
||||
@ -82,6 +82,12 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
|
||||
*/
|
||||
List<DictModelMany> queryManyDictByKeys(@Param("dictCodeList") List<String> dictCodeList, @Param("keys") List<String> keys);
|
||||
|
||||
/**
|
||||
* 查询系统所有字典项
|
||||
* @return
|
||||
*/
|
||||
public List<DictModelMany> queryAllDictItems(List<Integer> tenantIdList);
|
||||
|
||||
/**
|
||||
* 查询所有部门 作为字典信息 id -->value,departName -->text
|
||||
* @return
|
||||
@ -187,4 +193,11 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
|
||||
*/
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
List<SysDict> getDictListByLowAppId(@Param("lowAppId") String lowAppId, @Param("tenantId") Integer tenantId);
|
||||
|
||||
/**
|
||||
* 查询被逻辑删除的数据(根据租户id)
|
||||
* @return
|
||||
*/
|
||||
@Select("select * from sys_dict where del_flag = 1 and tenant_id = #{tenantId}")
|
||||
List<SysDict> queryDeleteListBtTenantId(@Param("tenantId") Integer tenantId);
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
package org.jeecg.modules.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.jeecg.modules.system.entity.SysFiles;
|
||||
|
||||
/**
|
||||
* @Description: 知识库-文档管理
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2022-07-21
|
||||
* @Version: V1.0
|
||||
*/
|
||||
public interface SysFilesMapper extends BaseMapper<SysFiles> {
|
||||
|
||||
}
|
||||
@ -29,10 +29,10 @@ public interface SysPermissionMapper extends BaseMapper<SysPermission> {
|
||||
|
||||
/**
|
||||
* 根据用户查询用户权限
|
||||
* @param username 用户账户名称
|
||||
* @param userId 用户ID
|
||||
* @return List<SysPermission>
|
||||
*/
|
||||
public List<SysPermission> queryByUser(@Param("username") String username);
|
||||
public List<SysPermission> queryByUser(@Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 修改菜单状态字段: 是否子节点
|
||||
|
||||
@ -119,5 +119,12 @@ public interface SysTenantMapper extends BaseMapper<SysTenant> {
|
||||
* @return
|
||||
*/
|
||||
Long getApplySuperAdminCount(@Param("userId") String userId, @Param("tenantId") Integer tenantId);
|
||||
|
||||
|
||||
/**
|
||||
* 租户是否存在
|
||||
* @param tenantId
|
||||
* @return
|
||||
*/
|
||||
@Select("select count(1) from sys_tenant where id = #{tenantId} and del_flag = 0")
|
||||
Long tenantIzExist(@Param("tenantId") Integer tenantId);
|
||||
}
|
||||
|
||||
@ -25,4 +25,11 @@ public interface SysTenantPackUserMapper extends BaseMapper<SysTenantPackUser> {
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
List<String> queryTenantPackUserNameList(@Param("tenantId") Integer tenantId, @Param("packCodeList") List<String> packCodeList);
|
||||
|
||||
/**
|
||||
* 判断当前用户在该租户下是否拥有管理员的权限
|
||||
* @param userId
|
||||
* @param tenantId
|
||||
* @return
|
||||
*/
|
||||
Long izHaveBuyAuth(@Param("userId") String userId, @Param("tenantId") String tenantId);
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package org.jeecg.modules.system.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.jeecg.modules.system.entity.SysThirdAccount;
|
||||
import org.jeecg.modules.system.vo.thirdapp.JwUserDepartVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -22,5 +23,12 @@ public interface SysThirdAccountMapper extends BaseMapper<SysThirdAccount> {
|
||||
* @return
|
||||
*/
|
||||
List<SysThirdAccount> selectThirdIdsByUsername(@Param("sysUsernameArr") String[] sysUsernameArr, @Param("thirdType") String thirdType, @Param("tenantId") Integer tenantId);
|
||||
|
||||
|
||||
/**
|
||||
* 查询被绑定的用户
|
||||
* @param tenantId
|
||||
* @param thirdType
|
||||
* @return
|
||||
*/
|
||||
List<JwUserDepartVo> getThirdUserBindByWechat(@Param("tenantId") int tenantId, @Param("thirdType") String thirdType);
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ public interface SysUserDepartMapper extends BaseMapper<SysUserDepart>{
|
||||
* @param keyword
|
||||
* @return
|
||||
*/
|
||||
IPage<SysUser> getProcessUserList(Page<SysUser> page, @Param("orgCode") String orgCode, @Param("keyword") String keyword, @Param("tenantId") Integer tenantId);
|
||||
IPage<SysUser> getProcessUserList(Page<SysUser> page, @Param("orgCode") String orgCode, @Param("keyword") String keyword, @Param("tenantId") Integer tenantId, @Param("excludeUserIdList") List<String> excludeUserIdList);
|
||||
|
||||
/**
|
||||
* 获取租户下的部门通过前台传过来的部门id
|
||||
|
||||
@ -171,9 +171,10 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
|
||||
* @param page
|
||||
* @param roleId
|
||||
* @param keyword
|
||||
* @param userIdList
|
||||
* @return
|
||||
*/
|
||||
IPage<SysUser> selectUserListByRoleId(Page<SysUser> page, @Param("roleId") String roleId, @Param("keyword") String keyword, @Param("tenantId") Integer tenantId);
|
||||
IPage<SysUser> selectUserListByRoleId(Page<SysUser> page, @Param("roleId") String roleId, @Param("keyword") String keyword, @Param("tenantId") Integer tenantId, @Param("excludeUserIdList") List<String> excludeUserIdList);
|
||||
|
||||
/**
|
||||
* 更新刪除状态和离职状态
|
||||
|
||||
@ -2,6 +2,7 @@ package org.jeecg.modules.system.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
@ -64,6 +65,7 @@ public interface SysUserPositionMapper extends BaseMapper<SysUserPosition> {
|
||||
* @param tenantId
|
||||
* @return
|
||||
*/
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
List<String> getPositionIdByUserTenantId(@Param("userId")String userId, @Param("tenantId")Integer tenantId);
|
||||
|
||||
/**
|
||||
|
||||
@ -12,6 +12,7 @@ import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.entity.SysUserTenant;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.jeecg.modules.system.vo.SysUserTenantVo;
|
||||
import org.jeecg.modules.system.vo.thirdapp.JwUserDepartVo;
|
||||
|
||||
/**
|
||||
* @Description: sys_user_tenant_relation
|
||||
@ -149,4 +150,20 @@ public interface SysUserTenantMapper extends BaseMapper<SysUserTenant> {
|
||||
* @param tenantIds
|
||||
*/
|
||||
void deleteUserByTenantId(@Param("tenantIds") List<Integer> tenantIds);
|
||||
|
||||
/**
|
||||
* 获取租户下的成员数量
|
||||
*
|
||||
* @param tenantId
|
||||
* @param tenantStatus
|
||||
* @return
|
||||
*/
|
||||
Long getUserCount(Integer tenantId, String tenantStatus);
|
||||
|
||||
/**
|
||||
* 根据租户id和名称获取用户数据
|
||||
* @param tenantId
|
||||
* @return
|
||||
*/
|
||||
List<JwUserDepartVo> getUsersByTenantIdAndName(@Param("tenantId") Integer tenantId);
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
|
||||
|
||||
<select id="querySysCementListByUserId" parameterType="String" resultMap="SysAnnouncement">
|
||||
select * from sys_announcement
|
||||
select id,titile,create_time,priority,bus_id,open_type,open_page,sender,send_time,msg_content from sys_announcement
|
||||
where send_status = '1'
|
||||
and del_flag = '0'
|
||||
and msg_category = #{msgCategory}
|
||||
|
||||
@ -114,7 +114,9 @@
|
||||
SELECT id,depart_name,org_code,parent_id FROM sys_depart
|
||||
where
|
||||
depart_name = #{departName}
|
||||
and tenant_id = #{tenantId}
|
||||
<if test="null != tenantId and 0 != tenantId">
|
||||
and tenant_id = #{tenantId}
|
||||
</if>
|
||||
<if test="parentId != null and parentId != ''">
|
||||
and parent_id = #{parentId}
|
||||
</if>
|
||||
@ -154,4 +156,24 @@
|
||||
</foreach>
|
||||
)
|
||||
</select>
|
||||
|
||||
<!--系统后台导出,根据父级id和租户id查询部门数据-->
|
||||
<select id="getSysDepartList" resultType="org.jeecg.modules.system.vo.SysDepartExportVo">
|
||||
SELECT id,depart_name,parent_id,depart_name_en,depart_order,description,org_category,org_code,mobile,fax,address,memo FROM sys_depart
|
||||
WHERE
|
||||
1=1
|
||||
<if test="null != tenantId and 0 != tenantId">
|
||||
AND tenant_id = #{tenantId}
|
||||
</if>
|
||||
AND
|
||||
<choose>
|
||||
<when test="parentId != null and parentId != ''">
|
||||
parent_id = #{parentId}
|
||||
</when>
|
||||
<otherwise>
|
||||
parent_id IS NULL OR parent_id=''
|
||||
</otherwise>
|
||||
</choose>
|
||||
ORDER BY depart_order DESC
|
||||
</select>
|
||||
</mapper>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user