1 Commits

Author SHA1 Message Date
duhongming
3709c17e17 修复MySQL第一次启动不初始化数据库问题 2024-08-27 13:29:31 +08:00
218 changed files with 4646 additions and 5247 deletions

3
.gitignore vendored
View File

@@ -43,4 +43,5 @@ nbdist/
!*/build/*.java !*/build/*.java
!*/build/*.html !*/build/*.html
!*/build/*.xml !*/build/*.xml
docker

View File

@@ -1,11 +1,11 @@
<p align="center"> <p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png"> <img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png">
</p> </p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.7</h1> <h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.4</h1>
<h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4> <h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4>
<p align="center"> <p align="center">
<a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a>
<a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.7-brightgreen.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.4-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p> </p>
@@ -17,9 +17,12 @@
* 后端采用Spring Boot、Spring Cloud & Alibaba。 * 后端采用Spring Boot、Spring Cloud & Alibaba。
* 注册中心、配置中心选型Nacos权限认证使用Redis。 * 注册中心、配置中心选型Nacos权限认证使用Redis。
* 流量控制框架选型Sentinel分布式事务选型Seata。 * 流量控制框架选型Sentinel分布式事务选型Seata。
* 提供了技术栈Vue3 Element Plus Vite的 [RuoYi-Cloud-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Cloud-Vue3)版本以及技术栈TypeScript[RuoYi-Cloud-Vue3-TypeScript](https://gitcode.com/yangzongzhuan/RuoYi-Cloud-Vue3/tree/typescript)版本,两者保持同步更新。 * 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev)版本[RuoYi-Cloud-Vue3](https://github.com/yangzongzhuan/RuoYi-Cloud-Vue3)保持同步更新。
* 提供了适配 Spring Boot 3 的版本分支 [RuoYi-Cloud (springboot3)](https://gitee.com/y_project/RuoYi-Cloud/tree/springboot3),与 Oracle数据库版本 [RuoYi-Cloud-Oracle](https://gitcode.com/yangzongzhuan/RuoYi-Cloud-Oracle),均保持同步更新。 * 如需不分离应用,请移步 [RuoYi](https://gitee.com/y_project/RuoYi),如需分离应用,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)
* 阿里云优惠券[点我进入](http://aly.ruoyi.vip),腾讯云优惠券[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp; * 阿里云折扣场[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp;
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)&nbsp;&nbsp;
#### 友情链接 [若依/RuoYi-Cloud](https://gitee.com/zhangmrit/ruoyi-cloud) Ant Design版本。
## 系统模块 ## 系统模块
@@ -38,7 +41,6 @@ com.ruoyi
│ └── ruoyi-common-redis // 缓存服务 │ └── ruoyi-common-redis // 缓存服务
│ └── ruoyi-common-seata // 分布式事务 │ └── ruoyi-common-seata // 分布式事务
│ └── ruoyi-common-security // 安全模块 │ └── ruoyi-common-security // 安全模块
│ └── ruoyi-common-sensitive // 数据脱敏
│ └── ruoyi-common-swagger // 系统接口 │ └── ruoyi-common-swagger // 系统接口
├── ruoyi-modules // 业务模块 ├── ruoyi-modules // 业务模块
│ └── ruoyi-system // 系统模块 [9201] │ └── ruoyi-system // 系统模块 [9201]
@@ -74,21 +76,6 @@ com.ruoyi
16. 在线构建器拖动表单元素生成相应的HTML代码。 16. 在线构建器拖动表单元素生成相应的HTML代码。
17. 连接池监视监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈。 17. 连接池监视监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈。
# 版本对比
RuoYi-Cloud 前端项目的三个主要演进版本,方便你直观对比其技术栈差异(并行开发维护)。
| 项目名称 | **RuoYi-Cloud** | **RuoYi-Cloud-Vue3** | **RuoYi-Cloud-Vue3-TypeScript** |
| :--- | :--- | :--- | :--- |
| **前端框架** | Vue 2 | Vue 3 | Vue 3 |
| **脚本语言** | JavaScript | JavaScript | TypeScript |
| **构建工具** | Vue CLI | Vite | Vite |
| **UI 组件库** | Element UI | Element Plus | Element Plus |
| **状态管理** | Vuex | Pinia | Pinia |
| **路由管理** | Vue Router 3 | Vue Router 4 | Vue Router 4 |
| **核心特点** | 1. 技术栈经典稳定<br>2. 社区资料丰富<br>3. 当前维护重心已转移 | 1. 现代前端技术栈<br>2. 开发体验与性能更优<br>3. 官方主推的活跃版本 | 1. 类型加持,减少沟通成本<br>2. 开发时有提示,效率更高<br>3. 多人协作企业级开发项目 |
| **仓库地址** | [RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud) | [RuoYi-Cloud-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Cloud-Vue3) | [RuoYi-Cloud-Vue3-TypeScript](https://gitcode.com/yangzongzhuan/RuoYi-Cloud-Vue3/tree/typescript) |
## 在线体验 ## 在线体验
- admin/admin123 - admin/admin123
@@ -141,4 +128,4 @@ RuoYi-Cloud 前端项目的三个主要演进版本,方便你直观对比其
## 若依微服务交流群 ## 若依微服务交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/已满-158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) [![加入QQ群](https://img.shields.io/badge/112869560-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Kuaw0Xdlw2Nlgn6s8h9elzuquHGxGObD&authKey=cSrQcWQ%2BzQZAFFrwxaR%2BbzcumX4WRduZnd1O6JO1dlclQMiu%2BKwxAy8t2JfNp67V&noverify=0&group_code=112869560) 点击按钮入群。 QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) 点击按钮入群。

View File

@@ -9,8 +9,9 @@ usage() {
# copy sql # copy sql
echo "begin copy sql " echo "begin copy sql "
cp ../sql/ry_20250523.sql ./mysql/db cp ../sql/ry_*.sql ./mysql/db
cp ../sql/ry_config_20250902.sql ./mysql/db cp ../sql/ry_config_*.sql ./mysql/db
cp ../sql/ry_seata_*.sql ./mysql/db
# copy html # copy html
echo "begin copy html " echo "begin copy html "

View File

@@ -27,6 +27,7 @@ services:
- ./mysql/conf:/etc/mysql/conf.d - ./mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/logs - ./mysql/logs:/logs
- ./mysql/data:/var/lib/mysql - ./mysql/data:/var/lib/mysql
- ./mysql/db:/docker-entrypoint-initdb.d
command: [ command: [
'mysqld', 'mysqld',
'--innodb-buffer-pool-size=80M', '--innodb-buffer-pool-size=80M',

View File

@@ -29,7 +29,7 @@ http {
} }
# 避免actuator暴露 # 避免actuator暴露
if ($uri ~ "/actuator") { if ($request_uri ~ "/actuator") {
return 403; return 403;
} }

73
pom.xml
View File

@@ -6,45 +6,43 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依微服务系统</description> <description>若依微服务系统</description>
<properties> <properties>
<ruoyi.version>3.6.7</ruoyi.version> <ruoyi.version>3.6.4</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<spring-boot.version>2.7.18</spring-boot.version> <spring-boot.version>2.7.18</spring-boot.version>
<spring-cloud.version>2021.0.9</spring-cloud.version> <spring-cloud.version>2021.0.8</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.6.1</spring-cloud-alibaba.version> <spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
<spring-boot-admin.version>2.7.16</spring-boot-admin.version> <spring-framework.version>5.3.33</spring-framework.version>
<spring-boot-admin.version>2.7.15</spring-boot-admin.version>
<swagger.fox.version>3.0.0</swagger.fox.version>
<swagger.core.version>1.6.2</swagger.core.version>
<tobato.version>1.27.2</tobato.version> <tobato.version>1.27.2</tobato.version>
<kaptcha.version>2.3.3</kaptcha.version> <kaptcha.version>2.3.3</kaptcha.version>
<pagehelper.boot.version>2.0.0</pagehelper.boot.version> <pagehelper.boot.version>2.0.0</pagehelper.boot.version>
<druid.version>1.2.27</druid.version> <druid.version>1.2.23</druid.version>
<dynamic-ds.version>4.3.1</dynamic-ds.version> <dynamic-ds.version>4.2.0</dynamic-ds.version>
<commons.io.version>2.21.0</commons.io.version> <commons.io.version>2.13.0</commons.io.version>
<velocity.version>2.3</velocity.version> <velocity.version>2.3</velocity.version>
<fastjson.version>2.0.60</fastjson.version> <fastjson.version>2.0.43</fastjson.version>
<jjwt.version>0.9.1</jjwt.version> <jjwt.version>0.9.1</jjwt.version>
<minio.version>8.2.2</minio.version> <minio.version>8.2.2</minio.version>
<poi.version>4.1.2</poi.version> <poi.version>4.1.2</poi.version>
<springdoc.version>1.6.9</springdoc.version>
<transmittable-thread-local.version>2.14.4</transmittable-thread-local.version> <transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
<!-- override dependency version -->
<tomcat.version>9.0.112</tomcat.version>
<logback.version>1.2.13</logback.version>
<spring-framework.version>5.3.39</spring-framework.version>
</properties> </properties>
<!-- 依赖声明 --> <!-- 依赖声明 -->
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<!-- 覆盖SpringFramework的依赖配置--> <!-- SpringFramework的依赖配置-->
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId> <artifactId>spring-framework-bom</artifactId>
@@ -80,38 +78,6 @@
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!-- 覆盖logback的依赖配置-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- 覆盖tomcat的依赖配置-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat.version}</version>
</dependency>
<!-- FastDFS 分布式文件系统 --> <!-- FastDFS 分布式文件系统 -->
<dependency> <dependency>
<groupId>com.github.tobato</groupId> <groupId>com.github.tobato</groupId>
@@ -119,11 +85,16 @@
<version>${tobato.version}</version> <version>${tobato.version}</version>
</dependency> </dependency>
<!-- Springdoc webmvc 依赖配置 --> <!-- Swagger 依赖配置 -->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>io.swagger</groupId>
<artifactId>springdoc-openapi-ui</artifactId> <artifactId>swagger-models</artifactId>
<version>${springdoc.version}</version> <version>${swagger.core.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger.core.version}</version>
</dependency> </dependency>
<!-- 验证码 --> <!-- 验证码 -->

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api</artifactId> <artifactId>ruoyi-api</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -2,9 +2,7 @@ package com.ruoyi.system.api;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.constant.ServiceNameConstants; import com.ruoyi.common.core.constant.ServiceNameConstants;
@@ -28,13 +26,4 @@ public interface RemoteFileService
*/ */
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file); public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file);
/**
* 删除文件
*
* @param fileUrl 文件地址
* @return 结果
*/
@DeleteMapping(value = "/delete", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public R<Boolean> delete(@RequestParam("fileUrl") String fileUrl);
} }

View File

@@ -8,7 +8,6 @@ import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.annotation.Excel; import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.annotation.Excel.ColumnType; import com.ruoyi.common.core.annotation.Excel.ColumnType;
import com.ruoyi.common.core.annotation.Excel.Type; import com.ruoyi.common.core.annotation.Excel.Type;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.annotation.Excels; import com.ruoyi.common.core.annotation.Excels;
import com.ruoyi.common.core.web.domain.BaseEntity; import com.ruoyi.common.core.web.domain.BaseEntity;
import com.ruoyi.common.core.xss.Xss; import com.ruoyi.common.core.xss.Xss;
@@ -56,8 +55,8 @@ public class SysUser extends BaseEntity
/** 密码 */ /** 密码 */
private String password; private String password;
/** 号状态0正常 1停用 */ /** 号状态0正常 1停用 */
@Excel(name = "号状态", readConverterExp = "0=正常,1=停用") @Excel(name = "号状态", readConverterExp = "0=正常,1=停用")
private String status; private String status;
/** 删除标志0代表存在 2代表删除 */ /** 删除标志0代表存在 2代表删除 */
@@ -71,9 +70,6 @@ public class SysUser extends BaseEntity
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
private Date loginDate; private Date loginDate;
/** 密码最后更新时间 */
private Date pwdUpdateDate;
/** 部门对象 */ /** 部门对象 */
@Excels({ @Excels({
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
@@ -115,7 +111,12 @@ public class SysUser extends BaseEntity
public boolean isAdmin() public boolean isAdmin()
{ {
return UserConstants.isAdmin(userId); return isAdmin(this.userId);
}
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
} }
public Long getDeptId() public Long getDeptId()
@@ -246,16 +247,6 @@ public class SysUser extends BaseEntity
this.loginDate = loginDate; this.loginDate = loginDate;
} }
public Date getPwdUpdateDate()
{
return pwdUpdateDate;
}
public void setPwdUpdateDate(Date pwdUpdateDate)
{
this.pwdUpdateDate = pwdUpdateDate;
}
public SysDept getDept() public SysDept getDept()
{ {
return dept; return dept;
@@ -305,7 +296,6 @@ public class SysUser extends BaseEntity
{ {
this.roleId = roleId; this.roleId = roleId;
} }
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -322,7 +312,6 @@ public class SysUser extends BaseEntity
.append("delFlag", getDelFlag()) .append("delFlag", getDelFlag())
.append("loginIp", getLoginIp()) .append("loginIp", getLoginIp())
.append("loginDate", getLoginDate()) .append("loginDate", getLoginDate())
.append("pwdUpdateDate", getPwdUpdateDate())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
.append("updateBy", getUpdateBy()) .append("updateBy", getUpdateBy())

View File

@@ -30,12 +30,6 @@ public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileServ
{ {
return R.fail("上传文件失败:" + throwable.getMessage()); return R.fail("上传文件失败:" + throwable.getMessage());
} }
@Override
public R<Boolean> delete(String fileUrl)
{
return R.fail("删除文件失败:" + throwable.getMessage());
}
}; };
} }
} }

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -74,11 +74,17 @@ public class SysLoginService
// 查询用户信息 // 查询用户信息
R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER); R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
{
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
throw new ServiceException("登录用户:" + username + " 不存在");
}
if (R.FAIL == userResult.getCode()) if (R.FAIL == userResult.getCode())
{ {
throw new ServiceException(userResult.getMsg()); throw new ServiceException(userResult.getMsg());
} }
LoginUser userInfo = userResult.getData(); LoginUser userInfo = userResult.getData();
SysUser user = userResult.getData().getSysUser(); SysUser user = userResult.getData().getSysUser();
if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
@@ -143,7 +149,6 @@ public class SysLoginService
SysUser sysUser = new SysUser(); SysUser sysUser = new SysUser();
sysUser.setUserName(username); sysUser.setUserName(username);
sysUser.setNickName(username); sysUser.setNickName(username);
sysUser.setPwdUpdateDate(DateUtils.getNowDate());
sysUser.setPassword(SecurityUtils.encryptPassword(password)); sysUser.setPassword(SecurityUtils.encryptPassword(password));
R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER); R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -107,6 +107,12 @@
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
</dependency> </dependency>
<!-- Swagger -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -78,11 +78,6 @@ public @interface Excel
*/ */
public String prompt() default ""; public String prompt() default "";
/**
* 是否允许内容换行
*/
public boolean wrapText() default false;
/** /**
* 设置只能选择不能输入的列内容. * 设置只能选择不能输入的列内容.
*/ */

View File

@@ -87,16 +87,6 @@ public class Constants
*/ */
public static final String LOGIN_FAIL = "Error"; public static final String LOGIN_FAIL = "Error";
/**
* 所有权限标识
*/
public static final String ALL_PERMISSION = "*:*:*";
/**
* 管理员角色权限标识
*/
public static final String SUPER_ADMIN = "admin";
/** /**
* 当前记录起始索引 * 当前记录起始索引
*/ */
@@ -130,7 +120,7 @@ public class Constants
/** /**
* 自动识别json对象白名单配置仅允许解析的包名范围越小越安全 * 自动识别json对象白名单配置仅允许解析的包名范围越小越安全
*/ */
public static final String[] JSON_WHITELIST_STR = { "com.ruoyi" }; public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" };
/** /**
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)

View File

@@ -20,7 +20,7 @@ public class SecurityConstants
/** /**
* 授权信息字段 * 授权信息字段
*/ */
public static final String AUTHORIZATION_HEADER = "Authorization"; public static final String AUTHORIZATION_HEADER = "authorization";
/** /**
* 请求来源 * 请求来源

View File

@@ -7,6 +7,11 @@ package com.ruoyi.common.core.constant;
*/ */
public class TokenConstants public class TokenConstants
{ {
/**
* 令牌自定义标识
*/
public static final String AUTHENTICATION = "Authorization";
/** /**
* 令牌前缀 * 令牌前缀
*/ */

View File

@@ -21,9 +21,6 @@ public class UserConstants
/** 用户封禁状态 */ /** 用户封禁状态 */
public static final String USER_DISABLE = "1"; public static final String USER_DISABLE = "1";
/** 角色正常状态 */
public static final String ROLE_NORMAL = "0";
/** 角色封禁状态 */ /** 角色封禁状态 */
public static final String ROLE_DISABLE = "1"; public static final String ROLE_DISABLE = "1";
@@ -80,9 +77,4 @@ public class UserConstants
public static final int PASSWORD_MIN_LENGTH = 5; public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20; public static final int PASSWORD_MAX_LENGTH = 20;
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
} }

View File

@@ -3,7 +3,7 @@ package com.ruoyi.common.core.exception.file;
import java.util.Arrays; import java.util.Arrays;
/** /**
* 文件上传无效扩展名异常类 * 文件上传异常类
* *
* @author ruoyi * @author ruoyi
*/ */

View File

@@ -540,9 +540,9 @@ public class Convert
/** /**
* 转换为boolean<br> * 转换为boolean<br>
* String支持的值为true、false、yes、ok、no、1、0、是、否, 如果给定的值为空,或者转换失败,返回默认值<br> * String支持的值为true、false、yes、ok、no1,0 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错 * 转换失败不会报错
* *
* @param value 被转换的值 * @param value 被转换的值
* @param defaultValue 转换错误时的默认值 * @param defaultValue 转换错误时的默认值
* @return 结果 * @return 结果
@@ -569,12 +569,10 @@ public class Convert
case "yes": case "yes":
case "ok": case "ok":
case "1": case "1":
case "":
return true; return true;
case "false": case "false":
case "no": case "no":
case "0": case "0":
case "":
return false; return false;
default: default:
return defaultValue; return defaultValue;

View File

@@ -136,14 +136,6 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
return new Date(time); return new Date(time);
} }
/**
* 计算相差天数
*/
public static int differentDaysByMillisecond(Date date1, Date date2)
{
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
}
/** /**
* 计算时间差 * 计算时间差
* *

View File

@@ -283,32 +283,6 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return str.substring(start, end); return str.substring(start, end);
} }
/**
* 在字符串中查找第一个出现的 `open` 和最后一个出现的 `close` 之间的子字符串
*
* @param str 要截取的字符串
* @param open 起始字符串
* @param close 结束字符串
* @return 截取结果
*/
public static String substringBetweenLast(final String str, final String open, final String close)
{
if (isEmpty(str) || isEmpty(open) || isEmpty(close))
{
return NULLSTR;
}
final int start = str.indexOf(open);
if (start != INDEX_NOT_FOUND)
{
final int end = str.lastIndexOf(close);
if (end != INDEX_NOT_FOUND)
{
return str.substring(start + open.length(), end);
}
}
return NULLSTR;
}
/** /**
* 判断是否为空,并且不是空白字符 * 判断是否为空,并且不是空白字符
* *

View File

@@ -114,20 +114,20 @@ public class FileUtils
} }
/** /**
* 校验文件路径合法性(安全性与扩展名) * 检查文件是否可下载
* *
* @param fileUrl 待校验的文件地址 * @param resource 需要下载的文件
* @return true 正常 false 非法 * @return true 正常 false 非法
*/ */
public static boolean validateFilePath(String fileUrl) public static boolean checkAllowDownload(String resource)
{ {
// 禁止目录上跳级别 // 禁止目录上跳级别
if (StringUtils.contains(fileUrl, "..")) if (StringUtils.contains(resource, ".."))
{ {
return false; return false;
} }
// 判断是否在允许下载的文件规则内 // 判断是否在允许下载的文件规则内
return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(fileUrl)); return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource));
} }
/** /**

View File

@@ -73,8 +73,6 @@ public class ExcelUtil<T>
{ {
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
public static final String SEPARATOR = ",";
public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
@@ -147,28 +145,28 @@ public class ExcelUtil<T>
/** /**
* 对象的子列表方法 * 对象的子列表方法
*/ */
private Map<String, Method> subMethods; private Method subMethod;
/** /**
* 对象的子列表属性 * 对象的子列表属性
*/ */
private Map<String, List<Field>> subFieldsMap; private List<Field> subFields;
/** /**
* 统计列表 * 统计列表
*/ */
private Map<Integer, Double> statistics = new HashMap<Integer, Double>(); private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
/**
* 数字格式
*/
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/** /**
* 实体对象 * 实体对象
*/ */
public Class<T> clazz; public Class<T> clazz;
/**
* 需要显示列属性
*/
public String[] includeFields;
/** /**
* 需要排除列属性 * 需要排除列属性
*/ */
@@ -179,20 +177,11 @@ public class ExcelUtil<T>
this.clazz = clazz; this.clazz = clazz;
} }
/**
* 仅在Excel中显示列属性
*
* @param fields 列属性名 示例[单个"name"/多个"id","name"]
*/
public void showColumn(String... fields)
{
this.includeFields = fields;
}
/** /**
* 隐藏Excel中列属性 * 隐藏Excel中列属性
* *
* @param fields 列属性名 示例[单个"name"/多个"id","name"] * @param fields 列属性名 示例[单个"name"/多个"id","name"]
* @throws Exception
*/ */
public void hideColumn(String... fields) public void hideColumn(String... fields)
{ {
@@ -222,20 +211,19 @@ public class ExcelUtil<T>
{ {
if (StringUtils.isNotEmpty(title)) if (StringUtils.isNotEmpty(title))
{ {
subMergedFirstRowNum++;
subMergedLastRowNum++;
int titleLastCol = this.fields.size() - 1; int titleLastCol = this.fields.size() - 1;
if (isSubList()) if (isSubList())
{ {
for (List<Field> currentSubFields : subFieldsMap.values()) titleLastCol = titleLastCol + subFields.size() - 1;
{
titleLastCol = titleLastCol + currentSubFields.size() - 1;
}
} }
Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
titleRow.setHeightInPoints(30); titleRow.setHeightInPoints(30);
Cell titleCell = titleRow.createCell(0); Cell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(styles.get("title")); titleCell.setCellStyle(styles.get("title"));
titleCell.setCellValue(title); titleCell.setCellValue(title);
sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol)); sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol));
} }
} }
@@ -246,32 +234,23 @@ public class ExcelUtil<T>
{ {
if (isSubList()) if (isSubList())
{ {
subMergedFirstRowNum++;
subMergedLastRowNum++;
Row subRow = sheet.createRow(rownum); Row subRow = sheet.createRow(rownum);
int column = 0; int excelNum = 0;
for (Object[] objects : fields) for (Object[] objects : fields)
{ {
Field field = (Field) objects[0];
Excel attr = (Excel) objects[1]; Excel attr = (Excel) objects[1];
CellStyle cellStyle = styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())); Cell headCell1 = subRow.createCell(excelNum);
if (Collection.class.isAssignableFrom(field.getType())) headCell1.setCellValue(attr.name());
{ headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
Cell cell = subRow.createCell(column); excelNum++;
cell.setCellValue(attr.name()); }
cell.setCellStyle(cellStyle); int headFirstRow = excelNum - 1;
int subFieldSize = subFieldsMap != null ? subFieldsMap.get(field.getName()).size() : 0; int headLastRow = headFirstRow + subFields.size() - 1;
if (subFieldSize > 1) if (headLastRow > headFirstRow)
{ {
CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1); sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow));
sheet.addMergedRegion(cellAddress);
}
column += subFieldSize;
}
else
{
Cell cell = subRow.createCell(column++);
cell.setCellValue(attr.name());
cell.setCellStyle(cellStyle);
}
} }
rownum++; rownum++;
} }
@@ -284,23 +263,11 @@ public class ExcelUtil<T>
* @return 转换后集合 * @return 转换后集合
*/ */
public List<T> importExcel(InputStream is) public List<T> importExcel(InputStream is)
{
return importExcel(is, 0);
}
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum)
{ {
List<T> list = null; List<T> list = null;
try try
{ {
list = importExcel(StringUtils.EMPTY, is, titleNum); list = importExcel(is, 0);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -314,6 +281,18 @@ public class ExcelUtil<T>
return list; return list;
} }
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum) throws Exception
{
return importExcel(StringUtils.EMPTY, is, titleNum);
}
/** /**
* 对excel表单指定表格索引名转换成list * 对excel表单指定表格索引名转换成list
* *
@@ -342,11 +321,7 @@ public class ExcelUtil<T>
Map<String, Integer> cellMap = new HashMap<String, Integer>(); Map<String, Integer> cellMap = new HashMap<String, Integer>();
// 获取表头 // 获取表头
Row heard = sheet.getRow(titleNum); Row heard = sheet.getRow(titleNum);
if (heard == null) for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
{
throw new UtilException("文件标题行为空请检查Excel文件格式");
}
for (int i = 0; i < heard.getLastCellNum(); i++)
{ {
Cell cell = heard.getCell(i); Cell cell = heard.getCell(i);
if (StringUtils.isNotNull(cell)) if (StringUtils.isNotNull(cell))
@@ -354,6 +329,10 @@ public class ExcelUtil<T>
String value = this.getCellValue(heard, i).toString(); String value = this.getCellValue(heard, i).toString();
cellMap.put(value, i); cellMap.put(value, i);
} }
else
{
cellMap.put(null, i);
}
} }
// 有数据时才处理 得到类的所有field. // 有数据时才处理 得到类的所有field.
List<Object[]> fields = this.getFields(); List<Object[]> fields = this.getFields();
@@ -391,7 +370,7 @@ public class ExcelUtil<T>
if (String.class == fieldType) if (String.class == fieldType)
{ {
String s = Convert.toStr(val); String s = Convert.toStr(val);
if (s.matches("^\\d+\\.0$")) if (StringUtils.endsWith(s, ".0"))
{ {
val = StringUtils.substringBefore(s, ".0"); val = StringUtils.substringBefore(s, ".0");
} }
@@ -566,8 +545,7 @@ public class ExcelUtil<T>
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()))
{ {
List<Field> currentSubFields = subFieldsMap.get(field.getName()); for (Field subField : subFields)
for (Field subField : currentSubFields)
{ {
Excel subExcel = subField.getAnnotation(Excel.class); Excel subExcel = subField.getAnnotation(Excel.class);
this.createHeadCell(subExcel, row, column++); this.createHeadCell(subExcel, row, column++);
@@ -580,7 +558,7 @@ public class ExcelUtil<T>
} }
if (Type.EXPORT.equals(type)) if (Type.EXPORT.equals(type))
{ {
fillExcelData(index); fillExcelData(index, row);
addStatisticsRow(); addStatisticsRow();
} }
} }
@@ -590,98 +568,71 @@ public class ExcelUtil<T>
* 填充excel数据 * 填充excel数据
* *
* @param index 序号 * @param index 序号
* @param row 单元格行
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void fillExcelData(int index) public void fillExcelData(int index, Row row)
{ {
int startNo = index * sheetSize; int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size()); int endNo = Math.min(startNo + sheetSize, list.size());
int currentRowNum = rownum + 1; // 从标题行后开始 int rowNo = (1 + rownum) - startNo;
for (int i = startNo; i < endNo; i++) for (int i = startNo; i < endNo; i++)
{ {
Row row = sheet.createRow(currentRowNum); rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;
row = sheet.createRow(rowNo);
// 得到导出对象.
T vo = (T) list.get(i); T vo = (T) list.get(i);
Collection<?> subList = null;
if (isSubList())
{
if (isSubListValue(vo))
{
subList = getListCellValue(vo);
subMergedLastRowNum = subMergedLastRowNum + subList.size();
}
else
{
subMergedFirstRowNum++;
subMergedLastRowNum++;
}
}
int column = 0; int column = 0;
int maxSubListSize = getCurrentMaxSubListSize(vo);
for (Object[] os : fields) for (Object[] os : fields)
{ {
Field field = (Field) os[0]; Field field = (Field) os[0];
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList))
{ {
try boolean subFirst = false;
for (Object obj : subList)
{ {
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel); if (subFirst)
List<Field> currentSubFields = subFieldsMap.get(field.getName());
if (subList != null && !subList.isEmpty())
{ {
int subIndex = 0; rowNo++;
for (Object subVo : subList) row = sheet.createRow(rowNo);
{
Row subRow = sheet.getRow(currentRowNum + subIndex);
if (subRow == null)
{
subRow = sheet.createRow(currentRowNum + subIndex);
}
int subColumn = column;
for (Field subField : currentSubFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
}
subIndex++;
}
} }
column += currentSubFields.size(); List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);
} int subIndex = 0;
catch (Exception e) for (Field subField : subFields)
{ {
log.error("填充集合数据失败", e); if (subField.isAnnotationPresent(Excel.class))
{
subField.setAccessible(true);
Excel attr = subField.getAnnotation(Excel.class);
this.addCell(attr, row, (T) obj, subField, column + subIndex);
}
subIndex++;
}
subFirst = true;
} }
this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();
} }
else else
{ {
// 创建单元格并设置值 this.addCell(excel, row, vo, field, column++);
addCell(excel, row, vo, field, column);
if (maxSubListSize > 1 && excel.needMerge())
{
sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));
}
column++;
}
}
currentRowNum += maxSubListSize;
}
}
/**
* 获取子列表最大数
*/
private int getCurrentMaxSubListSize(T vo)
{
int maxSubListSize = 1;
for (Object[] os : fields)
{
Field field = (Field) os[0];
if (Collection.class.isAssignableFrom(field.getType()))
{
try
{
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, (Excel) os[1]);
if (subList != null && !subList.isEmpty())
{
maxSubListSize = Math.max(maxSubListSize, subList.size());
}
}
catch (Exception e)
{
log.error("获取集合大小失败", e);
} }
} }
} }
return maxSubListSize;
} }
/** /**
@@ -726,7 +677,6 @@ public class ExcelUtil<T>
style = wb.createCellStyle(); style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER); style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(dataFormat.getFormat("######0.00"));
Font totalFont = wb.createFont(); Font totalFont = wb.createFont();
totalFont.setFontName("Arial"); totalFont.setFontName("Arial");
totalFont.setFontHeightInPoints((short) 10); totalFont.setFontHeightInPoints((short) 10);
@@ -817,7 +767,7 @@ public class ExcelUtil<T>
*/ */
public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel) public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
{ {
String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText()); String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType());
if (!styles.containsKey(key)) if (!styles.containsKey(key))
{ {
CellStyle style = wb.createCellStyle(); CellStyle style = wb.createCellStyle();
@@ -833,7 +783,6 @@ public class ExcelUtil<T>
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND); style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(excel.backgroundColor().getIndex()); style.setFillForegroundColor(excel.backgroundColor().getIndex());
style.setWrapText(excel.wrapText());
Font dataFont = wb.createFont(); Font dataFont = wb.createFont();
dataFont.setFontName("Arial"); dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10); dataFont.setFontHeightInPoints((short) 10);
@@ -862,7 +811,7 @@ public class ExcelUtil<T>
if (isSubList()) if (isSubList())
{ {
// 填充默认样式,防止合并单元格样式失效 // 填充默认样式,防止合并单元格样式失效
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText()))); sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
if (attr.needMerge()) if (attr.needMerge())
{ {
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
@@ -987,14 +936,12 @@ public class ExcelUtil<T>
{ {
// 创建cell // 创建cell
cell = row.createCell(column); cell = row.createCell(column);
if (isSubListValue(vo) && getListCellValue(vo) > 1 && attr.needMerge()) if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
{ {
if (subMergedLastRowNum >= subMergedFirstRowNum) CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
{ sheet.addMergedRegion(cellAddress);
sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
}
} }
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText()))); cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
// 用于读取对象中的属性 // 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr); Object value = getTargetValue(vo, field, attr);
@@ -1003,7 +950,6 @@ public class ExcelUtil<T>
String separator = attr.separator(); String separator = attr.separator();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{ {
cell.setCellStyle(createCellStyle(cell.getCellStyle(), dateFormat));
cell.setCellValue(parseDateToStr(dateFormat, value)); cell.setCellValue(parseDateToStr(dateFormat, value));
} }
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
@@ -1033,21 +979,6 @@ public class ExcelUtil<T>
return cell; return cell;
} }
/**
* 使用自定义格式,同时避免样式污染
*
* @param cellStyle 从此样式复制
* @param format 格式匹配的字符串
* @return 格式化后CellStyle对象
*/
private CellStyle createCellStyle(CellStyle cellStyle, String format)
{
CellStyle style = wb.createCellStyle();
style.cloneStyleFrom(cellStyle);
style.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat(format));
return style;
}
/** /**
* 设置 POI XSSFSheet 单元格提示或选择框 * 设置 POI XSSFSheet 单元格提示或选择框
* *
@@ -1099,36 +1030,18 @@ public class ExcelUtil<T>
public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
{ {
String hideSheetName = "combo_" + firstCol + "_" + endCol; String hideSheetName = "combo_" + firstCol + "_" + endCol;
Sheet hideSheet = null; Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据
String hideSheetDataName = hideSheetName + "_data"; for (int i = 0; i < textlist.length; i++)
Name name = wb.getName(hideSheetDataName);
if (name != null)
{ {
// 名称已存在尝试从名称的引用中找到sheet名称 hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
String refersToFormula = name.getRefersToFormula();
if (StringUtils.isNotEmpty(refersToFormula) && refersToFormula.contains("!"))
{
String sheetNameFromFormula = refersToFormula.substring(0, refersToFormula.indexOf("!"));
hideSheet = wb.getSheet(sheetNameFromFormula);
}
} }
// 创建名称,可被其他单元格引用
if (hideSheet == null) Name name = wb.createName();
{ name.setNameName(hideSheetName + "_data");
hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据 name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
for (int i = 0; i < textlist.length; i++)
{
hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
}
// 创建名称,可被其他单元格引用
name = wb.createName();
name.setNameName(hideSheetDataName);
name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
}
DataValidationHelper helper = sheet.getDataValidationHelper(); DataValidationHelper helper = sheet.getDataValidationHelper();
// 加载下拉列表内容 // 加载下拉列表内容
DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetDataName); DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象 // 数据有效性对象
@@ -1166,7 +1079,7 @@ public class ExcelUtil<T>
public static String convertByExp(String propertyValue, String converterExp, String separator) public static String convertByExp(String propertyValue, String converterExp, String separator)
{ {
StringBuilder propertyString = new StringBuilder(); StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(SEPARATOR); String[] convertSource = converterExp.split(",");
for (String item : convertSource) for (String item : convertSource)
{ {
String[] itemArray = item.split("="); String[] itemArray = item.split("=");
@@ -1203,7 +1116,7 @@ public class ExcelUtil<T>
public static String reverseByExp(String propertyValue, String converterExp, String separator) public static String reverseByExp(String propertyValue, String converterExp, String separator)
{ {
StringBuilder propertyString = new StringBuilder(); StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(SEPARATOR); String[] convertSource = converterExp.split(",");
for (String item : convertSource) for (String item : convertSource)
{ {
String[] itemArray = item.split("="); String[] itemArray = item.split("=");
@@ -1291,7 +1204,7 @@ public class ExcelUtil<T>
{ {
cell = row.createCell(key); cell = row.createCell(key);
cell.setCellStyle(styles.get("total")); cell.setCellStyle(styles.get("total"));
cell.setCellValue(statistics.get(key)); cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
} }
statistics.clear(); statistics.clear();
} }
@@ -1308,7 +1221,6 @@ public class ExcelUtil<T>
*/ */
private Object getTargetValue(T vo, Field field, Excel excel) throws Exception private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
{ {
field.setAccessible(true);
Object o = field.get(vo); Object o = field.get(vo);
if (StringUtils.isNotEmpty(excel.targetAttr())) if (StringUtils.isNotEmpty(excel.targetAttr()))
{ {
@@ -1366,90 +1278,50 @@ public class ExcelUtil<T>
{ {
List<Object[]> fields = new ArrayList<Object[]>(); List<Object[]> fields = new ArrayList<Object[]>();
List<Field> tempFields = new ArrayList<>(); List<Field> tempFields = new ArrayList<>();
subFieldsMap = new HashMap<>();
subMethods = new HashMap<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (StringUtils.isNotEmpty(includeFields)) for (Field field : tempFields)
{ {
for (Field field : tempFields) if (!ArrayUtils.contains(this.excludeFields, field.getName()))
{ {
if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class)) // 单注解
if (field.isAnnotationPresent(Excel.class))
{ {
addField(fields, field); Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
if (Collection.class.isAssignableFrom(field.getType()))
{
subMethod = getSubMethod(field.getName(), clazz);
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
}
} }
}
} // 多注解
else if (StringUtils.isNotEmpty(excludeFields)) if (field.isAnnotationPresent(Excels.class))
{
for (Field field : tempFields)
{
if (!ArrayUtils.contains(this.excludeFields, field.getName()))
{ {
addField(fields, field); Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
{
if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{
field.setAccessible(true);
fields.add(new Object[] { field, attr });
}
}
} }
} }
} }
else
{
for (Field field : tempFields)
{
addField(fields, field);
}
}
return fields; return fields;
} }
/**
* 添加字段信息
*/
public void addField(List<Object[]> fields, Field field)
{
// 单注解
if (field.isAnnotationPresent(Excel.class))
{
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
{
fields.add(new Object[] { field, attr });
}
if (Collection.class.isAssignableFrom(field.getType()))
{
String fieldName = field.getName();
subMethods.put(fieldName, getSubMethod(fieldName, clazz));
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
subFieldsMap.put(fieldName, FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class));
}
}
// 多注解
if (field.isAnnotationPresent(Excels.class))
{
Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
{
if (StringUtils.isNotEmpty(includeFields))
{
if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{
fields.add(new Object[] { field, attr });
}
}
else
{
if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
{
fields.add(new Object[] { field, attr });
}
}
}
}
}
/** /**
* 根据注解获取最大行高 * 根据注解获取最大行高
*/ */
@@ -1488,8 +1360,7 @@ public class ExcelUtil<T>
{ {
this.sheet = wb.createSheet(); this.sheet = wb.createSheet();
this.createTitle(); this.createTitle();
int actualIndex = wb.getSheetIndex(this.sheet); wb.setSheetName(index, sheetName + index);
wb.setSheetName(actualIndex, sheetName + index);
} }
} }
@@ -1614,7 +1485,7 @@ public class ExcelUtil<T>
*/ */
public boolean isSubList() public boolean isSubList()
{ {
return !StringUtils.isEmpty(subFieldsMap); return StringUtils.isNotNull(subFields) && subFields.size() > 0;
} }
/** /**
@@ -1622,32 +1493,24 @@ public class ExcelUtil<T>
*/ */
public boolean isSubListValue(T vo) public boolean isSubListValue(T vo)
{ {
return !StringUtils.isEmpty(subFieldsMap) && getListCellValue(vo) > 0; return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
} }
/** /**
* 获取集合的值 * 获取集合的值
*/ */
public int getListCellValue(Object obj) public Collection<?> getListCellValue(Object obj)
{ {
Collection<?> value; Object value;
int max = 0;
try try
{ {
for (String s : subMethods.keySet()) value = subMethod.invoke(obj, new Object[] {});
{
value = (Collection<?>) subMethods.get(s).invoke(obj);
if (value.size() > max)
{
max = value.size();
}
}
} }
catch (Exception e) catch (Exception e)
{ {
return 0; return new ArrayList<Object>();
} }
return max; return (Collection<?>) value;
} }
/** /**

View File

@@ -13,7 +13,7 @@ public class SqlUtil
/** /**
* 定义常用的 sql关键字 * 定义常用的 sql关键字
*/ */
public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()"; public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()";
/** /**
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)

View File

@@ -343,25 +343,25 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low // time_low
builder.append(digits(mostSigBits >> 32, 8)); builder.append(digits(mostSigBits >> 32, 8));
if (!isSimple) if (false == isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// time_mid // time_mid
builder.append(digits(mostSigBits >> 16, 4)); builder.append(digits(mostSigBits >> 16, 4));
if (!isSimple) if (false == isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// time_high_and_version // time_high_and_version
builder.append(digits(mostSigBits, 4)); builder.append(digits(mostSigBits, 4));
if (!isSimple) if (false == isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// variant_and_sequence // variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4)); builder.append(digits(leastSigBits >> 48, 4));
if (!isSimple) if (false == isSimple)
{ {
builder.append('-'); builder.append('-');
} }

View File

@@ -7,17 +7,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.constant.HttpStatus; import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.PageUtils; import com.ruoyi.common.core.utils.PageUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.sql.SqlUtil;
import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableDataInfo; import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.core.web.page.TableSupport;
/** /**
* web层通用数据处理 * web层通用数据处理
@@ -53,19 +48,6 @@ public class BaseController
PageUtils.startPage(); PageUtils.startPage();
} }
/**
* 设置请求排序数据
*/
protected void startOrderBy()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy);
}
}
/** /**
* 清理分页的线程变量 * 清理分页的线程变量
*/ */

View File

@@ -37,7 +37,7 @@ public class TableDataInfo implements Serializable
* @param list 列表数据 * @param list 列表数据
* @param total 总记录数 * @param total 总记录数
*/ */
public TableDataInfo(List<?> list, long total) public TableDataInfo(List<?> list, int total)
{ {
this.rows = list; this.rows = list;
this.total = total; this.total = total;

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -6,7 +6,6 @@ import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.context.SecurityContextHolder; import com.ruoyi.common.core.context.SecurityContextHolder;
import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
@@ -74,7 +73,8 @@ public class DataScopeAspect
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
{ {
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), SecurityContextHolder.getPermission()); String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), SecurityContextHolder.getPermission());
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), controllerDataScope.userAlias(), permission); dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias(), permission);
} }
} }
} }
@@ -94,7 +94,7 @@ public class DataScopeAspect
List<String> conditions = new ArrayList<String>(); List<String> conditions = new ArrayList<String>();
List<String> scopeCustomIds = new ArrayList<String>(); List<String> scopeCustomIds = new ArrayList<String>();
user.getRoles().forEach(role -> { user.getRoles().forEach(role -> {
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && (StringUtils.isEmpty(permission) || StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))) if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{ {
scopeCustomIds.add(Convert.toStr(role.getRoleId())); scopeCustomIds.add(Convert.toStr(role.getRoleId()));
} }
@@ -103,11 +103,11 @@ public class DataScopeAspect
for (SysRole role : user.getRoles()) for (SysRole role : user.getRoles())
{ {
String dataScope = role.getDataScope(); String dataScope = role.getDataScope();
if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE)) if (conditions.contains(dataScope))
{ {
continue; continue;
} }
if (StringUtils.isNotEmpty(permission) && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{ {
continue; continue;
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -19,8 +19,6 @@ import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.ExceptionUtil;
import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.ip.IpUtils; import com.ruoyi.common.core.utils.ip.IpUtils;
@@ -48,9 +46,6 @@ public class LogAspect
/** 计算操作消耗时间 */ /** 计算操作消耗时间 */
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time"); private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
/** 参数最大长度限制 */
private static final int PARAM_MAX_LENGTH = 2000;
@Autowired @Autowired
private AsyncLogService asyncLogService; private AsyncLogService asyncLogService;
@@ -58,7 +53,7 @@ public class LogAspect
* 处理请求前执行 * 处理请求前执行
*/ */
@Before(value = "@annotation(controllerLog)") @Before(value = "@annotation(controllerLog)")
public void doBefore(JoinPoint joinPoint, Log controllerLog) public void boBefore(JoinPoint joinPoint, Log controllerLog)
{ {
TIME_THREADLOCAL.set(System.currentTimeMillis()); TIME_THREADLOCAL.set(System.currentTimeMillis());
} }
@@ -106,7 +101,7 @@ public class LogAspect
if (e != null) if (e != null)
{ {
operLog.setStatus(BusinessStatus.FAIL.ordinal()); operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StringUtils.substring(Convert.toStr(e.getMessage(), ExceptionUtil.getExceptionMessage(e)), 0, 2000)); operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
} }
// 设置方法名称 // 设置方法名称
String className = joinPoint.getTarget().getClass().getName(); String className = joinPoint.getTarget().getClass().getName();
@@ -171,14 +166,15 @@ public class LogAspect
{ {
String requestMethod = operLog.getRequestMethod(); String requestMethod = operLog.getRequestMethod();
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())) if (StringUtils.isEmpty(paramsMap)
&& (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)))
{ {
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
operLog.setOperParam(params); operLog.setOperParam(StringUtils.substring(params, 0, 2000));
} }
else else
{ {
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, PARAM_MAX_LENGTH)); operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));
} }
} }
@@ -187,7 +183,7 @@ public class LogAspect
*/ */
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
{ {
StringBuilder params = new StringBuilder(); String params = "";
if (paramsArray != null && paramsArray.length > 0) if (paramsArray != null && paramsArray.length > 0)
{ {
for (Object o : paramsArray) for (Object o : paramsArray)
@@ -197,20 +193,15 @@ public class LogAspect
try try
{ {
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames)); String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
params.append(jsonObj).append(" "); params += jsonObj.toString() + " ";
if (params.length() >= PARAM_MAX_LENGTH)
{
return StringUtils.substring(params.toString(), 0, PARAM_MAX_LENGTH);
}
} }
catch (Exception e) catch (Exception e)
{ {
log.error("请求参数拼装异常 msg:{}, 参数:{}", e.getMessage(), paramsArray, e);
} }
} }
} }
} }
return params.toString(); return params.trim();
} }
/** /**

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -56,8 +56,16 @@ public class PreAuthorizeAspect
// 注解鉴权 // 注解鉴权
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); MethodSignature signature = (MethodSignature) joinPoint.getSignature();
checkMethodAnnotation(signature.getMethod()); checkMethodAnnotation(signature.getMethod());
// 执行原有逻辑 try
return joinPoint.proceed(); {
// 执行原有逻辑
Object obj = joinPoint.proceed();
return obj;
}
catch (Throwable e)
{
throw e;
}
} }
/** /**

View File

@@ -36,11 +36,11 @@ public class TokenService
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
private final static long TOKEN_EXPIRE_TIME = CacheConstants.EXPIRATION; private final static long expireTime = CacheConstants.EXPIRATION;
private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY; private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY;
private final static Long TOKEN_REFRESH_THRESHOLD_MINUTES = CacheConstants.REFRESH_TIME * MILLIS_MINUTE; private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;
/** /**
* 创建令牌 * 创建令牌
@@ -65,7 +65,7 @@ public class TokenService
// 接口返回信息 // 接口返回信息
Map<String, Object> rspMap = new HashMap<String, Object>(); Map<String, Object> rspMap = new HashMap<String, Object>();
rspMap.put("access_token", JwtUtils.createToken(claimsMap)); rspMap.put("access_token", JwtUtils.createToken(claimsMap));
rspMap.put("expires_in", TOKEN_EXPIRE_TIME); rspMap.put("expires_in", expireTime);
return rspMap; return rspMap;
} }
@@ -147,7 +147,7 @@ public class TokenService
{ {
long expireTime = loginUser.getExpireTime(); long expireTime = loginUser.getExpireTime();
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= TOKEN_REFRESH_THRESHOLD_MINUTES) if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
{ {
refreshToken(loginUser); refreshToken(loginUser);
} }
@@ -161,10 +161,10 @@ public class TokenService
public void refreshToken(LoginUser loginUser) public void refreshToken(LoginUser loginUser)
{ {
loginUser.setLoginTime(System.currentTimeMillis()); loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + TOKEN_EXPIRE_TIME * MILLIS_MINUTE); loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
// 根据uuid将loginUser缓存 // 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken()); String userKey = getTokenKey(loginUser.getToken());
redisService.setCacheObject(userKey, loginUser, TOKEN_EXPIRE_TIME, TimeUnit.MINUTES); redisService.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
} }
private String getTokenKey(String token) private String getTokenKey(String token)

View File

@@ -4,7 +4,6 @@ import javax.servlet.http.HttpServletRequest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.TokenConstants; import com.ruoyi.common.core.constant.TokenConstants;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.context.SecurityContextHolder; import com.ruoyi.common.core.context.SecurityContextHolder;
import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
@@ -63,7 +62,7 @@ public class SecurityUtils
public static String getToken(HttpServletRequest request) public static String getToken(HttpServletRequest request)
{ {
// 从header获取token标识 // 从header获取token标识
String token = request.getHeader(SecurityConstants.AUTHORIZATION_HEADER); String token = request.getHeader(TokenConstants.AUTHENTICATION);
return replaceTokenPrefix(token); return replaceTokenPrefix(token);
} }
@@ -80,16 +79,6 @@ public class SecurityUtils
return token; return token;
} }
/**
* 是否为管理员
*
* @return 结果
*/
public static boolean isAdmin()
{
return isAdmin(getUserId());
}
/** /**
* 是否为管理员 * 是否为管理员
* *
@@ -98,7 +87,7 @@ public class SecurityUtils
*/ */
public static boolean isAdmin(Long userId) public static boolean isAdmin(Long userId)
{ {
return UserConstants.isAdmin(userId); return userId != null && 1L == userId;
} }
/** /**

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -17,10 +17,10 @@
<dependencies> <dependencies>
<!-- RuoYi Common Core --> <!-- RuoYi Common Security -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId> <artifactId>ruoyi-common-security</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -8,10 +8,10 @@ import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.common.core.context.SecurityContextHolder;
import com.ruoyi.common.sensitive.annotation.Sensitive; import com.ruoyi.common.sensitive.annotation.Sensitive;
import com.ruoyi.common.sensitive.enums.DesensitizedType; import com.ruoyi.common.sensitive.enums.DesensitizedType;
import com.ruoyi.system.api.model.LoginUser;
/** /**
* 数据脱敏序列化过滤 * 数据脱敏序列化过滤
@@ -55,9 +55,9 @@ public class SensitiveJsonSerializer extends JsonSerializer<String> implements C
{ {
try try
{ {
Long userId = SecurityContextHolder.getUserId(); LoginUser securityUser = SecurityUtils.getLoginUser();
// 管理员不脱敏 // 管理员不脱敏
return !UserConstants.isAdmin(userId); return !securityUser.getSysUser().isAdmin();
} }
catch (Exception e) catch (Exception e)
{ {

View File

@@ -23,7 +23,7 @@ public enum DesensitizedType
/** /**
* 身份证中间10位星号替换 * 身份证中间10位星号替换
*/ */
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{3}[Xx]|\\d{4})", "$1** **** ****$2")), ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1** **** ****$2")),
/** /**
* 手机号中间4位星号替换 * 手机号中间4位星号替换

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -23,10 +23,11 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<!-- SpringDoc webmvc --> <!-- Swagger -->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>io.springfox</groupId>
<artifactId>springdoc-openapi-ui</artifactId> <artifactId>springfox-swagger2</artifactId>
<version>${swagger.fox.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -0,0 +1,20 @@
package com.ruoyi.common.swagger.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
import com.ruoyi.common.swagger.config.SwaggerAutoConfiguration;
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({ SwaggerAutoConfiguration.class })
public @interface EnableCustomSwagger2
{
}

View File

@@ -1,63 +0,0 @@
package com.ruoyi.common.swagger.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import com.ruoyi.common.swagger.config.properties.SpringDocProperties;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
/**
* Swagger 文档配置
*
* @author ruoyi
*/
@EnableConfigurationProperties(SpringDocProperties.class)
@ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = true)
public class SpringDocAutoConfiguration
{
@Bean
@ConditionalOnMissingBean(OpenAPI.class)
public OpenAPI openApi(SpringDocProperties properties)
{
return new OpenAPI().components(new Components()
// 设置认证的请求头
.addSecuritySchemes("apikey", securityScheme()))
.addSecurityItem(new SecurityRequirement().addList("apikey"))
.info(convertInfo(properties.getInfo()))
.servers(servers(properties.getGatewayUrl()));
}
public SecurityScheme securityScheme()
{
return new SecurityScheme().type(SecurityScheme.Type.APIKEY)
.name("Authorization")
.in(SecurityScheme.In.HEADER)
.scheme("Bearer");
}
private Info convertInfo(SpringDocProperties.InfoProperties infoProperties)
{
Info info = new Info();
info.setTitle(infoProperties.getTitle());
info.setDescription(infoProperties.getDescription());
info.setContact(infoProperties.getContact());
info.setLicense(infoProperties.getLicense());
info.setVersion(infoProperties.getVersion());
return info;
}
public List<Server> servers(String gatewayUrl)
{
List<Server> serverList = new ArrayList<>();
serverList.add(new Server().url(gatewayUrl));
return serverList;
}
}

View File

@@ -0,0 +1,123 @@
package com.ruoyi.common.swagger.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.ApiSelectorBuilder;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
@EnableConfigurationProperties(SwaggerProperties.class)
@ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true)
@Import({SwaggerBeanPostProcessor.class, SwaggerWebConfiguration.class})
public class SwaggerAutoConfiguration
{
/**
* 默认的排除路径排除Spring Boot默认的错误处理路径和端点
*/
private static final List<String> DEFAULT_EXCLUDE_PATH = Arrays.asList("/error", "/actuator/**");
private static final String BASE_PATH = "/**";
@Bean
public Docket api(SwaggerProperties swaggerProperties)
{
// base-path处理
if (swaggerProperties.getBasePath().isEmpty())
{
swaggerProperties.getBasePath().add(BASE_PATH);
}
// noinspection unchecked
List<Predicate<String>> basePath = new ArrayList<Predicate<String>>();
swaggerProperties.getBasePath().forEach(path -> basePath.add(PathSelectors.ant(path)));
// exclude-path处理
if (swaggerProperties.getExcludePath().isEmpty())
{
swaggerProperties.getExcludePath().addAll(DEFAULT_EXCLUDE_PATH);
}
List<Predicate<String>> excludePath = new ArrayList<>();
swaggerProperties.getExcludePath().forEach(path -> excludePath.add(PathSelectors.ant(path)));
ApiSelectorBuilder builder = new Docket(DocumentationType.SWAGGER_2).host(swaggerProperties.getHost())
.apiInfo(apiInfo(swaggerProperties)).select()
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()));
swaggerProperties.getBasePath().forEach(p -> builder.paths(PathSelectors.ant(p)));
swaggerProperties.getExcludePath().forEach(p -> builder.paths(PathSelectors.ant(p).negate()));
return builder.build().securitySchemes(securitySchemes()).securityContexts(securityContexts()).pathMapping("/");
}
/**
* 安全模式这里指定token通过Authorization头请求头传递
*/
private List<SecurityScheme> securitySchemes()
{
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
return apiKeyList;
}
/**
* 安全上下文
*/
private List<SecurityContext> securityContexts()
{
List<SecurityContext> securityContexts = new ArrayList<>();
securityContexts.add(
SecurityContext.builder()
.securityReferences(defaultAuth())
.operationSelector(o -> o.requestMappingPattern().matches("/.*"))
.build());
return securityContexts;
}
/**
* 默认的全局鉴权策略
*
* @return
*/
private List<SecurityReference> defaultAuth()
{
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
List<SecurityReference> securityReferences = new ArrayList<>();
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
return securityReferences;
}
private ApiInfo apiInfo(SwaggerProperties swaggerProperties)
{
return new ApiInfoBuilder()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.license(swaggerProperties.getLicense())
.licenseUrl(swaggerProperties.getLicenseUrl())
.termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
.contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail()))
.version(swaggerProperties.getVersion())
.build();
}
}

View File

@@ -0,0 +1,52 @@
package com.ruoyi.common.swagger.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;
/**
* swagger 在 springboot 2.6.x 不兼容问题的处理
*
* @author ruoyi
*/
public class SwaggerBeanPostProcessor implements BeanPostProcessor
{
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
{
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider)
{
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings)
{
List<T> copy = mappings.stream().filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean)
{
try
{
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
}
catch (IllegalArgumentException | IllegalAccessException e)
{
throw new IllegalStateException(e);
}
}
}

View File

@@ -0,0 +1,343 @@
package com.ruoyi.common.swagger.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("swagger")
public class SwaggerProperties
{
/**
* 是否开启swagger
*/
private Boolean enabled;
/**
* swagger会解析的包路径
**/
private String basePackage = "";
/**
* swagger会解析的url规则
**/
private List<String> basePath = new ArrayList<>();
/**
* 在basePath基础上需要排除的url规则
**/
private List<String> excludePath = new ArrayList<>();
/**
* 标题
**/
private String title = "";
/**
* 描述
**/
private String description = "";
/**
* 版本
**/
private String version = "";
/**
* 许可证
**/
private String license = "";
/**
* 许可证URL
**/
private String licenseUrl = "";
/**
* 服务条款URL
**/
private String termsOfServiceUrl = "";
/**
* host信息
**/
private String host = "";
/**
* 联系人信息
*/
private Contact contact = new Contact();
/**
* 全局统一鉴权配置
**/
private Authorization authorization = new Authorization();
public Boolean getEnabled()
{
return enabled;
}
public void setEnabled(Boolean enabled)
{
this.enabled = enabled;
}
public String getBasePackage()
{
return basePackage;
}
public void setBasePackage(String basePackage)
{
this.basePackage = basePackage;
}
public List<String> getBasePath()
{
return basePath;
}
public void setBasePath(List<String> basePath)
{
this.basePath = basePath;
}
public List<String> getExcludePath()
{
return excludePath;
}
public void setExcludePath(List<String> excludePath)
{
this.excludePath = excludePath;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public String getVersion()
{
return version;
}
public void setVersion(String version)
{
this.version = version;
}
public String getLicense()
{
return license;
}
public void setLicense(String license)
{
this.license = license;
}
public String getLicenseUrl()
{
return licenseUrl;
}
public void setLicenseUrl(String licenseUrl)
{
this.licenseUrl = licenseUrl;
}
public String getTermsOfServiceUrl()
{
return termsOfServiceUrl;
}
public void setTermsOfServiceUrl(String termsOfServiceUrl)
{
this.termsOfServiceUrl = termsOfServiceUrl;
}
public String getHost()
{
return host;
}
public void setHost(String host)
{
this.host = host;
}
public Contact getContact()
{
return contact;
}
public void setContact(Contact contact)
{
this.contact = contact;
}
public Authorization getAuthorization()
{
return authorization;
}
public void setAuthorization(Authorization authorization)
{
this.authorization = authorization;
}
public static class Contact
{
/**
* 联系人
**/
private String name = "";
/**
* 联系人url
**/
private String url = "";
/**
* 联系人email
**/
private String email = "";
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
}
public static class Authorization
{
/**
* 鉴权策略ID需要和SecurityReferences ID保持一致
*/
private String name = "";
/**
* 需要开启鉴权URL的正则
*/
private String authRegex = "^.*$";
/**
* 鉴权作用域列表
*/
private List<AuthorizationScope> authorizationScopeList = new ArrayList<>();
private List<String> tokenUrlList = new ArrayList<>();
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAuthRegex()
{
return authRegex;
}
public void setAuthRegex(String authRegex)
{
this.authRegex = authRegex;
}
public List<AuthorizationScope> getAuthorizationScopeList()
{
return authorizationScopeList;
}
public void setAuthorizationScopeList(List<AuthorizationScope> authorizationScopeList)
{
this.authorizationScopeList = authorizationScopeList;
}
public List<String> getTokenUrlList()
{
return tokenUrlList;
}
public void setTokenUrlList(List<String> tokenUrlList)
{
this.tokenUrlList = tokenUrlList;
}
}
public static class AuthorizationScope
{
/**
* 作用域名称
*/
private String scope = "";
/**
* 作用域描述
*/
private String description = "";
public String getScope()
{
return scope;
}
public void setScope(String scope)
{
this.scope = scope;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
}
}

View File

@@ -0,0 +1,20 @@
package com.ruoyi.common.swagger.config;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* swagger 资源映射路径
*
* @author ruoyi
*/
public class SwaggerWebConfiguration implements WebMvcConfigurer
{
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
/** swagger-ui 地址 */
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
}
}

View File

@@ -1,135 +0,0 @@
package com.ruoyi.common.swagger.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.License;
/**
* Swagger 配置属性
*
* @author ruoyi
*/
@ConfigurationProperties(prefix = "springdoc")
public class SpringDocProperties
{
/**
* 网关
*/
private String gatewayUrl;
/**
* 文档基本信息
*/
@NestedConfigurationProperty
private InfoProperties info = new InfoProperties();
/**
* <p>
* 文档的基础属性信息
* </p>
*
* @see io.swagger.v3.oas.models.info.Info
*
* 为了 springboot 自动生产配置提示信息,所以这里复制一个类出来
*/
public static class InfoProperties
{
/**
* 标题
*/
private String title = null;
/**
* 描述
*/
private String description = null;
/**
* 联系人信息
*/
@NestedConfigurationProperty
private Contact contact = null;
/**
* 许可证
*/
@NestedConfigurationProperty
private License license = null;
/**
* 版本
*/
private String version = null;
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public Contact getContact()
{
return contact;
}
public void setContact(Contact contact)
{
this.contact = contact;
}
public License getLicense()
{
return license;
}
public void setLicense(License license)
{
this.license = license;
}
public String getVersion()
{
return version;
}
public void setVersion(String version)
{
this.version = version;
}
}
public String getGatewayUrl()
{
return gatewayUrl;
}
public void setGatewayUrl(String gatewayUrl)
{
this.gatewayUrl = gatewayUrl;
}
public InfoProperties getInfo()
{
return info;
}
public void setInfo(InfoProperties info)
{
this.info = info;
}
}

View File

@@ -1 +1,3 @@
com.ruoyi.common.swagger.config.SpringDocAutoConfiguration # com.ruoyi.common.swagger.config.SwaggerAutoConfiguration
# com.ruoyi.common.swagger.config.SwaggerWebConfiguration
# com.ruoyi.common.swagger.config.SwaggerBeanPostProcessor

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -76,11 +76,16 @@
<artifactId>ruoyi-common-redis</artifactId> <artifactId>ruoyi-common-redis</artifactId>
</dependency> </dependency>
<!-- Springdoc --> <!-- Swagger -->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>io.springfox</groupId>
<artifactId>springdoc-openapi-webflux-ui</artifactId> <artifactId>springfox-swagger-ui</artifactId>
<version>${springdoc.version}</version> <version>${swagger.fox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.fox.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -1,93 +0,0 @@
package com.ruoyi.gateway.config;
import java.util.Set;
import java.util.stream.Collectors;
import org.springdoc.core.AbstractSwaggerUiConfigProperties;
import org.springdoc.core.SwaggerUiConfigProperties;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Configuration;
import com.alibaba.nacos.client.naming.event.InstancesChangeEvent;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.ruoyi.common.core.utils.StringUtils;
/**
* SpringDoc配置类
*
* @author ruoyi
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "springdoc.api-docs.enabled", matchIfMissing = true)
public class SpringDocConfig implements InitializingBean
{
@Autowired
private SwaggerUiConfigProperties swaggerUiConfigProperties;
@Autowired
private DiscoveryClient discoveryClient;
/**
* 在初始化后调用的方法
*/
@Override
public void afterPropertiesSet()
{
NotifyCenter.registerSubscriber(new SwaggerDocRegister(swaggerUiConfigProperties, discoveryClient));
}
}
/**
* Swagger文档注册器
*/
class SwaggerDocRegister extends Subscriber<InstancesChangeEvent>
{
@Autowired
private SwaggerUiConfigProperties swaggerUiConfigProperties;
@Autowired
private DiscoveryClient discoveryClient;
private final static String[] EXCLUDE_ROUTES = new String[] { "ruoyi-gateway", "ruoyi-auth", "ruoyi-file", "ruoyi-monitor" };
public SwaggerDocRegister(SwaggerUiConfigProperties swaggerUiConfigProperties, DiscoveryClient discoveryClient)
{
this.swaggerUiConfigProperties = swaggerUiConfigProperties;
this.discoveryClient = discoveryClient;
}
/**
* 事件回调方法处理InstancesChangeEvent事件
* @param event 事件对象
*/
@Override
public void onEvent(InstancesChangeEvent event)
{
Set<AbstractSwaggerUiConfigProperties.SwaggerUrl> swaggerUrlSet = discoveryClient.getServices()
.stream()
.flatMap(serviceId -> discoveryClient.getInstances(serviceId).stream())
.filter(instance -> !StringUtils.equalsAnyIgnoreCase(instance.getServiceId(), EXCLUDE_ROUTES))
.map(instance -> {
AbstractSwaggerUiConfigProperties.SwaggerUrl swaggerUrl = new AbstractSwaggerUiConfigProperties.SwaggerUrl();
swaggerUrl.setName(instance.getServiceId());
swaggerUrl.setUrl(String.format("/%s/v3/api-docs", instance.getServiceId()));
return swaggerUrl;
})
.collect(Collectors.toSet());
swaggerUiConfigProperties.setUrls(swaggerUrlSet);
}
/**
* 订阅类型方法,返回订阅的事件类型
* @return 订阅的事件类型
*/
@Override
public Class<? extends Event> subscribeType()
{
return InstancesChangeEvent.class;
}
}

View File

@@ -0,0 +1,79 @@
package com.ruoyi.gateway.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.config.ResourceHandlerRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
/**
* 聚合系统接口
*
* @author ruoyi
*/
@Component
public class SwaggerProvider implements SwaggerResourcesProvider, WebFluxConfigurer
{
/**
* Swagger2默认的url后缀
*/
public static final String SWAGGER2URL = "/v2/api-docs";
/**
* 网关路由
*/
@Lazy
@Autowired
private RouteLocator routeLocator;
@Autowired
private GatewayProperties gatewayProperties;
/**
* 聚合其他服务接口
*
* @return
*/
@Override
public List<SwaggerResource> get()
{
List<SwaggerResource> resourceList = new ArrayList<>();
List<String> routes = new ArrayList<>();
// 获取网关中配置的route
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
gatewayProperties.getRoutes().stream()
.filter(routeDefinition -> routes
.contains(routeDefinition.getId()))
.forEach(routeDefinition -> routeDefinition.getPredicates().stream()
.filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName()))
.filter(predicateDefinition -> !"ruoyi-auth".equalsIgnoreCase(routeDefinition.getId()))
.forEach(predicateDefinition -> resourceList
.add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs()
.get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", SWAGGER2URL)))));
return resourceList;
}
private SwaggerResource swaggerResource(String name, String location)
{
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion("2.0");
return swaggerResource;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
/** swagger-ui 地址 */
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
}
}

View File

@@ -101,7 +101,7 @@ public class AuthFilter implements GlobalFilter, Ordered
private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg)
{ {
log.error("[鉴权异常处理]请求路径:{},错误信息:{}", exchange.getRequest().getPath(), msg); log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED); return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED);
} }
@@ -118,7 +118,7 @@ public class AuthFilter implements GlobalFilter, Ordered
*/ */
private String getToken(ServerHttpRequest request) private String getToken(ServerHttpRequest request)
{ {
String token = request.getHeaders().getFirst(SecurityConstants.AUTHORIZATION_HEADER); String token = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION);
// 如果前端设置了令牌前缀,则裁剪掉前缀 // 如果前端设置了令牌前缀,则裁剪掉前缀
if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX)) if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX))
{ {

View File

@@ -0,0 +1,87 @@
package com.ruoyi.gateway.filter;
import java.util.Collections;
import java.util.List;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 获取body请求数据解决流不能重复读取问题
*
* @author ruoyi
*/
@Component
public class CacheRequestFilter extends AbstractGatewayFilterFactory<CacheRequestFilter.Config>
{
public CacheRequestFilter()
{
super(Config.class);
}
@Override
public String name()
{
return "CacheRequestFilter";
}
@Override
public GatewayFilter apply(Config config)
{
CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter();
Integer order = config.getOrder();
if (order == null)
{
return cacheRequestGatewayFilter;
}
return new OrderedGatewayFilter(cacheRequestGatewayFilter, order);
}
public static class CacheRequestGatewayFilter implements GatewayFilter
{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{
// GET DELETE 不过滤
HttpMethod method = exchange.getRequest().getMethod();
if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE)
{
return chain.filter(exchange);
}
return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> {
if (serverHttpRequest == exchange.getRequest())
{
return chain.filter(exchange);
}
return chain.filter(exchange.mutate().request(serverHttpRequest).build());
});
}
}
@Override
public List<String> shortcutFieldOrder()
{
return Collections.singletonList("order");
}
static class Config
{
private Integer order;
public Integer getOrder()
{
return order;
}
public void setOrder(Integer order)
{
this.order = order;
}
}
}

View File

@@ -0,0 +1,56 @@
package com.ruoyi.gateway.handler;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder;
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler
{
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Autowired(required = false)
private UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources;
@Autowired
public SwaggerHandler(SwaggerResourcesProvider swaggerResources)
{
this.swaggerResources = swaggerResources;
}
@GetMapping("/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration()
{
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()),
HttpStatus.OK));
}
@GetMapping("/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration()
{
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@SuppressWarnings("rawtypes")
@GetMapping("")
public Mono<ResponseEntity> swaggerResources()
{
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -40,12 +40,6 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- FastDFS --> <!-- FastDFS -->
<dependency> <dependency>
@@ -66,6 +60,12 @@
<artifactId>ruoyi-api-system</artifactId> <artifactId>ruoyi-api-system</artifactId>
</dependency> </dependency>
<!-- RuoYi Common Swagger -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -3,12 +3,14 @@ package com.ruoyi.file;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
/** /**
* 文件服务 * 文件服务
* *
* @author ruoyi * @author ruoyi
*/ */
@EnableCustomSwagger2
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class RuoYiFileApplication public class RuoYiFileApplication
{ {

View File

@@ -1,46 +0,0 @@
package com.ruoyi.file.config;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.DispatcherType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.file.filter.RefererFilter;
/**
* Filter配置
*
* @author ruoyi
*/
@Configuration
public class FilterConfig
{
/**
* 资源映射路径 前缀
*/
@Value("${file.prefix}")
public String localFilePrefix;
@Value("${referer.allowed-domains}")
private String allowedDomains;
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(value = "referer.enabled", havingValue = "true")
public FilterRegistrationBean refererFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new RefererFilter());
registration.addUrlPatterns(localFilePrefix + "/*");
registration.setName("refererFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("allowedDomains", allowedDomains);
registration.setInitParameters(initParameters);
return registration;
}
}

View File

@@ -3,12 +3,10 @@ package com.ruoyi.file.controller;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileUtils; import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.service.ISysFileService; import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.system.api.domain.SysFile; import com.ruoyi.system.api.domain.SysFile;
@@ -47,26 +45,4 @@ public class SysFileController
return R.fail(e.getMessage()); return R.fail(e.getMessage());
} }
} }
}
/**
* 文件删除请求
*/
@DeleteMapping("delete")
public R<Boolean> delete(String fileUrl)
{
try
{
if (!FileUtils.validateFilePath(fileUrl))
{
throw new Exception(StringUtils.format("资源文件({})非法,不允许删除。 ", fileUrl));
}
sysFileService.deleteFile(fileUrl);
return R.ok();
}
catch (Exception e)
{
log.error("删除文件失败", e);
return R.fail(e.getMessage());
}
}
}

View File

@@ -1,77 +0,0 @@
package com.ruoyi.file.filter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 防盗链过滤器
*
* @author ruoyi
*/
public class RefererFilter implements Filter
{
/**
* 允许的域名列表
*/
public List<String> allowedDomains;
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
String domains = filterConfig.getInitParameter("allowedDomains");
this.allowedDomains = Arrays.asList(domains.split(","));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String referer = req.getHeader("Referer");
// 如果Referer为空拒绝访问
if (referer == null || referer.isEmpty())
{
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer header is required");
return;
}
// 检查Referer是否在允许的域名列表中
boolean allowed = false;
for (String domain : allowedDomains)
{
if (referer.contains(domain))
{
allowed = true;
break;
}
}
// 根据检查结果决定是否放行
if (allowed)
{
chain.doFilter(request, response);
}
else
{
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer '" + referer + "' is not allowed");
}
}
@Override
public void destroy()
{
}
}

View File

@@ -1,11 +1,11 @@
package com.ruoyi.file.service; package com.ruoyi.file.service;
import java.io.InputStream; import java.io.InputStream;
import com.alibaba.nacos.common.utils.IoUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.alibaba.nacos.common.utils.IoUtils;
import com.github.tobato.fastdfs.domain.fdfs.StorePath; import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient; import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.ruoyi.common.core.utils.file.FileTypeUtils; import com.ruoyi.common.core.utils.file.FileTypeUtils;
@@ -37,40 +37,10 @@ public class FastDfsSysFileServiceImpl implements ISysFileService
@Override @Override
public String uploadFile(MultipartFile file) throws Exception public String uploadFile(MultipartFile file) throws Exception
{ {
InputStream inputStream = null; InputStream inputStream = file.getInputStream();
try StorePath storePath = storageClient.uploadFile(inputStream, file.getSize(),
{ FileTypeUtils.getExtension(file), null);
inputStream = file.getInputStream(); IoUtils.closeQuietly(inputStream);
StorePath storePath = storageClient.uploadFile(inputStream, file.getSize(), FileTypeUtils.getExtension(file), null); return domain + "/" + storePath.getFullPath();
return domain + "/" + storePath.getFullPath();
}
catch (Exception e)
{
throw new RuntimeException("FastDfs Failed to upload file", e);
}
finally
{
IoUtils.closeQuietly(inputStream);
}
}
/**
* FastDFS文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
try
{
StorePath storePath = StorePath.parseFromUrl(fileUrl);
storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
}
catch (Exception e)
{
throw new RuntimeException("FastDfs Failed to delete file: ", e);
}
} }
} }

View File

@@ -17,12 +17,4 @@ public interface ISysFileService
* @throws Exception * @throws Exception
*/ */
public String uploadFile(MultipartFile file) throws Exception; public String uploadFile(MultipartFile file) throws Exception;
/**
* 文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
public void deleteFile(String fileUrl) throws Exception;
} }

View File

@@ -4,8 +4,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.utils.FileUploadUtils; import com.ruoyi.file.utils.FileUploadUtils;
/** /**
@@ -49,17 +47,4 @@ public class LocalSysFileServiceImpl implements ISysFileService
String url = domain + localFilePrefix + name; String url = domain + localFilePrefix + name;
return url; return url;
} }
/**
* 本地文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
String localFile = StringUtils.substringAfter(fileUrl, localFilePrefix);
FileUtils.deleteFile(localFilePath + localFile);
}
} }

View File

@@ -5,12 +5,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.alibaba.nacos.common.utils.IoUtils; import com.alibaba.nacos.common.utils.IoUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.file.config.MinioConfig; import com.ruoyi.file.config.MinioConfig;
import com.ruoyi.file.utils.FileUploadUtils; import com.ruoyi.file.utils.FileUploadUtils;
import io.minio.MinioClient; import io.minio.MinioClient;
import io.minio.PutObjectArgs; import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
/** /**
* Minio 文件存储 * Minio 文件存储
@@ -36,47 +34,16 @@ public class MinioSysFileServiceImpl implements ISysFileService
@Override @Override
public String uploadFile(MultipartFile file) throws Exception public String uploadFile(MultipartFile file) throws Exception
{ {
InputStream inputStream = null; String fileName = FileUploadUtils.extractFilename(file);
try InputStream inputStream = file.getInputStream();
{ PutObjectArgs args = PutObjectArgs.builder()
String fileName = FileUploadUtils.extractFilename(file); .bucket(minioConfig.getBucketName())
inputStream = file.getInputStream(); .object(fileName)
PutObjectArgs args = PutObjectArgs.builder() .stream(inputStream, file.getSize(), -1)
.bucket(minioConfig.getBucketName()) .contentType(file.getContentType())
.object(fileName) .build();
.stream(inputStream, file.getSize(), -1) client.putObject(args);
.contentType(file.getContentType()) IoUtils.closeQuietly(inputStream);
.build(); return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
client.putObject(args);
return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
}
catch (Exception e)
{
throw new RuntimeException("Minio Failed to upload file", e);
}
finally
{
IoUtils.closeQuietly(inputStream);
}
}
/**
* Minio文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
try
{
String minioFile = StringUtils.substringAfter(fileUrl, minioConfig.getBucketName());
client.removeObject(RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(minioFile).build());
}
catch (Exception e)
{
throw new RuntimeException("Minio Failed to delete file", e);
}
} }
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -40,6 +40,13 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Apache Velocity --> <!-- Apache Velocity -->
<dependency> <dependency>

View File

@@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.ruoyi.common.security.annotation.EnableCustomConfig; import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients; import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
/** /**
* 代码生成 * 代码生成
@@ -11,6 +12,7 @@ import com.ruoyi.common.security.annotation.EnableRyFeignClients;
* @author ruoyi * @author ruoyi
*/ */
@EnableCustomConfig @EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients @EnableRyFeignClients
@SpringBootApplication @SpringBootApplication
public class RuoYiGenApplication public class RuoYiGenApplication

View File

@@ -18,15 +18,12 @@ public class GenConfig
/** 生成包路径 */ /** 生成包路径 */
public static String packageName; public static String packageName;
/** 自动去除表前缀 */ /** 自动去除表前缀默认是false */
public static boolean autoRemovePre; public static boolean autoRemovePre;
/** 表前缀 */ /** 表前缀(类名不会包含表前缀) */
public static String tablePrefix; public static String tablePrefix;
/** 是否允许生成文件覆盖到本地(自定义路径) */
public static boolean allowOverwrite;
public static String getAuthor() public static String getAuthor()
{ {
return author; return author;
@@ -66,14 +63,4 @@ public class GenConfig
{ {
GenConfig.tablePrefix = tablePrefix; GenConfig.tablePrefix = tablePrefix;
} }
public static boolean isAllowOverwrite()
{
return allowOverwrite;
}
public void setAllowOverwrite(boolean allowOverwrite)
{
GenConfig.allowOverwrite = allowOverwrite;
}
} }

View File

@@ -23,7 +23,6 @@ import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.gen.config.GenConfig;
import com.ruoyi.gen.domain.GenTable; import com.ruoyi.gen.domain.GenTable;
import com.ruoyi.gen.domain.GenTableColumn; import com.ruoyi.gen.domain.GenTableColumn;
import com.ruoyi.gen.service.IGenTableColumnService; import com.ruoyi.gen.service.IGenTableColumnService;
@@ -57,7 +56,7 @@ public class GenController extends BaseController
} }
/** /**
* 获取代码生成信息 * 修改代码生成业务
*/ */
@RequiresPermissions("tool:gen:query") @RequiresPermissions("tool:gen:query")
@GetMapping(value = "/{tableId}") @GetMapping(value = "/{tableId}")
@@ -169,10 +168,6 @@ public class GenController extends BaseController
@GetMapping("/genCode/{tableName}") @GetMapping("/genCode/{tableName}")
public AjaxResult genCode(@PathVariable("tableName") String tableName) public AjaxResult genCode(@PathVariable("tableName") String tableName)
{ {
if (!GenConfig.isAllowOverwrite())
{
return AjaxResult.error("【系统预设】不允许生成文件覆盖到本地");
}
genTableService.generatorCode(tableName); genTableService.generatorCode(tableName);
return success(); return success();
} }

View File

@@ -93,7 +93,7 @@ public class GenTable extends BaseEntity
private String treeName; private String treeName;
/** 上级菜单ID字段 */ /** 上级菜单ID字段 */
private Long parentMenuId; private String parentMenuId;
/** 上级菜单名称字段 */ /** 上级菜单名称字段 */
private String parentMenuName; private String parentMenuName;
@@ -317,12 +317,12 @@ public class GenTable extends BaseEntity
this.treeName = treeName; this.treeName = treeName;
} }
public Long getParentMenuId() public String getParentMenuId()
{ {
return parentMenuId; return parentMenuId;
} }
public void setParentMenuId(Long parentMenuId) public void setParentMenuId(String parentMenuId)
{ {
this.parentMenuId = parentMenuId; this.parentMenuId = parentMenuId;
} }

View File

@@ -1,6 +1,7 @@
package com.ruoyi.gen.domain; package com.ruoyi.gen.domain;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.BaseEntity; import com.ruoyi.common.core.web.domain.BaseEntity;

View File

@@ -129,9 +129,9 @@ public class GenTableServiceImpl implements IGenTableService
int row = genTableMapper.updateGenTable(genTable); int row = genTableMapper.updateGenTable(genTable);
if (row > 0) if (row > 0)
{ {
for (GenTableColumn genTableColumn : genTable.getColumns()) for (GenTableColumn cenTableColumn : genTable.getColumns())
{ {
genTableColumnMapper.updateGenTableColumn(genTableColumn); genTableColumnMapper.updateGenTableColumn(cenTableColumn);
} }
} }
} }
@@ -414,16 +414,16 @@ public class GenTableServiceImpl implements IGenTableService
{ {
throw new ServiceException("树名称字段不能为空"); throw new ServiceException("树名称字段不能为空");
} }
} else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
{
if (StringUtils.isEmpty(genTable.getSubTableName()))
{ {
throw new ServiceException("关联子表的表名不能为空"); if (StringUtils.isEmpty(genTable.getSubTableName()))
} {
else if (StringUtils.isEmpty(genTable.getSubTableFkName())) throw new ServiceException("关联子表的表名不能为空");
{ }
throw new ServiceException("子表关联的外键名不能为空"); else if (StringUtils.isEmpty(genTable.getSubTableFkName()))
{
throw new ServiceException("子表关联的外键名不能为空");
}
} }
} }
} }
@@ -491,7 +491,7 @@ public class GenTableServiceImpl implements IGenTableService
String treeCode = paramsObj.getString(GenConstants.TREE_CODE); String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE); String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
String treeName = paramsObj.getString(GenConstants.TREE_NAME); String treeName = paramsObj.getString(GenConstants.TREE_NAME);
Long parentMenuId = paramsObj.getLongValue(GenConstants.PARENT_MENU_ID); String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID);
String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME); String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
genTable.setTreeCode(treeCode); genTable.setTreeCode(treeCode);

View File

@@ -71,9 +71,9 @@ public class ${ClassName} extends ${Entity}
{ {
return $column.javaField; return $column.javaField;
} }
#end
#end
#end
#end
#if($table.sub) #if($table.sub)
public List<${subClassName}> get${subClassName}List() public List<${subClassName}> get${subClassName}List()
{ {

View File

@@ -75,7 +75,7 @@
icon="el-icon-plus" icon="el-icon-plus"
size="mini" size="mini"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['${permissionPrefix}:add']" v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button> >新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -144,21 +144,21 @@
type="text" type="text"
icon="el-icon-edit" icon="el-icon-edit"
@click="handleUpdate(scope.row)" @click="handleUpdate(scope.row)"
v-hasPermi="['${permissionPrefix}:edit']" v-hasPermi="['${moduleName}:${businessName}:edit']"
>修改</el-button> >修改</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-plus" icon="el-icon-plus"
@click="handleAdd(scope.row)" @click="handleAdd(scope.row)"
v-hasPermi="['${permissionPrefix}:add']" v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button> >新增</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-delete" icon="el-icon-delete"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
v-hasPermi="['${permissionPrefix}:remove']" v-hasPermi="['${moduleName}:${businessName}:remove']"
>删除</el-button> >删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
@@ -283,9 +283,9 @@
</template> </template>
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}" import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css" import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
@@ -346,18 +346,18 @@ export default {
#end #end
#end #end
} }
} };
}, },
created() { created() {
this.getList() this.getList();
}, },
methods: { methods: {
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
getList() { getList() {
this.loading = true this.loading = true;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
this.queryParams.params = {} this.queryParams.params = {};
#break #break
#end #end
#end #end
@@ -365,40 +365,40 @@ export default {
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) { if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0] this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1] this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
} }
#end #end
#end #end
list${BusinessName}(this.queryParams).then(response => { list${BusinessName}(this.queryParams).then(response => {
this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}") this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
this.loading = false this.loading = false;
}) });
}, },
/** 转换${functionName}数据结构 */ /** 转换${functionName}数据结构 */
normalizer(node) { normalizer(node) {
if (node.children && !node.children.length) { if (node.children && !node.children.length) {
delete node.children delete node.children;
} }
return { return {
id: node.${treeCode}, id: node.${treeCode},
label: node.${treeName}, label: node.${treeName},
children: node.children children: node.children
} };
}, },
/** 查询${functionName}下拉树结构 */ /** 查询${functionName}下拉树结构 */
getTreeselect() { getTreeselect() {
list${BusinessName}().then(response => { list${BusinessName}().then(response => {
this.${businessName}Options = [] this.${businessName}Options = [];
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] } const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] };
data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}") data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
this.${businessName}Options.push(data) this.${businessName}Options.push(data);
}) });
}, },
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false this.open = false;
this.reset() this.reset();
}, },
// 表单重置 // 表单重置
reset() { reset() {
@@ -410,61 +410,61 @@ export default {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
} };
this.resetForm("form") this.resetForm("form");
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.getList() this.getList();
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.daterange${AttrName} = [] this.daterange${AttrName} = [];
#end #end
#end #end
this.resetForm("queryForm") this.resetForm("queryForm");
this.handleQuery() this.handleQuery();
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd(row) { handleAdd(row) {
this.reset() this.reset();
this.getTreeselect() this.getTreeselect();
if (row != null && row.${treeCode}) { if (row != null && row.${treeCode}) {
this.form.${treeParentCode} = row.${treeCode} this.form.${treeParentCode} = row.${treeCode};
} else { } else {
this.form.${treeParentCode} = 0 this.form.${treeParentCode} = 0;
} }
this.open = true this.open = true;
this.title = "添加${functionName}" this.title = "添加${functionName}";
}, },
/** 展开/折叠操作 */ /** 展开/折叠操作 */
toggleExpandAll() { toggleExpandAll() {
this.refreshTable = false this.refreshTable = false;
this.isExpandAll = !this.isExpandAll this.isExpandAll = !this.isExpandAll;
this.$nextTick(() => { this.$nextTick(() => {
this.refreshTable = true this.refreshTable = true;
}) });
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset();
this.getTreeselect() this.getTreeselect();
if (row != null) { if (row != null) {
this.form.${treeParentCode} = row.${treeParentCode} this.form.${treeParentCode} = row.${treeCode};
} }
get${BusinessName}(row.${pkColumn.javaField}).then(response => { get${BusinessName}(row.${pkColumn.javaField}).then(response => {
this.form = response.data this.form = response.data;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(",") this.form.$column.javaField = this.form.${column.javaField}.split(",");
#end #end
#end #end
this.open = true this.open = true;
this.title = "修改${functionName}" this.title = "修改${functionName}";
}) });
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
@@ -472,34 +472,34 @@ export default {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(",") this.form.$column.javaField = this.form.${column.javaField}.join(",");
#end #end
#end #end
if (this.form.${pkColumn.javaField} != null) { if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("修改成功") this.#[[$modal]]#.msgSuccess("修改成功");
this.open = false this.open = false;
this.getList() this.getList();
}) });
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("新增成功") this.#[[$modal]]#.msgSuccess("新增成功");
this.open = false this.open = false;
this.getList() this.getList();
}) });
} }
} }
}) });
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() { this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
return del${BusinessName}(row.${pkColumn.javaField}) return del${BusinessName}(row.${pkColumn.javaField});
}).then(() => { }).then(() => {
this.getList() this.getList();
this.#[[$modal]]#.msgSuccess("删除成功") this.#[[$modal]]#.msgSuccess("删除成功");
}).catch(() => {}) }).catch(() => {});
} }
} }
} };
</script> </script>

View File

@@ -75,7 +75,7 @@
icon="el-icon-plus" icon="el-icon-plus"
size="mini" size="mini"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['${permissionPrefix}:add']" v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button> >新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -86,7 +86,7 @@
size="mini" size="mini"
:disabled="single" :disabled="single"
@click="handleUpdate" @click="handleUpdate"
v-hasPermi="['${permissionPrefix}:edit']" v-hasPermi="['${moduleName}:${businessName}:edit']"
>修改</el-button> >修改</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -97,7 +97,7 @@
size="mini" size="mini"
:disabled="multiple" :disabled="multiple"
@click="handleDelete" @click="handleDelete"
v-hasPermi="['${permissionPrefix}:remove']" v-hasPermi="['${moduleName}:${businessName}:remove']"
>删除</el-button> >删除</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -107,7 +107,7 @@
icon="el-icon-download" icon="el-icon-download"
size="mini" size="mini"
@click="handleExport" @click="handleExport"
v-hasPermi="['${permissionPrefix}:export']" v-hasPermi="['${moduleName}:${businessName}:export']"
>导出</el-button> >导出</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
@@ -158,14 +158,14 @@
type="text" type="text"
icon="el-icon-edit" icon="el-icon-edit"
@click="handleUpdate(scope.row)" @click="handleUpdate(scope.row)"
v-hasPermi="['${permissionPrefix}:edit']" v-hasPermi="['${moduleName}:${businessName}:edit']"
>修改</el-button> >修改</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-delete" icon="el-icon-delete"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
v-hasPermi="['${permissionPrefix}:remove']" v-hasPermi="['${moduleName}:${businessName}:remove']"
>删除</el-button> >删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
@@ -353,7 +353,7 @@
</template> </template>
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}" import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
@@ -423,18 +423,18 @@ export default {
#end #end
#end #end
} }
} };
}, },
created() { created() {
this.getList() this.getList();
}, },
methods: { methods: {
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
getList() { getList() {
this.loading = true this.loading = true;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
this.queryParams.params = {} this.queryParams.params = {};
#break #break
#end #end
#end #end
@@ -442,21 +442,21 @@ export default {
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) { if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0] this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1] this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
} }
#end #end
#end #end
list${BusinessName}(this.queryParams).then(response => { list${BusinessName}(this.queryParams).then(response => {
this.${businessName}List = response.rows this.${businessName}List = response.rows;
this.total = response.total this.total = response.total;
this.loading = false this.loading = false;
}) });
}, },
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false this.open = false;
this.reset() this.reset();
}, },
// 表单重置 // 表单重置
reset() { reset() {
@@ -468,27 +468,27 @@ export default {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
} };
#if($table.sub) #if($table.sub)
this.${subclassName}List = [] this.${subclassName}List = [];
#end #end
this.resetForm("form") this.resetForm("form");
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1 this.queryParams.pageNum = 1;
this.getList() this.getList();
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.daterange${AttrName} = [] this.daterange${AttrName} = [];
#end #end
#end #end
this.resetForm("queryForm") this.resetForm("queryForm");
this.handleQuery() this.handleQuery();
}, },
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
@@ -498,27 +498,27 @@ export default {
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset();
this.open = true this.open = true;
this.title = "添加${functionName}" this.title = "添加${functionName}";
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset();
const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
get${BusinessName}(${pkColumn.javaField}).then(response => { get${BusinessName}(${pkColumn.javaField}).then(response => {
this.form = response.data this.form = response.data;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(",") this.form.$column.javaField = this.form.${column.javaField}.split(",");
#end #end
#end #end
#if($table.sub) #if($table.sub)
this.${subclassName}List = response.data.${subclassName}List this.${subclassName}List = response.data.${subclassName}List;
#end #end
this.open = true this.open = true;
this.title = "修改${functionName}" this.title = "修改${functionName}";
}) });
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
@@ -526,64 +526,64 @@ export default {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(",") this.form.$column.javaField = this.form.${column.javaField}.join(",");
#end #end
#end #end
#if($table.sub) #if($table.sub)
this.form.${subclassName}List = this.${subclassName}List this.form.${subclassName}List = this.${subclassName}List;
#end #end
if (this.form.${pkColumn.javaField} != null) { if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("修改成功") this.#[[$modal]]#.msgSuccess("修改成功");
this.open = false this.open = false;
this.getList() this.getList();
}) });
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("新增成功") this.#[[$modal]]#.msgSuccess("新增成功");
this.open = false this.open = false;
this.getList() this.getList();
}) });
} }
} }
}) });
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids;
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() { this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(${pkColumn.javaField}s) return del${BusinessName}(${pkColumn.javaField}s);
}).then(() => { }).then(() => {
this.getList() this.getList();
this.#[[$modal]]#.msgSuccess("删除成功") this.#[[$modal]]#.msgSuccess("删除成功");
}).catch(() => {}) }).catch(() => {});
}, },
#if($table.sub) #if($table.sub)
/** ${subTable.functionName}序号 */ /** ${subTable.functionName}序号 */
row${subClassName}Index({ row, rowIndex }) { row${subClassName}Index({ row, rowIndex }) {
row.index = rowIndex + 1 row.index = rowIndex + 1;
}, },
/** ${subTable.functionName}添加按钮操作 */ /** ${subTable.functionName}添加按钮操作 */
handleAdd${subClassName}() { handleAdd${subClassName}() {
let obj = {} let obj = {};
#foreach($column in $subTable.columns) #foreach($column in $subTable.columns)
#if($column.pk || $column.javaField == ${subTableFkclassName}) #if($column.pk || $column.javaField == ${subTableFkclassName})
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
obj.$column.javaField = "" obj.$column.javaField = "";
#end #end
#end #end
this.${subclassName}List.push(obj) this.${subclassName}List.push(obj);
}, },
/** ${subTable.functionName}删除按钮操作 */ /** ${subTable.functionName}删除按钮操作 */
handleDelete${subClassName}() { handleDelete${subClassName}() {
if (this.checked${subClassName}.length == 0) { if (this.checked${subClassName}.length == 0) {
this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据") this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据");
} else { } else {
const ${subclassName}List = this.${subclassName}List const ${subclassName}List = this.${subclassName}List;
const checked${subClassName} = this.checked${subClassName} const checked${subClassName} = this.checked${subClassName};
this.${subclassName}List = ${subclassName}List.filter(function(item) { this.${subclassName}List = ${subclassName}List.filter(function(item) {
return checked${subClassName}.indexOf(item.index) == -1 return checked${subClassName}.indexOf(item.index) == -1
}) });
} }
}, },
/** 复选框选中数据 */ /** 复选框选中数据 */
@@ -598,5 +598,5 @@ export default {
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`) }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
} }
} }
} };
</script> </script>

View File

@@ -73,7 +73,7 @@
plain plain
icon="Plus" icon="Plus"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['${permissionPrefix}:add']" v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button> >新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -136,9 +136,9 @@
#end #end
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${permissionPrefix}:edit']">修改</el-button> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button>
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${permissionPrefix}:add']">新增</el-button> <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${moduleName}:${businessName}:add']">新增</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${permissionPrefix}:remove']">删除</el-button> <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -271,26 +271,26 @@
</template> </template>
<script setup name="${BusinessName}"> <script setup name="${BusinessName}">
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}" import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance();
#if(${dicts} != '') #if(${dicts} != '')
#set($dictsNoSymbol=$dicts.replace("'", "")) #set($dictsNoSymbol=$dicts.replace("'", ""))
const { ${dictsNoSymbol} } = proxy.useDict(${dicts}) const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
#end #end
const ${businessName}List = ref([]) const ${businessName}List = ref([]);
const ${businessName}Options = ref([]) const ${businessName}Options = ref([]);
const open = ref(false) const open = ref(false);
const loading = ref(true) const loading = ref(true);
const showSearch = ref(true) const showSearch = ref(true);
const title = ref("") const title = ref("");
const isExpandAll = ref(true) const isExpandAll = ref(true);
const refreshTable = ref(true) const refreshTable = ref(true);
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
const daterange${AttrName} = ref([]) const daterange${AttrName} = ref([]);
#end #end
#end #end
@@ -318,48 +318,48 @@ const data = reactive({
#end #end
#end #end
} }
}) });
const { queryParams, form, rules } = toRefs(data) const { queryParams, form, rules } = toRefs(data);
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
function getList() { function getList() {
loading.value = true loading.value = true;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
queryParams.value.params = {} queryParams.value.params = {};
#break #break
#end #end
#end #end
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) { if (null != daterange${AttrName} && '' != daterange${AttrName}) {
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0] queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1] queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
} }
#end #end
#end #end
list${BusinessName}(queryParams.value).then(response => { list${BusinessName}(queryParams.value).then(response => {
${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}") ${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
loading.value = false loading.value = false;
}) });
} }
/** 查询${functionName}下拉树结构 */ /** 查询${functionName}下拉树结构 */
function getTreeselect() { function getTreeselect() {
list${BusinessName}().then(response => { list${BusinessName}().then(response => {
${businessName}Options.value = [] ${businessName}Options.value = [];
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] } const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] };
data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}") data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
${businessName}Options.value.push(data) ${businessName}Options.value.push(data);
}) });
} }
// 取消按钮 // 取消按钮
function cancel() { function cancel() {
open.value = false open.value = false;
reset() reset();
} }
// 表单重置 // 表单重置
@@ -372,13 +372,13 @@ function reset() {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
} };
proxy.resetForm("${businessName}Ref") proxy.resetForm("${businessName}Ref");
} }
/** 搜索按钮操作 */ /** 搜索按钮操作 */
function handleQuery() { function handleQuery() {
getList() getList();
} }
/** 重置按钮操作 */ /** 重置按钮操作 */
@@ -386,52 +386,52 @@ function resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
daterange${AttrName}.value = [] daterange${AttrName}.value = [];
#end #end
#end #end
proxy.resetForm("queryRef") proxy.resetForm("queryRef");
handleQuery() handleQuery();
} }
/** 新增按钮操作 */ /** 新增按钮操作 */
function handleAdd(row) { function handleAdd(row) {
reset() reset();
getTreeselect() getTreeselect();
if (row != null && row.${treeCode}) { if (row != null && row.${treeCode}) {
form.value.${treeParentCode} = row.${treeCode} form.value.${treeParentCode} = row.${treeCode};
} else { } else {
form.value.${treeParentCode} = 0 form.value.${treeParentCode} = 0;
} }
open.value = true open.value = true;
title.value = "添加${functionName}" title.value = "添加${functionName}";
} }
/** 展开/折叠操作 */ /** 展开/折叠操作 */
function toggleExpandAll() { function toggleExpandAll() {
refreshTable.value = false refreshTable.value = false;
isExpandAll.value = !isExpandAll.value isExpandAll.value = !isExpandAll.value;
nextTick(() => { nextTick(() => {
refreshTable.value = true refreshTable.value = true;
}) });
} }
/** 修改按钮操作 */ /** 修改按钮操作 */
async function handleUpdate(row) { async function handleUpdate(row) {
reset() reset();
await getTreeselect() await getTreeselect();
if (row != null) { if (row != null) {
form.value.${treeParentCode} = row.${treeParentCode} form.value.${treeParentCode} = row.${treeCode};
} }
get${BusinessName}(row.${pkColumn.javaField}).then(response => { get${BusinessName}(row.${pkColumn.javaField}).then(response => {
form.value = response.data form.value = response.data;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.split(",") form.value.$column.javaField = form.value.${column.javaField}.split(",");
#end #end
#end #end
open.value = true open.value = true;
title.value = "修改${functionName}" title.value = "修改${functionName}";
}) });
} }
/** 提交按钮 */ /** 提交按钮 */
@@ -440,35 +440,35 @@ function submitForm() {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.join(",") form.value.$column.javaField = form.value.${column.javaField}.join(",");
#end #end
#end #end
if (form.value.${pkColumn.javaField} != null) { if (form.value.${pkColumn.javaField} != null) {
update${BusinessName}(form.value).then(response => { update${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("修改成功") proxy.#[[$modal]]#.msgSuccess("修改成功");
open.value = false open.value = false;
getList() getList();
}) });
} else { } else {
add${BusinessName}(form.value).then(response => { add${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("新增成功") proxy.#[[$modal]]#.msgSuccess("新增成功");
open.value = false open.value = false;
getList() getList();
}) });
} }
} }
}) });
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
function handleDelete(row) { function handleDelete(row) {
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() { proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
return del${BusinessName}(row.${pkColumn.javaField}) return del${BusinessName}(row.${pkColumn.javaField});
}).then(() => { }).then(() => {
getList() getList();
proxy.#[[$modal]]#.msgSuccess("删除成功") proxy.#[[$modal]]#.msgSuccess("删除成功");
}).catch(() => {}) }).catch(() => {});
} }
getList() getList();
</script> </script>

View File

@@ -73,7 +73,7 @@
plain plain
icon="Plus" icon="Plus"
@click="handleAdd" @click="handleAdd"
v-hasPermi="['${permissionPrefix}:add']" v-hasPermi="['${moduleName}:${businessName}:add']"
>新增</el-button> >新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -83,7 +83,7 @@
icon="Edit" icon="Edit"
:disabled="single" :disabled="single"
@click="handleUpdate" @click="handleUpdate"
v-hasPermi="['${permissionPrefix}:edit']" v-hasPermi="['${moduleName}:${businessName}:edit']"
>修改</el-button> >修改</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -93,7 +93,7 @@
icon="Delete" icon="Delete"
:disabled="multiple" :disabled="multiple"
@click="handleDelete" @click="handleDelete"
v-hasPermi="['${permissionPrefix}:remove']" v-hasPermi="['${moduleName}:${businessName}:remove']"
>删除</el-button> >删除</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@@ -102,7 +102,7 @@
plain plain
icon="Download" icon="Download"
@click="handleExport" @click="handleExport"
v-hasPermi="['${permissionPrefix}:export']" v-hasPermi="['${moduleName}:${businessName}:export']"
>导出</el-button> >导出</el-button>
</el-col> </el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
@@ -148,8 +148,8 @@
#end #end
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${permissionPrefix}:edit']">修改</el-button> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${permissionPrefix}:remove']">删除</el-button> <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -343,33 +343,33 @@
</template> </template>
<script setup name="${BusinessName}"> <script setup name="${BusinessName}">
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}" import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance();
#if(${dicts} != '') #if(${dicts} != '')
#set($dictsNoSymbol=$dicts.replace("'", "")) #set($dictsNoSymbol=$dicts.replace("'", ""))
const { ${dictsNoSymbol} } = proxy.useDict(${dicts}) const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
#end #end
const ${businessName}List = ref([]) const ${businessName}List = ref([]);
#if($table.sub) #if($table.sub)
const ${subclassName}List = ref([]) const ${subclassName}List = ref([]);
#end #end
const open = ref(false) const open = ref(false);
const loading = ref(true) const loading = ref(true);
const showSearch = ref(true) const showSearch = ref(true);
const ids = ref([]) const ids = ref([]);
#if($table.sub) #if($table.sub)
const checked${subClassName} = ref([]) const checked${subClassName} = ref([]);
#end #end
const single = ref(true) const single = ref(true);
const multiple = ref(true) const multiple = ref(true);
const total = ref(0) const total = ref(0);
const title = ref("") const title = ref("");
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
const daterange${AttrName} = ref([]) const daterange${AttrName} = ref([]);
#end #end
#end #end
@@ -399,39 +399,39 @@ const data = reactive({
#end #end
#end #end
} }
}) });
const { queryParams, form, rules } = toRefs(data) const { queryParams, form, rules } = toRefs(data);
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
function getList() { function getList() {
loading.value = true loading.value = true;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
queryParams.value.params = {} queryParams.value.params = {};
#break #break
#end #end
#end #end
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) { if (null != daterange${AttrName} && '' != daterange${AttrName}) {
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0] queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1] queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
} }
#end #end
#end #end
list${BusinessName}(queryParams.value).then(response => { list${BusinessName}(queryParams.value).then(response => {
${businessName}List.value = response.rows ${businessName}List.value = response.rows;
total.value = response.total total.value = response.total;
loading.value = false loading.value = false;
}) });
} }
// 取消按钮 // 取消按钮
function cancel() { function cancel() {
open.value = false open.value = false;
reset() reset();
} }
// 表单重置 // 表单重置
@@ -444,17 +444,17 @@ function reset() {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
} };
#if($table.sub) #if($table.sub)
${subclassName}List.value = [] ${subclassName}List.value = [];
#end #end
proxy.resetForm("${businessName}Ref") proxy.resetForm("${businessName}Ref");
} }
/** 搜索按钮操作 */ /** 搜索按钮操作 */
function handleQuery() { function handleQuery() {
queryParams.value.pageNum = 1 queryParams.value.pageNum = 1;
getList() getList();
} }
/** 重置按钮操作 */ /** 重置按钮操作 */
@@ -462,44 +462,44 @@ function resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
daterange${AttrName}.value = [] daterange${AttrName}.value = [];
#end #end
#end #end
proxy.resetForm("queryRef") proxy.resetForm("queryRef");
handleQuery() handleQuery();
} }
// 多选框选中数据 // 多选框选中数据
function handleSelectionChange(selection) { function handleSelectionChange(selection) {
ids.value = selection.map(item => item.${pkColumn.javaField}) ids.value = selection.map(item => item.${pkColumn.javaField});
single.value = selection.length != 1 single.value = selection.length != 1;
multiple.value = !selection.length multiple.value = !selection.length;
} }
/** 新增按钮操作 */ /** 新增按钮操作 */
function handleAdd() { function handleAdd() {
reset() reset();
open.value = true open.value = true;
title.value = "添加${functionName}" title.value = "添加${functionName}";
} }
/** 修改按钮操作 */ /** 修改按钮操作 */
function handleUpdate(row) { function handleUpdate(row) {
reset() reset();
const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
get${BusinessName}(_${pkColumn.javaField}).then(response => { get${BusinessName}(_${pkColumn.javaField}).then(response => {
form.value = response.data form.value = response.data;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.split(",") form.value.$column.javaField = form.value.${column.javaField}.split(",");
#end #end
#end #end
#if($table.sub) #if($table.sub)
${subclassName}List.value = response.data.${subclassName}List ${subclassName}List.value = response.data.${subclassName}List;
#end #end
open.value = true open.value = true;
title.value = "修改${functionName}" title.value = "修改${functionName}";
}) });
} }
/** 提交按钮 */ /** 提交按钮 */
@@ -508,68 +508,68 @@ function submitForm() {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.join(",") form.value.$column.javaField = form.value.${column.javaField}.join(",");
#end #end
#end #end
#if($table.sub) #if($table.sub)
form.value.${subclassName}List = ${subclassName}List.value form.value.${subclassName}List = ${subclassName}List.value;
#end #end
if (form.value.${pkColumn.javaField} != null) { if (form.value.${pkColumn.javaField} != null) {
update${BusinessName}(form.value).then(response => { update${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("修改成功") proxy.#[[$modal]]#.msgSuccess("修改成功");
open.value = false open.value = false;
getList() getList();
}) });
} else { } else {
add${BusinessName}(form.value).then(response => { add${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("新增成功") proxy.#[[$modal]]#.msgSuccess("新增成功");
open.value = false open.value = false;
getList() getList();
}) });
} }
} }
}) });
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
function handleDelete(row) { function handleDelete(row) {
const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value;
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() { proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(_${pkColumn.javaField}s) return del${BusinessName}(_${pkColumn.javaField}s);
}).then(() => { }).then(() => {
getList() getList();
proxy.#[[$modal]]#.msgSuccess("删除成功") proxy.#[[$modal]]#.msgSuccess("删除成功");
}).catch(() => {}) }).catch(() => {});
} }
#if($table.sub) #if($table.sub)
/** ${subTable.functionName}序号 */ /** ${subTable.functionName}序号 */
function row${subClassName}Index({ row, rowIndex }) { function row${subClassName}Index({ row, rowIndex }) {
row.index = rowIndex + 1 row.index = rowIndex + 1;
} }
/** ${subTable.functionName}添加按钮操作 */ /** ${subTable.functionName}添加按钮操作 */
function handleAdd${subClassName}() { function handleAdd${subClassName}() {
let obj = {} let obj = {};
#foreach($column in $subTable.columns) #foreach($column in $subTable.columns)
#if($column.pk || $column.javaField == ${subTableFkclassName}) #if($column.pk || $column.javaField == ${subTableFkclassName})
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
obj.$column.javaField = "" obj.$column.javaField = "";
#end #end
#end #end
${subclassName}List.value.push(obj) ${subclassName}List.value.push(obj);
} }
/** ${subTable.functionName}删除按钮操作 */ /** ${subTable.functionName}删除按钮操作 */
function handleDelete${subClassName}() { function handleDelete${subClassName}() {
if (checked${subClassName}.value.length == 0) { if (checked${subClassName}.value.length == 0) {
proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据") proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据");
} else { } else {
const ${subclassName}s = ${subclassName}List.value const ${subclassName}s = ${subclassName}List.value;
const checked${subClassName}s = checked${subClassName}.value const checked${subClassName}s = checked${subClassName}.value;
${subclassName}List.value = ${subclassName}s.filter(function(item) { ${subclassName}List.value = ${subclassName}s.filter(function(item) {
return checked${subClassName}s.indexOf(item.index) == -1 return checked${subClassName}s.indexOf(item.index) == -1
}) });
} }
} }
@@ -586,5 +586,5 @@ function handleExport() {
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`) }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
} }
getList() getList();
</script> </script>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -40,7 +40,14 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Quartz --> <!-- Quartz -->
<dependency> <dependency>
<groupId>org.quartz-scheduler</groupId> <groupId>org.quartz-scheduler</groupId>

View File

@@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.ruoyi.common.security.annotation.EnableCustomConfig; import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients; import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
/** /**
* 定时任务 * 定时任务
@@ -11,6 +12,7 @@ import com.ruoyi.common.security.annotation.EnableRyFeignClients;
* @author ruoyi * @author ruoyi
*/ */
@EnableCustomConfig @EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients @EnableRyFeignClients
@SpringBootApplication @SpringBootApplication
public class RuoYiJobApplication public class RuoYiJobApplication

View File

@@ -178,7 +178,7 @@ public class SysJobController extends BaseController
@RequiresPermissions("monitor:job:remove") @RequiresPermissions("monitor:job:remove")
@Log(title = "定时任务", businessType = BusinessType.DELETE) @Log(title = "定时任务", businessType = BusinessType.DELETE)
@DeleteMapping("/{jobIds}") @DeleteMapping("/{jobIds}")
public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException
{ {
jobService.deleteJobByIds(jobIds); jobService.deleteJobByIds(jobIds);
return success(); return success();

View File

@@ -3,6 +3,7 @@ package com.ruoyi.job.util;
import java.util.Date; import java.util.Date;
import org.quartz.Job; import org.quartz.Job;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.ruoyi.common.core.constant.ScheduleConstants; import com.ruoyi.common.core.constant.ScheduleConstants;
@@ -29,7 +30,7 @@ public abstract class AbstractQuartzJob implements Job
private static ThreadLocal<Date> threadLocal = new ThreadLocal<>(); private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
@Override @Override
public void execute(JobExecutionContext context) public void execute(JobExecutionContext context) throws JobExecutionException
{ {
SysJob sysJob = new SysJob(); SysJob sysJob = new SysJob();
BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));

View File

@@ -105,7 +105,7 @@ public class JobInvokeUtil
*/ */
public static List<Object[]> getMethodParams(String invokeTarget) public static List<Object[]> getMethodParams(String invokeTarget)
{ {
String methodStr = StringUtils.substringBetweenLast(invokeTarget, "(", ")"); String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")");
if (StringUtils.isEmpty(methodStr)) if (StringUtils.isEmpty(methodStr))
{ {
return null; return null;

View File

@@ -131,11 +131,11 @@ public class ScheduleUtils
int count = StringUtils.countMatches(packageName, "."); int count = StringUtils.countMatches(packageName, ".");
if (count > 1) if (count > 1)
{ {
return StringUtils.startsWithAny(invokeTarget, Constants.JOB_WHITELIST_STR); return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR);
} }
Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]); Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]);
String beanPackageName = obj.getClass().getPackage().getName(); String beanPackageName = obj.getClass().getPackage().getName();
return StringUtils.startsWithAny(beanPackageName, Constants.JOB_WHITELIST_STR) return StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_WHITELIST_STR)
&& !StringUtils.startsWithAny(beanPackageName, Constants.JOB_ERROR_STR); && !StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_ERROR_STR);
} }
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -40,7 +40,14 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Mysql Connector --> <!-- Mysql Connector -->
<dependency> <dependency>
<groupId>com.mysql</groupId> <groupId>com.mysql</groupId>

View File

@@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.ruoyi.common.security.annotation.EnableCustomConfig; import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients; import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
/** /**
* 系统模块 * 系统模块
@@ -11,6 +12,7 @@ import com.ruoyi.common.security.annotation.EnableRyFeignClients;
* @author ruoyi * @author ruoyi
*/ */
@EnableCustomConfig @EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients @EnableRyFeignClients
@SpringBootApplication @SpringBootApplication
public class RuoYiSystemApplication public class RuoYiSystemApplication

View File

@@ -97,10 +97,6 @@ public class SysMenuController extends BaseController
{ {
return error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头"); return error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
} }
else if (!menuService.checkRouteConfigUnique(menu))
{
return error("新增菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
}
menu.setCreateBy(SecurityUtils.getUsername()); menu.setCreateBy(SecurityUtils.getUsername());
return toAjax(menuService.insertMenu(menu)); return toAjax(menuService.insertMenu(menu));
} }
@@ -125,10 +121,6 @@ public class SysMenuController extends BaseController
{ {
return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
} }
else if (!menuService.checkRouteConfigUnique(menu))
{
return error("修改菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
}
menu.setUpdateBy(SecurityUtils.getUsername()); menu.setUpdateBy(SecurityUtils.getUsername());
return toAjax(menuService.updateMenu(menu)); return toAjax(menuService.updateMenu(menu));
} }

View File

@@ -1,7 +1,6 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@@ -12,7 +11,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileTypeUtils; import com.ruoyi.common.core.utils.file.FileTypeUtils;
import com.ruoyi.common.core.utils.file.MimeTypeUtils; import com.ruoyi.common.core.utils.file.MimeTypeUtils;
@@ -95,13 +93,11 @@ public class SysProfileController extends BaseController
*/ */
@Log(title = "个人信息", businessType = BusinessType.UPDATE) @Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping("/updatePwd") @PutMapping("/updatePwd")
public AjaxResult updatePwd(@RequestBody Map<String, String> params) public AjaxResult updatePwd(String oldPassword, String newPassword)
{ {
String oldPassword = params.get("oldPassword"); String username = SecurityUtils.getUsername();
String newPassword = params.get("newPassword"); SysUser user = userService.selectUserByUserName(username);
LoginUser loginUser = SecurityUtils.getLoginUser(); String password = user.getPassword();
Long userId = loginUser.getUserid();
String password = loginUser.getSysUser().getPassword();
if (!SecurityUtils.matchesPassword(oldPassword, password)) if (!SecurityUtils.matchesPassword(oldPassword, password))
{ {
return error("修改密码失败,旧密码错误"); return error("修改密码失败,旧密码错误");
@@ -111,10 +107,10 @@ public class SysProfileController extends BaseController
return error("新密码不能与旧密码相同"); return error("新密码不能与旧密码相同");
} }
newPassword = SecurityUtils.encryptPassword(newPassword); newPassword = SecurityUtils.encryptPassword(newPassword);
if (userService.resetUserPwd(userId, newPassword) > 0) if (userService.resetUserPwd(username, newPassword) > 0)
{ {
// 更新缓存用户密码&密码最后更新时间 // 更新缓存用户密码
loginUser.getSysUser().setPwdUpdateDate(DateUtils.getNowDate()); LoginUser loginUser = SecurityUtils.getLoginUser();
loginUser.getSysUser().setPassword(newPassword); loginUser.getSysUser().setPassword(newPassword);
tokenService.setLoginUser(loginUser); tokenService.setLoginUser(loginUser);
return success(); return success();
@@ -143,13 +139,8 @@ public class SysProfileController extends BaseController
return error("文件服务异常,请联系管理员"); return error("文件服务异常,请联系管理员");
} }
String url = fileResult.getData().getUrl(); String url = fileResult.getData().getUrl();
if (userService.updateUserAvatar(loginUser.getUserid(), url)) if (userService.updateUserAvatar(loginUser.getUsername(), url))
{ {
String oldAvatarUrl = loginUser.getSysUser().getAvatar();
if (StringUtils.isNotEmpty(oldAvatarUrl))
{
remoteFileService.delete(oldAvatarUrl);
}
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
ajax.put("imgUrl", url); ajax.put("imgUrl", url);
// 更新缓存用户头像 // 更新缓存用户头像

View File

@@ -1,7 +1,6 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.io.IOException; import java.io.IOException;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -19,8 +18,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.controller.BaseController;
@@ -30,7 +27,6 @@ import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.InnerAuth; import com.ruoyi.common.security.annotation.InnerAuth;
import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.domain.SysDept; import com.ruoyi.system.api.domain.SysDept;
import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysRole;
@@ -70,9 +66,6 @@ public class SysUserController extends BaseController
@Autowired @Autowired
private ISysConfigService configService; private ISysConfigService configService;
@Autowired
private TokenService tokenService;
/** /**
* 获取用户列表 * 获取用户列表
*/ */
@@ -163,7 +156,7 @@ public class SysUserController extends BaseController
@PutMapping("/recordlogin") @PutMapping("/recordlogin")
public R<Boolean> recordlogin(@RequestBody SysUser sysUser) public R<Boolean> recordlogin(@RequestBody SysUser sysUser)
{ {
return R.ok(userService.updateLoginInfo(sysUser)); return R.ok(userService.updateUserProfile(sysUser));
} }
/** /**
@@ -174,50 +167,18 @@ public class SysUserController extends BaseController
@GetMapping("getInfo") @GetMapping("getInfo")
public AjaxResult getInfo() public AjaxResult getInfo()
{ {
LoginUser loginUser = SecurityUtils.getLoginUser(); SysUser user = userService.selectUserById(SecurityUtils.getUserId());
SysUser user = loginUser.getSysUser();
// 角色集合 // 角色集合
Set<String> roles = permissionService.getRolePermission(user); Set<String> roles = permissionService.getRolePermission(user);
// 权限集合 // 权限集合
Set<String> permissions = permissionService.getMenuPermission(user); Set<String> permissions = permissionService.getMenuPermission(user);
if (!loginUser.getPermissions().equals(permissions))
{
loginUser.setPermissions(permissions);
tokenService.refreshToken(loginUser);
}
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
ajax.put("user", user); ajax.put("user", user);
ajax.put("roles", roles); ajax.put("roles", roles);
ajax.put("permissions", permissions); ajax.put("permissions", permissions);
ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
return ajax; return ajax;
} }
// 检查初始密码是否提醒修改
public boolean initPasswordIsModify(Date pwdUpdateDate)
{
Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
}
// 检查密码是否过期
public boolean passwordIsExpiration(Date pwdUpdateDate)
{
Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
if (passwordValidateDays != null && passwordValidateDays > 0)
{
if (StringUtils.isNull(pwdUpdateDate))
{
// 如果从未修改过初始密码,直接提醒过期
return true;
}
Date nowDate = DateUtils.getNowDate();
return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
}
return false;
}
/** /**
* 根据用户编号获取详细信息 * 根据用户编号获取详细信息
*/ */
@@ -225,18 +186,18 @@ public class SysUserController extends BaseController
@GetMapping(value = { "/", "/{userId}" }) @GetMapping(value = { "/", "/{userId}" })
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
{ {
userService.checkUserDataScope(userId);
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
List<SysRole> roles = roleService.selectRoleAll();
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
ajax.put("posts", postService.selectPostAll());
if (StringUtils.isNotNull(userId)) if (StringUtils.isNotNull(userId))
{ {
userService.checkUserDataScope(userId);
SysUser sysUser = userService.selectUserById(userId); SysUser sysUser = userService.selectUserById(userId);
ajax.put(AjaxResult.DATA_TAG, sysUser); ajax.put(AjaxResult.DATA_TAG, sysUser);
ajax.put("postIds", postService.selectPostListByUserId(userId)); ajax.put("postIds", postService.selectPostListByUserId(userId));
ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList())); ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
} }
List<SysRole> roles = roleService.selectRoleAll();
ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
ajax.put("posts", postService.selectPostAll());
return ajax; return ajax;
} }
@@ -350,7 +311,7 @@ public class SysUserController extends BaseController
SysUser user = userService.selectUserById(userId); SysUser user = userService.selectUserById(userId);
List<SysRole> roles = roleService.selectRolesByUserId(userId); List<SysRole> roles = roleService.selectRolesByUserId(userId);
ajax.put("user", user); ajax.put("user", user);
ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
return ajax; return ajax;
} }

View File

@@ -4,8 +4,6 @@ import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.system.api.domain.SysDept; import com.ruoyi.system.api.domain.SysDept;
import com.ruoyi.system.domain.SysMenu; import com.ruoyi.system.domain.SysMenu;
@@ -24,9 +22,6 @@ public class TreeSelect implements Serializable
/** 节点名称 */ /** 节点名称 */
private String label; private String label;
/** 节点禁用 */
private boolean disabled = false;
/** 子节点 */ /** 子节点 */
@JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<TreeSelect> children; private List<TreeSelect> children;
@@ -40,7 +35,6 @@ public class TreeSelect implements Serializable
{ {
this.id = dept.getDeptId(); this.id = dept.getDeptId();
this.label = dept.getDeptName(); this.label = dept.getDeptName();
this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus());
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
} }
@@ -71,16 +65,6 @@ public class TreeSelect implements Serializable
this.label = label; this.label = label;
} }
public boolean isDisabled()
{
return disabled;
}
public void setDisabled(boolean disabled)
{
this.disabled = disabled;
}
public List<TreeSelect> getChildren() public List<TreeSelect> getChildren()
{ {
return children; return children;

View File

@@ -122,13 +122,4 @@ public interface SysMenuMapper
* @return 结果 * @return 结果
*/ */
public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId); public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId);
/**
* 根据路由路径或名称查询菜单信息(用于唯一性校验)
*
* @param path 路由地址
* @param routeName 路由名称
* @return 匹配的菜单列表
*/
public List<SysMenu> selectMenusByPathOrRouteName(@Param("path") String path, @Param("routeName") String routeName);
} }

View File

@@ -70,37 +70,20 @@ public interface SysUserMapper
/** /**
* 修改用户头像 * 修改用户头像
* *
* @param userId 用户ID * @param userName 用户
* @param avatar 头像地址 * @param avatar 头像地址
* @return 结果 * @return 结果
*/ */
public int updateUserAvatar(@Param("userId") Long userId, @Param("avatar") String avatar); public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar);
/**
* 修改用户状态
*
* @param userId 用户ID
* @param status 状态
* @return 结果
*/
public int updateUserStatus(@Param("userId") Long userId, @Param("status") String status);
/**
* 更新用户登录信息IP和登录时间
*
* @param user 用户信息
* @return 结果
*/
public int updateLoginInfo(SysUser user);
/** /**
* 重置用户密码 * 重置用户密码
* *
* @param userId 用户ID * @param userName 用户
* @param password 密码 * @param password 密码
* @return 结果 * @return 结果
*/ */
public int resetUserPwd(@Param("userId") Long userId, @Param("password") String password); public int resetUserPwd(@Param("userName") String userName, @Param("password") String password);
/** /**
* 通过用户ID删除用户 * 通过用户ID删除用户

View File

@@ -141,12 +141,4 @@ public interface ISysMenuService
* @return 结果 * @return 结果
*/ */
public boolean checkMenuNameUnique(SysMenu menu); public boolean checkMenuNameUnique(SysMenu menu);
/**
* 校验路由组合是否唯一
*
* @param menu 菜单信息
* @return 结果
*/
public boolean checkRouteConfigUnique(SysMenu menu);
} }

View File

@@ -155,19 +155,11 @@ public interface ISysUserService
/** /**
* 修改用户头像 * 修改用户头像
* *
* @param userId 用户ID * @param userName 用户
* @param avatar 头像地址 * @param avatar 头像地址
* @return 结果 * @return 结果
*/ */
public boolean updateUserAvatar(Long userId, String avatar); public boolean updateUserAvatar(String userName, String avatar);
/**
* 更新用户登录信息IP和登录时间
*
* @param user 用户信息
* @return 结果
*/
public boolean updateLoginInfo(SysUser user);
/** /**
* 重置用户密码 * 重置用户密码
@@ -180,11 +172,11 @@ public interface ISysUserService
/** /**
* 重置用户密码 * 重置用户密码
* *
* @param userId 用户ID * @param userName 用户
* @param password 密码 * @param password 密码
* @return 结果 * @return 结果
*/ */
public int resetUserPwd(Long userId, String password); public int resetUserPwd(String userName, String password);
/** /**
* 通过用户ID删除用户 * 通过用户ID删除用户

View File

@@ -15,6 +15,7 @@ import com.ruoyi.common.datascope.annotation.DataScope;
import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.domain.SysDept; import com.ruoyi.system.api.domain.SysDept;
import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysRole;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.domain.vo.TreeSelect; import com.ruoyi.system.domain.vo.TreeSelect;
import com.ruoyi.system.mapper.SysDeptMapper; import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.mapper.SysRoleMapper; import com.ruoyi.system.mapper.SysRoleMapper;
@@ -189,7 +190,7 @@ public class SysDeptServiceImpl implements ISysDeptService
@Override @Override
public void checkDeptDataScope(Long deptId) public void checkDeptDataScope(Long deptId)
{ {
if (!SecurityUtils.isAdmin() && StringUtils.isNotNull(deptId)) if (!SysUser.isAdmin(SecurityUtils.getUserId()) && StringUtils.isNotNull(deptId))
{ {
SysDept dept = new SysDept(); SysDept dept = new SysDept();
dept.setDeptId(deptId); dept.setDeptId(deptId);

View File

@@ -8,8 +8,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.constant.Constants;
@@ -17,6 +15,7 @@ import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysRole;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.domain.SysMenu; import com.ruoyi.system.domain.SysMenu;
import com.ruoyi.system.domain.vo.MetaVo; import com.ruoyi.system.domain.vo.MetaVo;
import com.ruoyi.system.domain.vo.RouterVo; import com.ruoyi.system.domain.vo.RouterVo;
@@ -34,12 +33,8 @@ import com.ruoyi.system.service.ISysMenuService;
@Service @Service
public class SysMenuServiceImpl implements ISysMenuService public class SysMenuServiceImpl implements ISysMenuService
{ {
private static final Logger log = LoggerFactory.getLogger(SysMenuServiceImpl.class);
public static final String PREMISSION_STRING = "perms[\"{0}\"]"; public static final String PREMISSION_STRING = "perms[\"{0}\"]";
public static final Long MENU_ROOT_ID = 0L;
@Autowired @Autowired
private SysMenuMapper menuMapper; private SysMenuMapper menuMapper;
@@ -72,7 +67,7 @@ public class SysMenuServiceImpl implements ISysMenuService
{ {
List<SysMenu> menuList = null; List<SysMenu> menuList = null;
// 管理员显示所有菜单信息 // 管理员显示所有菜单信息
if (SecurityUtils.isAdmin(userId)) if (SysUser.isAdmin(userId))
{ {
menuList = menuMapper.selectMenuList(menu); menuList = menuMapper.selectMenuList(menu);
} }
@@ -144,7 +139,7 @@ public class SysMenuServiceImpl implements ISysMenuService
{ {
menus = menuMapper.selectMenuTreeByUserId(userId); menus = menuMapper.selectMenuTreeByUserId(userId);
} }
return getChildPerms(menus, MENU_ROOT_ID); return getChildPerms(menus, 0);
} }
/** /**
@@ -199,7 +194,7 @@ public class SysMenuServiceImpl implements ISysMenuService
childrenList.add(children); childrenList.add(children);
router.setChildren(childrenList); router.setChildren(childrenList);
} }
else if (menu.getParentId().intValue() == MENU_ROOT_ID && isInnerLink(menu)) else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
{ {
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
router.setPath("/"); router.setPath("/");
@@ -351,47 +346,6 @@ public class SysMenuServiceImpl implements ISysMenuService
return UserConstants.UNIQUE; return UserConstants.UNIQUE;
} }
/**
* 校验路由名称是否唯一
*
* @param menu 菜单信息
* @return 结果
*/
@Override
public boolean checkRouteConfigUnique(SysMenu menu)
{
Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
Long parentId = menu.getParentId();
String path = menu.getPath();
String routeName = StringUtils.isEmpty(menu.getRouteName()) ? path : menu.getRouteName();
List<SysMenu> sysMenuList = menuMapper.selectMenusByPathOrRouteName(path, routeName);
for (SysMenu sysMenu : sysMenuList)
{
if (sysMenu.getMenuId().longValue() != menuId.longValue())
{
Long dbParentId = sysMenu.getParentId();
String dbPath = sysMenu.getPath();
String dbRouteName = StringUtils.isEmpty(sysMenu.getRouteName()) ? dbPath : sysMenu.getRouteName();
if (StringUtils.equalsAnyIgnoreCase(path, dbPath) && parentId.longValue() == dbParentId.longValue())
{
log.warn("[同级路由冲突] 同级下已存在相同路由路径 '{}',冲突菜单:{}", dbPath, sysMenu.getMenuName());
return UserConstants.NOT_UNIQUE;
}
else if (StringUtils.equalsAnyIgnoreCase(path, dbPath) && parentId.longValue() == MENU_ROOT_ID)
{
log.warn("[根目录路由冲突] 根目录下路由 '{}' 必须唯一,已被菜单 '{}' 占用", path, sysMenu.getMenuName());
return UserConstants.NOT_UNIQUE;
}
else if (StringUtils.equalsAnyIgnoreCase(routeName, dbRouteName))
{
log.warn("[路由名称冲突] 路由名称 '{}' 需全局唯一,已被菜单 '{}' 使用", routeName, sysMenu.getMenuName());
return UserConstants.NOT_UNIQUE;
}
}
}
return UserConstants.UNIQUE;
}
/** /**
* 获取路由名称 * 获取路由名称
* *
@@ -411,7 +365,7 @@ public class SysMenuServiceImpl implements ISysMenuService
/** /**
* 获取路由名称,如没有配置路由名称则取路由地址 * 获取路由名称,如没有配置路由名称则取路由地址
* *
* @param name 路由名称 * @param routerName 路由名称
* @param path 路由地址 * @param path 路由地址
* @return 路由名称(驼峰格式) * @return 路由名称(驼峰格式)
*/ */
@@ -431,12 +385,12 @@ public class SysMenuServiceImpl implements ISysMenuService
{ {
String routerPath = menu.getPath(); String routerPath = menu.getPath();
// 内链打开外网方式 // 内链打开外网方式
if (menu.getParentId().intValue() != MENU_ROOT_ID && isInnerLink(menu)) if (menu.getParentId().intValue() != 0 && isInnerLink(menu))
{ {
routerPath = innerLinkReplaceEach(routerPath); routerPath = innerLinkReplaceEach(routerPath);
} }
// 非外链并且是一级目录(类型为目录) // 非外链并且是一级目录(类型为目录)
if (MENU_ROOT_ID == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
&& UserConstants.NO_FRAME.equals(menu.getIsFrame())) && UserConstants.NO_FRAME.equals(menu.getIsFrame()))
{ {
routerPath = "/" + menu.getPath(); routerPath = "/" + menu.getPath();
@@ -462,7 +416,7 @@ public class SysMenuServiceImpl implements ISysMenuService
{ {
component = menu.getComponent(); component = menu.getComponent();
} }
else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != MENU_ROOT_ID && isInnerLink(menu)) else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu))
{ {
component = UserConstants.INNER_LINK; component = UserConstants.INNER_LINK;
} }
@@ -481,21 +435,10 @@ public class SysMenuServiceImpl implements ISysMenuService
*/ */
public boolean isMenuFrame(SysMenu menu) public boolean isMenuFrame(SysMenu menu)
{ {
return menu.getParentId().intValue() == MENU_ROOT_ID && UserConstants.TYPE_MENU.equals(menu.getMenuType()) return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
&& menu.getIsFrame().equals(UserConstants.NO_FRAME); && menu.getIsFrame().equals(UserConstants.NO_FRAME);
} }
/**
* 是否为parent_view组件
*
* @param menu 菜单信息
* @return 结果
*/
public boolean isParentView(SysMenu menu)
{
return menu.getParentId().intValue() != MENU_ROOT_ID && UserConstants.TYPE_DIR.equals(menu.getMenuType());
}
/** /**
* 是否为内链组件 * 是否为内链组件
* *
@@ -507,6 +450,17 @@ public class SysMenuServiceImpl implements ISysMenuService
return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath()); return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath());
} }
/**
* 是否为parent_view组件
*
* @param menu 菜单信息
* @return 结果
*/
public boolean isParentView(SysMenu menu)
{
return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
}
/** /**
* 根据父节点的ID获取所有子节点 * 根据父节点的ID获取所有子节点
* *
@@ -514,7 +468,7 @@ public class SysMenuServiceImpl implements ISysMenuService
* @param parentId 传入的父节点ID * @param parentId 传入的父节点ID
* @return String * @return String
*/ */
public List<SysMenu> getChildPerms(List<SysMenu> list, long parentId) public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId)
{ {
List<SysMenu> returnList = new ArrayList<SysMenu>(); List<SysMenu> returnList = new ArrayList<SysMenu>();
for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();) for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();)

View File

@@ -6,9 +6,6 @@ import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysRole;
import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.service.ISysMenuService; import com.ruoyi.system.service.ISysMenuService;
@@ -42,7 +39,7 @@ public class SysPermissionServiceImpl implements ISysPermissionService
// 管理员拥有所有权限 // 管理员拥有所有权限
if (user.isAdmin()) if (user.isAdmin())
{ {
roles.add(Constants.SUPER_ADMIN); roles.add("admin");
} }
else else
{ {
@@ -64,7 +61,7 @@ public class SysPermissionServiceImpl implements ISysPermissionService
// 管理员拥有所有权限 // 管理员拥有所有权限
if (user.isAdmin()) if (user.isAdmin())
{ {
perms.add(Constants.ALL_PERMISSION); perms.add("*:*:*");
} }
else else
{ {
@@ -74,12 +71,9 @@ public class SysPermissionServiceImpl implements ISysPermissionService
// 多角色设置permissions属性以便数据权限匹配权限 // 多角色设置permissions属性以便数据权限匹配权限
for (SysRole role : roles) for (SysRole role : roles)
{ {
if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && !role.isAdmin()) Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
{ role.setPermissions(rolePerms);
Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId()); perms.addAll(rolePerms);
role.setPermissions(rolePerms);
perms.addAll(rolePerms);
}
} }
} }
else else

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