mirror of
https://gitee.com/y_project/RuoYi-Vue.git
synced 2026-04-30 00:00:08 +08:00
Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a811d9824 | |||
| 1c9c076280 | |||
| 918f94d8da | |||
| 5db610d16f | |||
| cc6f983ee3 | |||
| afe2852bbb | |||
| 9c7d302b94 | |||
| 9e66ada9c1 | |||
| a63eec3be4 | |||
| 51990695f5 | |||
| a7b8f2ee90 | |||
| 67ba621db6 | |||
| 05feef34c7 | |||
| be0b36f6b9 | |||
| 69bbccbd76 | |||
| 1eb7b3a03f | |||
| 4661edf7f0 | |||
| 8485605145 | |||
| a4fe88ca61 | |||
| af15a3b274 | |||
| 571393c32c | |||
| eff06c110f | |||
| 6a18e06339 | |||
| f04ca57f7a | |||
| b4f2a4f7dd | |||
| de0a43285f | |||
| 4952ac0a3d | |||
| 6ad345331d | |||
| 5a634a4ecd | |||
| f5b865a2e1 | |||
| f7595e4998 | |||
| 64e71302e4 | |||
| 2e99c68ed0 | |||
| af0e0a110e | |||
| bef86e041f | |||
| 1067567f1c | |||
| 0a670fdfd7 | |||
| a33090c90e | |||
| 5061558e94 | |||
| e7f088552f | |||
| 5c4682e060 | |||
| 5d5ebbec1a | |||
| 23544bab5e | |||
| c5ef0336a4 | |||
| a907f8485c | |||
| 66200c4203 | |||
| 5a25212509 | |||
| 95742bf5bd | |||
| 4eea8cdbb0 | |||
| cfce89be7d | |||
| ce7e12ec1d | |||
| 4f02f3c6f7 | |||
| 5ca9bd6876 | |||
| 020a2d4670 | |||
| 635d621b7b | |||
| 4cbd56cbd7 | |||
| dcb9cb3d13 | |||
| 628bc94a9a | |||
| 38ddefe2e6 | |||
| 7a090bda1e | |||
| 4e8dd706d5 | |||
| 641e550d7f | |||
| 81a01a1d9d | |||
| 6523fe59a2 | |||
| 90970eb9fe | |||
| 3402b69556 | |||
| 2c5e3e429f | |||
| 96ba768f50 | |||
| 1268637e58 | |||
| 61caa7966b | |||
| a5f95eddab | |||
| ade70583e9 | |||
| 5676cf9ad4 | |||
| c3d0cd5f8c | |||
| eb96afee64 | |||
| 5873da87ae | |||
| 4f1933e2e4 | |||
| 9926f73cd0 | |||
| 492919d4af | |||
| a7ff50e695 | |||
| 71e7e1d6dd | |||
| 5073f95ccd |
@@ -1,11 +1,11 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
|
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
|
||||||
</p>
|
</p>
|
||||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.5</h1>
|
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.6</h1>
|
||||||
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
|
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.5-brightgreen.svg"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.6-brightgreen.svg"></a>
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -21,7 +21,6 @@
|
|||||||
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Vue3](https://github.com/yangzongzhuan/RuoYi-Vue3),保持同步更新。
|
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Vue3](https://github.com/yangzongzhuan/RuoYi-Vue3),保持同步更新。
|
||||||
* 提供了单应用版本[RuoYi-Vue-fast](https://github.com/yangzongzhuan/RuoYi-Vue-fast),Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
|
* 提供了单应用版本[RuoYi-Vue-fast](https://github.com/yangzongzhuan/RuoYi-Vue-fast),Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
|
||||||
* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
|
* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
|
||||||
* 特别鸣谢:[element](https://github.com/ElemeFE/element),[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin),[eladmin-web](https://github.com/elunez/eladmin-web)。
|
|
||||||
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)
|
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)
|
||||||
* 阿里云优惠券:[点我领取](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)
|
* 阿里云优惠券:[点我领取](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)
|
||||||
|
|
||||||
@@ -94,4 +93,4 @@
|
|||||||
|
|
||||||
## 若依前后端分离交流群
|
## 若依前后端分离交流群
|
||||||
|
|
||||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) 点击按钮入群。
|
QQ群: [](https://jq.qq.com/?_wv=1027&k=5bVB1og) [](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [](https://jq.qq.com/?_wv=1027&k=51G72yr) [](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [](https://jq.qq.com/?_wv=1027&k=SpyH2875) [](https://jq.qq.com/?_wv=1027&k=tKEt51dz) 点击按钮入群。
|
||||||
@@ -6,27 +6,26 @@
|
|||||||
|
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<version>3.8.5</version>
|
<version>3.8.6</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.8.5</ruoyi.version>
|
<ruoyi.version>3.8.6</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>
|
||||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||||
<druid.version>1.2.15</druid.version>
|
<druid.version>1.2.16</druid.version>
|
||||||
<bitwalker.version>1.21</bitwalker.version>
|
<bitwalker.version>1.21</bitwalker.version>
|
||||||
<swagger.version>3.0.0</swagger.version>
|
<swagger.version>3.0.0</swagger.version>
|
||||||
<kaptcha.version>2.3.3</kaptcha.version>
|
<kaptcha.version>2.3.3</kaptcha.version>
|
||||||
<pagehelper.boot.version>1.4.6</pagehelper.boot.version>
|
<pagehelper.boot.version>1.4.6</pagehelper.boot.version>
|
||||||
<fastjson.version>2.0.20</fastjson.version>
|
<fastjson.version>2.0.34</fastjson.version>
|
||||||
<oshi.version>6.4.0</oshi.version>
|
<oshi.version>6.4.3</oshi.version>
|
||||||
<commons.io.version>2.11.0</commons.io.version>
|
<commons.io.version>2.11.0</commons.io.version>
|
||||||
<commons.fileupload.version>1.4</commons.fileupload.version>
|
|
||||||
<commons.collections.version>3.2.2</commons.collections.version>
|
<commons.collections.version>3.2.2</commons.collections.version>
|
||||||
<poi.version>4.1.2</poi.version>
|
<poi.version>4.1.2</poi.version>
|
||||||
<velocity.version>2.3</velocity.version>
|
<velocity.version>2.3</velocity.version>
|
||||||
@@ -41,7 +40,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-dependencies</artifactId>
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
<version>2.5.14</version>
|
<version>2.5.15</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -94,13 +93,6 @@
|
|||||||
<version>${commons.io.version}</version>
|
<version>${commons.io.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 文件上传工具类 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-fileupload</groupId>
|
|
||||||
<artifactId>commons-fileupload</artifactId>
|
|
||||||
<version>${commons.fileupload.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- excel工具 -->
|
<!-- excel工具 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
@@ -191,11 +183,6 @@
|
|||||||
</modules>
|
</modules>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.5</version>
|
<version>3.8.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|||||||
+3
-12
@@ -49,24 +49,15 @@ public class SysUserOnlineController extends BaseController
|
|||||||
LoginUser user = redisCache.getCacheObject(key);
|
LoginUser user = redisCache.getCacheObject(key);
|
||||||
if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
|
if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
|
||||||
{
|
{
|
||||||
if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
|
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
|
||||||
{
|
|
||||||
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (StringUtils.isNotEmpty(ipaddr))
|
else if (StringUtils.isNotEmpty(ipaddr))
|
||||||
{
|
{
|
||||||
if (StringUtils.equals(ipaddr, user.getIpaddr()))
|
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
|
||||||
{
|
|
||||||
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
|
else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
|
||||||
{
|
{
|
||||||
if (StringUtils.equals(userName, user.getUsername()))
|
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
|
||||||
{
|
|
||||||
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
@@ -84,7 +83,7 @@ public class SysConfigController extends BaseController
|
|||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@Validated @RequestBody SysConfig config)
|
public AjaxResult add(@Validated @RequestBody SysConfig config)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
|
if (!configService.checkConfigKeyUnique(config))
|
||||||
{
|
{
|
||||||
return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
|
return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
|
||||||
}
|
}
|
||||||
@@ -100,7 +99,7 @@ public class SysConfigController extends BaseController
|
|||||||
@PutMapping
|
@PutMapping
|
||||||
public AjaxResult edit(@Validated @RequestBody SysConfig config)
|
public AjaxResult edit(@Validated @RequestBody SysConfig config)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
|
if (!configService.checkConfigKeyUnique(config))
|
||||||
{
|
{
|
||||||
return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
|
return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class SysDeptController extends BaseController
|
|||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@Validated @RequestBody SysDept dept)
|
public AjaxResult add(@Validated @RequestBody SysDept dept)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
|
if (!deptService.checkDeptNameUnique(dept))
|
||||||
{
|
{
|
||||||
return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
|
return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ public class SysDeptController extends BaseController
|
|||||||
{
|
{
|
||||||
Long deptId = dept.getDeptId();
|
Long deptId = dept.getDeptId();
|
||||||
deptService.checkDeptDataScope(deptId);
|
deptService.checkDeptDataScope(deptId);
|
||||||
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
|
if (!deptService.checkDeptNameUnique(dept))
|
||||||
{
|
{
|
||||||
return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
|
return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -14,7 +14,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.entity.SysDictType;
|
import com.ruoyi.common.core.domain.entity.SysDictType;
|
||||||
@@ -72,7 +71,7 @@ public class SysDictTypeController extends BaseController
|
|||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@Validated @RequestBody SysDictType dict)
|
public AjaxResult add(@Validated @RequestBody SysDictType dict)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict)))
|
if (!dictTypeService.checkDictTypeUnique(dict))
|
||||||
{
|
{
|
||||||
return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
|
return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
|
||||||
}
|
}
|
||||||
@@ -88,7 +87,7 @@ public class SysDictTypeController extends BaseController
|
|||||||
@PutMapping
|
@PutMapping
|
||||||
public AjaxResult edit(@Validated @RequestBody SysDictType dict)
|
public AjaxResult edit(@Validated @RequestBody SysDictType dict)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict)))
|
if (!dictTypeService.checkDictTypeUnique(dict))
|
||||||
{
|
{
|
||||||
return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
|
return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class SysMenuController extends BaseController
|
|||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@Validated @RequestBody SysMenu menu)
|
public AjaxResult add(@Validated @RequestBody SysMenu menu)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu)))
|
if (!menuService.checkMenuNameUnique(menu))
|
||||||
{
|
{
|
||||||
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ public class SysMenuController extends BaseController
|
|||||||
@PutMapping
|
@PutMapping
|
||||||
public AjaxResult edit(@Validated @RequestBody SysMenu menu)
|
public AjaxResult edit(@Validated @RequestBody SysMenu menu)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu)))
|
if (!menuService.checkMenuNameUnique(menu))
|
||||||
{
|
{
|
||||||
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
@@ -75,11 +74,11 @@ public class SysPostController extends BaseController
|
|||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@Validated @RequestBody SysPost post)
|
public AjaxResult add(@Validated @RequestBody SysPost post)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post)))
|
if (!postService.checkPostNameUnique(post))
|
||||||
{
|
{
|
||||||
return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
|
return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
|
||||||
}
|
}
|
||||||
else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post)))
|
else if (!postService.checkPostCodeUnique(post))
|
||||||
{
|
{
|
||||||
return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
|
return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
|
||||||
}
|
}
|
||||||
@@ -95,11 +94,11 @@ public class SysPostController extends BaseController
|
|||||||
@PutMapping
|
@PutMapping
|
||||||
public AjaxResult edit(@Validated @RequestBody SysPost post)
|
public AjaxResult edit(@Validated @RequestBody SysPost post)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post)))
|
if (!postService.checkPostNameUnique(post))
|
||||||
{
|
{
|
||||||
return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
|
return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
|
||||||
}
|
}
|
||||||
else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post)))
|
else if (!postService.checkPostCodeUnique(post))
|
||||||
{
|
{
|
||||||
return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
|
return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
@@ -63,13 +62,11 @@ public class SysProfileController extends BaseController
|
|||||||
LoginUser loginUser = getLoginUser();
|
LoginUser loginUser = getLoginUser();
|
||||||
SysUser sysUser = loginUser.getUser();
|
SysUser sysUser = loginUser.getUser();
|
||||||
user.setUserName(sysUser.getUserName());
|
user.setUserName(sysUser.getUserName());
|
||||||
if (StringUtils.isNotEmpty(user.getPhonenumber())
|
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
|
||||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
|
||||||
{
|
{
|
||||||
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(user.getEmail())
|
if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
|
||||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
|
||||||
{
|
{
|
||||||
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||||
@@ -94,11 +93,11 @@ public class SysRoleController extends BaseController
|
|||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@Validated @RequestBody SysRole role)
|
public AjaxResult add(@Validated @RequestBody SysRole role)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
|
if (!roleService.checkRoleNameUnique(role))
|
||||||
{
|
{
|
||||||
return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
||||||
}
|
}
|
||||||
else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role)))
|
else if (!roleService.checkRoleKeyUnique(role))
|
||||||
{
|
{
|
||||||
return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
||||||
}
|
}
|
||||||
@@ -117,11 +116,11 @@ public class SysRoleController extends BaseController
|
|||||||
{
|
{
|
||||||
roleService.checkRoleAllowed(role);
|
roleService.checkRoleAllowed(role);
|
||||||
roleService.checkRoleDataScope(role.getRoleId());
|
roleService.checkRoleDataScope(role.getRoleId());
|
||||||
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
|
if (!roleService.checkRoleNameUnique(role))
|
||||||
{
|
{
|
||||||
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
||||||
}
|
}
|
||||||
else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role)))
|
else if (!roleService.checkRoleKeyUnique(role))
|
||||||
{
|
{
|
||||||
return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,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.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||||
@@ -125,17 +124,15 @@ public class SysUserController extends BaseController
|
|||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@Validated @RequestBody SysUser user)
|
public AjaxResult add(@Validated @RequestBody SysUser user)
|
||||||
{
|
{
|
||||||
if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user)))
|
if (!userService.checkUserNameUnique(user))
|
||||||
{
|
{
|
||||||
return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
|
return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
|
||||||
}
|
}
|
||||||
else if (StringUtils.isNotEmpty(user.getPhonenumber())
|
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
|
||||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
|
||||||
{
|
{
|
||||||
return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
|
return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||||
}
|
}
|
||||||
else if (StringUtils.isNotEmpty(user.getEmail())
|
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
|
||||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
|
||||||
{
|
{
|
||||||
return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||||
}
|
}
|
||||||
@@ -154,17 +151,15 @@ public class SysUserController extends BaseController
|
|||||||
{
|
{
|
||||||
userService.checkUserAllowed(user);
|
userService.checkUserAllowed(user);
|
||||||
userService.checkUserDataScope(user.getUserId());
|
userService.checkUserDataScope(user.getUserId());
|
||||||
if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user)))
|
if (!userService.checkUserNameUnique(user))
|
||||||
{
|
{
|
||||||
return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
|
return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
|
||||||
}
|
}
|
||||||
else if (StringUtils.isNotEmpty(user.getPhonenumber())
|
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
|
||||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
|
||||||
{
|
{
|
||||||
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||||
}
|
}
|
||||||
else if (StringUtils.isNotEmpty(user.getEmail())
|
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
|
||||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
|
||||||
{
|
{
|
||||||
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ spring:
|
|||||||
maxActive: 20
|
maxActive: 20
|
||||||
# 配置获取连接等待超时的时间
|
# 配置获取连接等待超时的时间
|
||||||
maxWait: 60000
|
maxWait: 60000
|
||||||
|
# 配置连接超时时间
|
||||||
|
connectTimeout: 30000
|
||||||
|
# 配置网络超时时间
|
||||||
|
socketTimeout: 60000
|
||||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||||
timeBetweenEvictionRunsMillis: 60000
|
timeBetweenEvictionRunsMillis: 60000
|
||||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ruoyi:
|
|||||||
# 名称
|
# 名称
|
||||||
name: RuoYi
|
name: RuoYi
|
||||||
# 版本
|
# 版本
|
||||||
version: 3.8.5
|
version: 3.8.6
|
||||||
# 版权年份
|
# 版权年份
|
||||||
copyrightYear: 2023
|
copyrightYear: 2023
|
||||||
# 实例演示开关
|
# 实例演示开关
|
||||||
@@ -12,7 +12,7 @@ ruoyi:
|
|||||||
profile: D:/ruoyi/uploadPath
|
profile: D:/ruoyi/uploadPath
|
||||||
# 获取ip地址开关
|
# 获取ip地址开关
|
||||||
addressEnabled: false
|
addressEnabled: false
|
||||||
# 验证码类型 math 数组计算 char 字符验证
|
# 验证码类型 math 数字计算 char 字符验证
|
||||||
captchaType: math
|
captchaType: math
|
||||||
|
|
||||||
# 开发环境配置
|
# 开发环境配置
|
||||||
@@ -53,15 +53,15 @@ spring:
|
|||||||
messages:
|
messages:
|
||||||
# 国际化资源文件路径
|
# 国际化资源文件路径
|
||||||
basename: i18n/messages
|
basename: i18n/messages
|
||||||
profiles:
|
profiles:
|
||||||
active: druid
|
active: druid
|
||||||
# 文件上传
|
# 文件上传
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
# 单个文件大小
|
# 单个文件大小
|
||||||
max-file-size: 10MB
|
max-file-size: 10MB
|
||||||
# 设置总上传的文件大小
|
# 设置总上传的文件大小
|
||||||
max-request-size: 20MB
|
max-request-size: 20MB
|
||||||
# 服务模块
|
# 服务模块
|
||||||
devtools:
|
devtools:
|
||||||
restart:
|
restart:
|
||||||
@@ -76,7 +76,7 @@ spring:
|
|||||||
# 数据库索引
|
# 数据库索引
|
||||||
database: 0
|
database: 0
|
||||||
# 密码
|
# 密码
|
||||||
password:
|
password:
|
||||||
# 连接超时时间
|
# 连接超时时间
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
lettuce:
|
lettuce:
|
||||||
@@ -92,27 +92,27 @@ spring:
|
|||||||
|
|
||||||
# token配置
|
# token配置
|
||||||
token:
|
token:
|
||||||
# 令牌自定义标识
|
# 令牌自定义标识
|
||||||
header: Authorization
|
header: Authorization
|
||||||
# 令牌密钥
|
# 令牌密钥
|
||||||
secret: abcdefghijklmnopqrstuvwxyz
|
secret: abcdefghijklmnopqrstuvwxyz
|
||||||
# 令牌有效期(默认30分钟)
|
# 令牌有效期(默认30分钟)
|
||||||
expireTime: 30
|
expireTime: 30
|
||||||
|
|
||||||
# MyBatis配置
|
# MyBatis配置
|
||||||
mybatis:
|
mybatis:
|
||||||
# 搜索指定包别名
|
# 搜索指定包别名
|
||||||
typeAliasesPackage: com.ruoyi.**.domain
|
typeAliasesPackage: com.ruoyi.**.domain
|
||||||
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||||
# 加载全局的配置文件
|
# 加载全局的配置文件
|
||||||
configLocation: classpath:mybatis/mybatis-config.xml
|
configLocation: classpath:mybatis/mybatis-config.xml
|
||||||
|
|
||||||
# PageHelper分页插件
|
# PageHelper分页插件
|
||||||
pagehelper:
|
pagehelper:
|
||||||
helperDialect: mysql
|
helperDialect: mysql
|
||||||
supportMethodsArguments: true
|
supportMethodsArguments: true
|
||||||
params: count=countSql
|
params: count=countSql
|
||||||
|
|
||||||
# Swagger配置
|
# Swagger配置
|
||||||
swagger:
|
swagger:
|
||||||
@@ -122,7 +122,7 @@ swagger:
|
|||||||
pathMapping: /dev-api
|
pathMapping: /dev-api
|
||||||
|
|
||||||
# 防止XSS攻击
|
# 防止XSS攻击
|
||||||
xss:
|
xss:
|
||||||
# 过滤开关
|
# 过滤开关
|
||||||
enabled: true
|
enabled: true
|
||||||
# 排除链接(多个用逗号分隔)
|
# 排除链接(多个用逗号分隔)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分
|
|||||||
user.password.delete=对不起,您的账号已被删除
|
user.password.delete=对不起,您的账号已被删除
|
||||||
user.blocked=用户已封禁,请联系管理员
|
user.blocked=用户已封禁,请联系管理员
|
||||||
role.blocked=角色已封禁,请联系管理员
|
role.blocked=角色已封禁,请联系管理员
|
||||||
|
login.blocked=很遗憾,访问IP已被列入系统黑名单
|
||||||
user.logout.success=退出成功
|
user.logout.success=退出成功
|
||||||
|
|
||||||
length.not.valid=长度必须在{min}到{max}个字符之间
|
length.not.valid=长度必须在{min}到{max}个字符之间
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.5</version>
|
<version>3.8.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -78,12 +78,6 @@
|
|||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 文件上传工具类 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-fileupload</groupId>
|
|
||||||
<artifactId>commons-fileupload</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- excel工具 -->
|
<!-- excel工具 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
|
|||||||
@@ -59,12 +59,12 @@ public @interface Excel
|
|||||||
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
|
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出时在excel中每个列的高度 单位为字符
|
* 导出时在excel中每个列的高度
|
||||||
*/
|
*/
|
||||||
public double height() default 14;
|
public double height() default 14;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出时在excel中每个列的宽 单位为字符
|
* 导出时在excel中每个列的宽度
|
||||||
*/
|
*/
|
||||||
public double width() default 16;
|
public double width() default 16;
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ public @interface Excel
|
|||||||
public ColumnType cellType() default ColumnType.STRING;
|
public ColumnType cellType() default ColumnType.STRING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出列头背景色
|
* 导出列头背景颜色
|
||||||
*/
|
*/
|
||||||
public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
|
public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ public @interface Excel
|
|||||||
public IndexedColors headerColor() default IndexedColors.WHITE;
|
public IndexedColors headerColor() default IndexedColors.WHITE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出单元格背景色
|
* 导出单元格背景颜色
|
||||||
*/
|
*/
|
||||||
public IndexedColors backgroundColor() default IndexedColors.WHITE;
|
public IndexedColors backgroundColor() default IndexedColors.WHITE;
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import com.ruoyi.common.enums.OperatorType;
|
|||||||
public @interface Log
|
public @interface Log
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 模块
|
* 模块
|
||||||
*/
|
*/
|
||||||
public String title() default "";
|
public String title() default "";
|
||||||
|
|
||||||
@@ -43,4 +43,9 @@ public @interface Log
|
|||||||
* 是否保存响应的参数
|
* 是否保存响应的参数
|
||||||
*/
|
*/
|
||||||
public boolean isSaveResponseData() default true;
|
public boolean isSaveResponseData() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排除指定的请求参数
|
||||||
|
*/
|
||||||
|
public String[] excludeParamNames() default {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ public class UserConstants
|
|||||||
/** InnerLink组件标识 */
|
/** InnerLink组件标识 */
|
||||||
public final static String INNER_LINK = "InnerLink";
|
public final static String INNER_LINK = "InnerLink";
|
||||||
|
|
||||||
/** 校验返回结果码 */
|
/** 校验是否唯一的返回标识 */
|
||||||
public final static String UNIQUE = "0";
|
public final static boolean UNIQUE = true;
|
||||||
public final static String NOT_UNIQUE = "1";
|
public final static boolean NOT_UNIQUE = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户名长度限制
|
* 用户名长度限制
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.ruoyi.common.core.domain;
|
package com.ruoyi.common.core.domain;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Objects;
|
||||||
import com.ruoyi.common.constant.HttpStatus;
|
import com.ruoyi.common.constant.HttpStatus;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
|
||||||
@@ -169,6 +170,36 @@ public class AjaxResult extends HashMap<String, Object>
|
|||||||
return new AjaxResult(code, msg, null);
|
return new AjaxResult(code, msg, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为成功消息
|
||||||
|
*
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public boolean isSuccess()
|
||||||
|
{
|
||||||
|
return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为警告消息
|
||||||
|
*
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public boolean isWarn()
|
||||||
|
{
|
||||||
|
return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为错误消息
|
||||||
|
*
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public boolean isError()
|
||||||
|
{
|
||||||
|
return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 方便链式调用
|
* 方便链式调用
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.ruoyi.common.core.domain.model;
|
package com.ruoyi.common.core.domain.model;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import com.alibaba.fastjson2.annotation.JSONField;
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录用户身份权限
|
* 登录用户身份权限
|
||||||
@@ -71,6 +71,24 @@ public class LoginUser implements UserDetails
|
|||||||
*/
|
*/
|
||||||
private SysUser user;
|
private SysUser user;
|
||||||
|
|
||||||
|
public LoginUser()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser(SysUser user, Set<String> permissions)
|
||||||
|
{
|
||||||
|
this.user = user;
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
|
||||||
|
{
|
||||||
|
this.userId = userId;
|
||||||
|
this.deptId = deptId;
|
||||||
|
this.user = user;
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
|
||||||
public Long getUserId()
|
public Long getUserId()
|
||||||
{
|
{
|
||||||
return userId;
|
return userId;
|
||||||
@@ -101,24 +119,6 @@ public class LoginUser implements UserDetails
|
|||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoginUser()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoginUser(SysUser user, Set<String> permissions)
|
|
||||||
{
|
|
||||||
this.user = user;
|
|
||||||
this.permissions = permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
|
|
||||||
{
|
|
||||||
this.userId = userId;
|
|
||||||
this.deptId = deptId;
|
|
||||||
this.user = user;
|
|
||||||
this.permissions = permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JSONField(serialize = false)
|
@JSONField(serialize = false)
|
||||||
@Override
|
@Override
|
||||||
public String getPassword()
|
public String getPassword()
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.ruoyi.common.exception.file;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传异常类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class FileUploadException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Throwable cause;
|
||||||
|
|
||||||
|
public FileUploadException()
|
||||||
|
{
|
||||||
|
this(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileUploadException(final String msg)
|
||||||
|
{
|
||||||
|
this(msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileUploadException(String msg, Throwable cause)
|
||||||
|
{
|
||||||
|
super(msg);
|
||||||
|
this.cause = cause;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printStackTrace(PrintStream stream)
|
||||||
|
{
|
||||||
|
super.printStackTrace(stream);
|
||||||
|
if (cause != null)
|
||||||
|
{
|
||||||
|
stream.println("Caused by:");
|
||||||
|
cause.printStackTrace(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printStackTrace(PrintWriter writer)
|
||||||
|
{
|
||||||
|
super.printStackTrace(writer);
|
||||||
|
if (cause != null)
|
||||||
|
{
|
||||||
|
writer.println("Caused by:");
|
||||||
|
cause.printStackTrace(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Throwable getCause()
|
||||||
|
{
|
||||||
|
return cause;
|
||||||
|
}
|
||||||
|
}
|
||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
package com.ruoyi.common.exception.file;
|
package com.ruoyi.common.exception.file;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import org.apache.commons.fileupload.FileUploadException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件上传 误异常类
|
* 文件上传 误异常类
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.ruoyi.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 黑名单IP异常类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class BlackListException extends UserException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BlackListException()
|
||||||
|
{
|
||||||
|
super("login.blocked", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package com.ruoyi.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户不存在异常类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class UserNotExistsException extends UserException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UserNotExistsException()
|
||||||
|
{
|
||||||
|
super("user.not.exists", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -145,16 +145,20 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算两个时间差
|
* 计算时间差
|
||||||
|
*
|
||||||
|
* @param endTime 最后时间
|
||||||
|
* @param startTime 开始时间
|
||||||
|
* @return 时间差(天/小时/分钟)
|
||||||
*/
|
*/
|
||||||
public static String getDatePoor(Date endDate, Date nowDate)
|
public static String timeDistance(Date endDate, Date startTime)
|
||||||
{
|
{
|
||||||
long nd = 1000 * 24 * 60 * 60;
|
long nd = 1000 * 24 * 60 * 60;
|
||||||
long nh = 1000 * 60 * 60;
|
long nh = 1000 * 60 * 60;
|
||||||
long nm = 1000 * 60;
|
long nm = 1000 * 60;
|
||||||
// long ns = 1000;
|
// long ns = 1000;
|
||||||
// 获得两个时间的毫秒时间差异
|
// 获得两个时间的毫秒时间差异
|
||||||
long diff = endDate.getTime() - nowDate.getTime();
|
long diff = endDate.getTime() - startTime.getTime();
|
||||||
// 计算差多少天
|
// 计算差多少天
|
||||||
long day = diff / nd;
|
long day = diff / nd;
|
||||||
// 计算差多少小时
|
// 计算差多少小时
|
||||||
|
|||||||
@@ -325,9 +325,9 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
|
* 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
|
||||||
*
|
*
|
||||||
* @param set 给定的集合
|
* @param collection 给定的集合
|
||||||
* @param array 给定的数组
|
* @param array 给定的数组
|
||||||
* @return boolean 结果
|
* @return boolean 结果
|
||||||
*/
|
*/
|
||||||
@@ -481,7 +481,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 驼峰式命名法 例如:user_name->userName
|
* 驼峰式命名法
|
||||||
|
* 例如:user_name->userName
|
||||||
*/
|
*/
|
||||||
public static String toCamelCase(String s)
|
public static String toCamelCase(String s)
|
||||||
{
|
{
|
||||||
@@ -489,6 +490,10 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (s.indexOf(SEPARATOR) == -1)
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
s = s.toLowerCase();
|
s = s.toLowerCase();
|
||||||
StringBuilder sb = new StringBuilder(s.length());
|
StringBuilder sb = new StringBuilder(s.length());
|
||||||
boolean upperCase = false;
|
boolean upperCase = false;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.ruoyi.common.utils.ip;
|
|||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,6 +13,23 @@ import com.ruoyi.common.utils.StringUtils;
|
|||||||
*/
|
*/
|
||||||
public class IpUtils
|
public class IpUtils
|
||||||
{
|
{
|
||||||
|
public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";
|
||||||
|
// 匹配 ip
|
||||||
|
public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")";
|
||||||
|
public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))";
|
||||||
|
// 匹配网段
|
||||||
|
public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端IP
|
||||||
|
*
|
||||||
|
* @return IP地址
|
||||||
|
*/
|
||||||
|
public static String getIpAddr()
|
||||||
|
{
|
||||||
|
return getIpAddr(ServletUtils.getRequest());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取客户端IP
|
* 获取客户端IP
|
||||||
*
|
*
|
||||||
@@ -248,7 +266,7 @@ public class IpUtils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ip;
|
return StringUtils.substring(ip, 0, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -261,4 +279,104 @@ public class IpUtils
|
|||||||
{
|
{
|
||||||
return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
|
return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为IP
|
||||||
|
*/
|
||||||
|
public static boolean isIP(String ip)
|
||||||
|
{
|
||||||
|
return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为IP,或 *为间隔的通配符地址
|
||||||
|
*/
|
||||||
|
public static boolean isIpWildCard(String ip)
|
||||||
|
{
|
||||||
|
return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测参数是否在ip通配符里
|
||||||
|
*/
|
||||||
|
public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip)
|
||||||
|
{
|
||||||
|
String[] s1 = ipWildCard.split("\\.");
|
||||||
|
String[] s2 = ip.split("\\.");
|
||||||
|
boolean isMatchedSeg = true;
|
||||||
|
for (int i = 0; i < s1.length && !s1[i].equals("*"); i++)
|
||||||
|
{
|
||||||
|
if (!s1[i].equals(s2[i]))
|
||||||
|
{
|
||||||
|
isMatchedSeg = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isMatchedSeg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为特定格式如:“10.10.10.1-10.10.10.99”的ip段字符串
|
||||||
|
*/
|
||||||
|
public static boolean isIPSegment(String ipSeg)
|
||||||
|
{
|
||||||
|
return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断ip是否在指定网段中
|
||||||
|
*/
|
||||||
|
public static boolean ipIsInNetNoCheck(String iparea, String ip)
|
||||||
|
{
|
||||||
|
int idx = iparea.indexOf('-');
|
||||||
|
String[] sips = iparea.substring(0, idx).split("\\.");
|
||||||
|
String[] sipe = iparea.substring(idx + 1).split("\\.");
|
||||||
|
String[] sipt = ip.split("\\.");
|
||||||
|
long ips = 0L, ipe = 0L, ipt = 0L;
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
ips = ips << 8 | Integer.parseInt(sips[i]);
|
||||||
|
ipe = ipe << 8 | Integer.parseInt(sipe[i]);
|
||||||
|
ipt = ipt << 8 | Integer.parseInt(sipt[i]);
|
||||||
|
}
|
||||||
|
if (ips > ipe)
|
||||||
|
{
|
||||||
|
long t = ips;
|
||||||
|
ips = ipe;
|
||||||
|
ipe = t;
|
||||||
|
}
|
||||||
|
return ips <= ipt && ipt <= ipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验ip是否符合过滤串规则
|
||||||
|
*
|
||||||
|
* @param filter 过滤IP列表,支持后缀'*'通配,支持网段如:`10.10.10.1-10.10.10.99`
|
||||||
|
* @param ip 校验IP地址
|
||||||
|
* @return boolean 结果
|
||||||
|
*/
|
||||||
|
public static boolean isMatchedIp(String filter, String ip)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String[] ips = filter.split(";");
|
||||||
|
for (String iStr : ips)
|
||||||
|
{
|
||||||
|
if (isIP(iStr) && iStr.equals(ip))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -98,6 +98,11 @@ public class ExcelUtil<T>
|
|||||||
|
|
||||||
public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
|
public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于dictType属性数据存储,避免重复查缓存
|
||||||
|
*/
|
||||||
|
public Map<String, String> sysDictMap = new HashMap<String, String>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excel sheet最大行数,默认65536
|
* Excel sheet最大行数,默认65536
|
||||||
*/
|
*/
|
||||||
@@ -1034,7 +1039,12 @@ public class ExcelUtil<T>
|
|||||||
}
|
}
|
||||||
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
|
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
|
||||||
{
|
{
|
||||||
cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator));
|
if (!sysDictMap.containsKey(dictType + value))
|
||||||
|
{
|
||||||
|
String lable = convertDictByExp(Convert.toStr(value), dictType, separator);
|
||||||
|
sysDictMap.put(dictType + value, lable);
|
||||||
|
}
|
||||||
|
cell.setCellValue(sysDictMap.get(dictType + value));
|
||||||
}
|
}
|
||||||
else if (value instanceof BigDecimal && -1 != attr.scale())
|
else if (value instanceof BigDecimal && -1 != attr.scale())
|
||||||
{
|
{
|
||||||
@@ -1321,7 +1331,7 @@ public class ExcelUtil<T>
|
|||||||
*/
|
*/
|
||||||
public String encodingFilename(String filename)
|
public String encodingFilename(String filename)
|
||||||
{
|
{
|
||||||
filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx";
|
filename = UUID.randomUUID() + "_" + filename + ".xlsx";
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1440,7 +1450,8 @@ public class ExcelUtil<T>
|
|||||||
Excel[] excels = attrs.value();
|
Excel[] excels = attrs.value();
|
||||||
for (Excel attr : excels)
|
for (Excel attr : excels)
|
||||||
{
|
{
|
||||||
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
|
if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
|
||||||
|
&& (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
|
||||||
{
|
{
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
fields.add(new Object[] { field, attr });
|
fields.add(new Object[] { field, attr });
|
||||||
@@ -1598,7 +1609,7 @@ public class ExcelUtil<T>
|
|||||||
HSSFPicture pic = (HSSFPicture) shape;
|
HSSFPicture pic = (HSSFPicture) shape;
|
||||||
int pictureIndex = pic.getPictureIndex() - 1;
|
int pictureIndex = pic.getPictureIndex() - 1;
|
||||||
HSSFPictureData picData = pictures.get(pictureIndex);
|
HSSFPictureData picData = pictures.get(pictureIndex);
|
||||||
String picIndex = String.valueOf(anchor.getRow1()) + "_" + String.valueOf(anchor.getCol1());
|
String picIndex = anchor.getRow1() + "_" + anchor.getCol1();
|
||||||
sheetIndexPicMap.put(picIndex, picData);
|
sheetIndexPicMap.put(picIndex, picData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class Seq
|
|||||||
private static AtomicInteger uploadSeq = new AtomicInteger(1);
|
private static AtomicInteger uploadSeq = new AtomicInteger(1);
|
||||||
|
|
||||||
// 机器标识
|
// 机器标识
|
||||||
private static String machineCode = "A";
|
private static final String machineCode = "A";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取通用序列号
|
* 获取通用序列号
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。
|
* 获取类型 4(伪随机生成的)UUID 的静态工厂。
|
||||||
*
|
*
|
||||||
* @return 随机生成的 {@code UUID}
|
* @return 随机生成的 {@code UUID}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.5</version>
|
<version>3.8.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<artifactId>kaptcha</artifactId>
|
<artifactId>kaptcha</artifactId>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<artifactId>javax.servlet-api</artifactId>
|
<artifactId>servlet-api</artifactId>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ public class DataScopeAspect
|
|||||||
if (DATA_SCOPE_ALL.equals(dataScope))
|
if (DATA_SCOPE_ALL.equals(dataScope))
|
||||||
{
|
{
|
||||||
sqlString = new StringBuilder();
|
sqlString = new StringBuilder();
|
||||||
|
conditions.add(dataScope);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
|
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
|
||||||
@@ -141,6 +142,12 @@ public class DataScopeAspect
|
|||||||
conditions.add(dataScope);
|
conditions.add(dataScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 多角色情况下,所有角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
|
||||||
|
if (StringUtils.isEmpty(conditions))
|
||||||
|
{
|
||||||
|
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(sqlString.toString()))
|
if (StringUtils.isNotBlank(sqlString.toString()))
|
||||||
{
|
{
|
||||||
Object params = joinPoint.getArgs()[0];
|
Object params = joinPoint.getArgs()[0];
|
||||||
|
|||||||
@@ -4,12 +4,15 @@ import java.util.Collection;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.annotation.AfterReturning;
|
import org.aspectj.lang.annotation.AfterReturning;
|
||||||
import org.aspectj.lang.annotation.AfterThrowing;
|
import org.aspectj.lang.annotation.AfterThrowing;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Before;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.core.NamedThreadLocal;
|
||||||
import org.springframework.stereotype.Component;
|
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;
|
||||||
@@ -41,6 +44,18 @@ public class LogAspect
|
|||||||
/** 排除敏感属性字段 */
|
/** 排除敏感属性字段 */
|
||||||
public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
|
public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
|
||||||
|
|
||||||
|
/** 计算操作消耗时间 */
|
||||||
|
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理请求前执行
|
||||||
|
*/
|
||||||
|
@Before(value = "@annotation(controllerLog)")
|
||||||
|
public void boBefore(JoinPoint joinPoint, Log controllerLog)
|
||||||
|
{
|
||||||
|
TIME_THREADLOCAL.set(System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理完请求后执行
|
* 处理完请求后执行
|
||||||
*
|
*
|
||||||
@@ -75,7 +90,7 @@ public class LogAspect
|
|||||||
SysOperLog operLog = new SysOperLog();
|
SysOperLog operLog = new SysOperLog();
|
||||||
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
||||||
// 请求的地址
|
// 请求的地址
|
||||||
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
String ip = IpUtils.getIpAddr();
|
||||||
operLog.setOperIp(ip);
|
operLog.setOperIp(ip);
|
||||||
operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
|
operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
|
||||||
if (loginUser != null)
|
if (loginUser != null)
|
||||||
@@ -96,6 +111,8 @@ public class LogAspect
|
|||||||
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
|
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
|
||||||
// 处理设置注解上的参数
|
// 处理设置注解上的参数
|
||||||
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
|
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
|
||||||
|
// 设置消耗时间
|
||||||
|
operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());
|
||||||
// 保存数据库
|
// 保存数据库
|
||||||
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
|
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
|
||||||
}
|
}
|
||||||
@@ -105,6 +122,10 @@ public class LogAspect
|
|||||||
log.error("异常信息:{}", exp.getMessage());
|
log.error("异常信息:{}", exp.getMessage());
|
||||||
exp.printStackTrace();
|
exp.printStackTrace();
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
TIME_THREADLOCAL.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,7 +147,7 @@ public class LogAspect
|
|||||||
if (log.isSaveRequestData())
|
if (log.isSaveRequestData())
|
||||||
{
|
{
|
||||||
// 获取参数的信息,传入到数据库中。
|
// 获取参数的信息,传入到数据库中。
|
||||||
setRequestValue(joinPoint, operLog);
|
setRequestValue(joinPoint, operLog, log.excludeParamNames());
|
||||||
}
|
}
|
||||||
// 是否需要保存response,参数和值
|
// 是否需要保存response,参数和值
|
||||||
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
|
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
|
||||||
@@ -141,25 +162,26 @@ public class LogAspect
|
|||||||
* @param operLog 操作日志
|
* @param operLog 操作日志
|
||||||
* @throws Exception 异常
|
* @throws Exception 异常
|
||||||
*/
|
*/
|
||||||
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception
|
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
|
||||||
{
|
{
|
||||||
|
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
||||||
String requestMethod = operLog.getRequestMethod();
|
String requestMethod = operLog.getRequestMethod();
|
||||||
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))
|
if (StringUtils.isEmpty(paramsMap)
|
||||||
|
&& (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)))
|
||||||
{
|
{
|
||||||
String params = argsArrayToString(joinPoint.getArgs());
|
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
|
||||||
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));
|
||||||
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter()), 0, 2000));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 参数拼装
|
* 参数拼装
|
||||||
*/
|
*/
|
||||||
private String argsArrayToString(Object[] paramsArray)
|
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
|
||||||
{
|
{
|
||||||
String params = "";
|
String params = "";
|
||||||
if (paramsArray != null && paramsArray.length > 0)
|
if (paramsArray != null && paramsArray.length > 0)
|
||||||
@@ -170,7 +192,7 @@ public class LogAspect
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter());
|
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
|
||||||
params += jsonObj.toString() + " ";
|
params += jsonObj.toString() + " ";
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -185,9 +207,9 @@ public class LogAspect
|
|||||||
/**
|
/**
|
||||||
* 忽略敏感属性
|
* 忽略敏感属性
|
||||||
*/
|
*/
|
||||||
public PropertyPreExcludeFilter excludePropertyPreFilter()
|
public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames)
|
||||||
{
|
{
|
||||||
return new PropertyPreExcludeFilter().addExcludes(EXCLUDE_PROPERTIES);
|
return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import org.springframework.stereotype.Component;
|
|||||||
import com.ruoyi.common.annotation.RateLimiter;
|
import com.ruoyi.common.annotation.RateLimiter;
|
||||||
import com.ruoyi.common.enums.LimitType;
|
import com.ruoyi.common.enums.LimitType;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.ip.IpUtils;
|
import com.ruoyi.common.utils.ip.IpUtils;
|
||||||
|
|
||||||
@@ -79,7 +78,7 @@ public class RateLimiterAspect
|
|||||||
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
|
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
|
||||||
if (rateLimiter.limitType() == LimitType.IP)
|
if (rateLimiter.limitType() == LimitType.IP)
|
||||||
{
|
{
|
||||||
stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-");
|
stringBuffer.append(IpUtils.getIpAddr()).append("-");
|
||||||
}
|
}
|
||||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||||
Method method = signature.getMethod();
|
Method method = signature.getMethod();
|
||||||
|
|||||||
+12
@@ -24,6 +24,12 @@ public class DruidProperties
|
|||||||
@Value("${spring.datasource.druid.maxWait}")
|
@Value("${spring.datasource.druid.maxWait}")
|
||||||
private int maxWait;
|
private int maxWait;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.connectTimeout}")
|
||||||
|
private int connectTimeout;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.socketTimeout}")
|
||||||
|
private int socketTimeout;
|
||||||
|
|
||||||
@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
|
@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
|
||||||
private int timeBetweenEvictionRunsMillis;
|
private int timeBetweenEvictionRunsMillis;
|
||||||
|
|
||||||
@@ -54,6 +60,12 @@ public class DruidProperties
|
|||||||
|
|
||||||
/** 配置获取连接等待超时的时间 */
|
/** 配置获取连接等待超时的时间 */
|
||||||
datasource.setMaxWait(maxWait);
|
datasource.setMaxWait(maxWait);
|
||||||
|
|
||||||
|
/** 配置驱动连接超时时间,检测数据库建立连接的超时时间,单位是毫秒 */
|
||||||
|
datasource.setConnectTimeout(connectTimeout);
|
||||||
|
|
||||||
|
/** 配置网络超时时间,等待数据库操作完成的网络超时时间,单位是毫秒 */
|
||||||
|
datasource.setSocketTimeout(socketTimeout);
|
||||||
|
|
||||||
/** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */
|
/** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */
|
||||||
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
|
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
|
||||||
|
|||||||
+3
-2
@@ -3,6 +3,7 @@ package com.ruoyi.framework.config.properties;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import org.apache.commons.lang3.RegExUtils;
|
import org.apache.commons.lang3.RegExUtils;
|
||||||
@@ -44,12 +45,12 @@ public class PermitAllUrlProperties implements InitializingBean, ApplicationCont
|
|||||||
|
|
||||||
// 获取方法上边的注解 替代path variable 为 *
|
// 获取方法上边的注解 替代path variable 为 *
|
||||||
Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
|
Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
|
||||||
Optional.ofNullable(method).ifPresent(anonymous -> info.getPatternsCondition().getPatterns()
|
Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
|
||||||
.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
|
.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
|
||||||
|
|
||||||
// 获取类上边的注解, 替代path variable 为 *
|
// 获取类上边的注解, 替代path variable 为 *
|
||||||
Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
|
Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
|
||||||
Optional.ofNullable(controller).ifPresent(anonymous -> info.getPatternsCondition().getPatterns()
|
Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
|
||||||
.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
|
.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ public class DynamicDataSourceContextHolder
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
|
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
|
||||||
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
|
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class AsyncFactory
|
|||||||
final Object... args)
|
final Object... args)
|
||||||
{
|
{
|
||||||
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||||
final String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
final String ip = IpUtils.getIpAddr();
|
||||||
return new TimerTask()
|
return new TimerTask()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public class Jvm
|
|||||||
*/
|
*/
|
||||||
public String getRunTime()
|
public String getRunTime()
|
||||||
{
|
{
|
||||||
return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate());
|
return DateUtils.timeDistance(DateUtils.getNowDate(), DateUtils.getServerStartDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-1
@@ -62,7 +62,7 @@ public class PermissionService
|
|||||||
/**
|
/**
|
||||||
* 验证用户是否具有以下任意一个权限
|
* 验证用户是否具有以下任意一个权限
|
||||||
*
|
*
|
||||||
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
|
* @param permissions 以 PERMISSION_DELIMETER 为分隔符的权限列表
|
||||||
* @return 用户是否具有以下任意一个权限
|
* @return 用户是否具有以下任意一个权限
|
||||||
*/
|
*/
|
||||||
public boolean hasAnyPermi(String permissions)
|
public boolean hasAnyPermi(String permissions)
|
||||||
|
|||||||
+57
-17
@@ -9,16 +9,18 @@ import org.springframework.security.core.Authentication;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import com.ruoyi.common.constant.CacheConstants;
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.core.redis.RedisCache;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.exception.user.BlackListException;
|
||||||
import com.ruoyi.common.exception.user.CaptchaException;
|
import com.ruoyi.common.exception.user.CaptchaException;
|
||||||
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
||||||
|
import com.ruoyi.common.exception.user.UserNotExistsException;
|
||||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.MessageUtils;
|
import com.ruoyi.common.utils.MessageUtils;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.ip.IpUtils;
|
import com.ruoyi.common.utils.ip.IpUtils;
|
||||||
import com.ruoyi.framework.manager.AsyncManager;
|
import com.ruoyi.framework.manager.AsyncManager;
|
||||||
@@ -61,12 +63,10 @@ public class SysLoginService
|
|||||||
*/
|
*/
|
||||||
public String login(String username, String password, String code, String uuid)
|
public String login(String username, String password, String code, String uuid)
|
||||||
{
|
{
|
||||||
boolean captchaEnabled = configService.selectCaptchaEnabled();
|
// 验证码校验
|
||||||
// 验证码开关
|
validateCaptcha(username, code, uuid);
|
||||||
if (captchaEnabled)
|
// 登录前置校验
|
||||||
{
|
loginPreCheck(username, password);
|
||||||
validateCaptcha(username, code, uuid);
|
|
||||||
}
|
|
||||||
// 用户验证
|
// 用户验证
|
||||||
Authentication authentication = null;
|
Authentication authentication = null;
|
||||||
try
|
try
|
||||||
@@ -110,18 +110,58 @@ public class SysLoginService
|
|||||||
*/
|
*/
|
||||||
public void validateCaptcha(String username, String code, String uuid)
|
public void validateCaptcha(String username, String code, String uuid)
|
||||||
{
|
{
|
||||||
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
|
boolean captchaEnabled = configService.selectCaptchaEnabled();
|
||||||
String captcha = redisCache.getCacheObject(verifyKey);
|
if (captchaEnabled)
|
||||||
redisCache.deleteObject(verifyKey);
|
|
||||||
if (captcha == null)
|
|
||||||
{
|
{
|
||||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
|
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
|
||||||
throw new CaptchaExpireException();
|
String captcha = redisCache.getCacheObject(verifyKey);
|
||||||
|
redisCache.deleteObject(verifyKey);
|
||||||
|
if (captcha == null)
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
|
||||||
|
throw new CaptchaExpireException();
|
||||||
|
}
|
||||||
|
if (!code.equalsIgnoreCase(captcha))
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
|
||||||
|
throw new CaptchaException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!code.equalsIgnoreCase(captcha))
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录前置校验
|
||||||
|
* @param username 用户名
|
||||||
|
* @param password 用户密码
|
||||||
|
*/
|
||||||
|
public void loginPreCheck(String username, String password)
|
||||||
|
{
|
||||||
|
// 用户名或密码为空 错误
|
||||||
|
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
|
||||||
{
|
{
|
||||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
|
||||||
throw new CaptchaException();
|
throw new UserNotExistsException();
|
||||||
|
}
|
||||||
|
// 密码如果不在指定范围内 错误
|
||||||
|
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
||||||
|
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||||
|
throw new UserPasswordNotMatchException();
|
||||||
|
}
|
||||||
|
// 用户名不在指定范围内 错误
|
||||||
|
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|
||||||
|
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||||
|
throw new UserPasswordNotMatchException();
|
||||||
|
}
|
||||||
|
// IP黑名单校验
|
||||||
|
String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
|
||||||
|
if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
|
||||||
|
throw new BlackListException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +174,7 @@ public class SysLoginService
|
|||||||
{
|
{
|
||||||
SysUser sysUser = new SysUser();
|
SysUser sysUser = new SysUser();
|
||||||
sysUser.setUserId(userId);
|
sysUser.setUserId(userId);
|
||||||
sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
|
sysUser.setLoginIp(IpUtils.getIpAddr());
|
||||||
sysUser.setLoginDate(DateUtils.getNowDate());
|
sysUser.setLoginDate(DateUtils.getNowDate());
|
||||||
userService.updateUserProfile(sysUser);
|
userService.updateUserProfile(sysUser);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -5,6 +5,7 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.system.service.ISysMenuService;
|
import com.ruoyi.system.service.ISysMenuService;
|
||||||
@@ -62,7 +63,7 @@ public class SysPermissionService
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<SysRole> roles = user.getRoles();
|
List<SysRole> roles = user.getRoles();
|
||||||
if (!roles.isEmpty() && roles.size() > 1)
|
if (!CollectionUtils.isEmpty(roles))
|
||||||
{
|
{
|
||||||
// 多角色设置permissions属性,以便数据权限匹配权限
|
// 多角色设置permissions属性,以便数据权限匹配权限
|
||||||
for (SysRole role : roles)
|
for (SysRole role : roles)
|
||||||
|
|||||||
+1
-1
@@ -69,7 +69,7 @@ public class SysRegisterService
|
|||||||
{
|
{
|
||||||
msg = "密码长度必须在5到20个字符之间";
|
msg = "密码长度必须在5到20个字符之间";
|
||||||
}
|
}
|
||||||
else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser)))
|
else if (!userService.checkUserNameUnique(sysUser))
|
||||||
{
|
{
|
||||||
msg = "保存用户'" + username + "'失败,注册账号已存在";
|
msg = "保存用户'" + username + "'失败,注册账号已存在";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ public class TokenService
|
|||||||
public void setUserAgent(LoginUser loginUser)
|
public void setUserAgent(LoginUser loginUser)
|
||||||
{
|
{
|
||||||
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||||
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
String ip = IpUtils.getIpAddr();
|
||||||
loginUser.setIpaddr(ip);
|
loginUser.setIpaddr(ip);
|
||||||
loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
|
loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
|
||||||
loginUser.setBrowser(userAgent.getBrowser().getName());
|
loginUser.setBrowser(userAgent.getBrowser().getName());
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.5</version>
|
<version>3.8.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# 代码生成
|
# 代码生成
|
||||||
gen:
|
gen:
|
||||||
# 作者
|
# 作者
|
||||||
author: ruoyi
|
author: ruoyi
|
||||||
# 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
|
# 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.ruoyi.generator.mapper.GenTableColumnMapper">
|
<mapper namespace="com.ruoyi.generator.mapper.GenTableColumnMapper">
|
||||||
|
|
||||||
<resultMap type="GenTableColumn" id="GenTableColumnResult">
|
<resultMap type="GenTableColumn" id="GenTableColumnResult">
|
||||||
<id property="columnId" column="column_id" />
|
<id property="columnId" column="column_id" />
|
||||||
<result property="tableId" column="table_id" />
|
<result property="tableId" column="table_id" />
|
||||||
@@ -28,23 +28,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<result property="updateBy" column="update_by" />
|
<result property="updateBy" column="update_by" />
|
||||||
<result property="updateTime" column="update_time" />
|
<result property="updateTime" column="update_time" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectGenTableColumnVo">
|
<sql id="selectGenTableColumnVo">
|
||||||
select column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time from gen_table_column
|
select column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time from gen_table_column
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="selectGenTableColumnListByTableId" parameterType="Long" resultMap="GenTableColumnResult">
|
<select id="selectGenTableColumnListByTableId" parameterType="Long" resultMap="GenTableColumnResult">
|
||||||
<include refid="selectGenTableColumnVo"/>
|
<include refid="selectGenTableColumnVo"/>
|
||||||
where table_id = #{tableId}
|
where table_id = #{tableId}
|
||||||
order by sort
|
order by sort
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
|
<select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
|
||||||
select column_name, (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else null end) as is_required, (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
|
select column_name, (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else null end) as is_required, (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
|
||||||
from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
|
from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
|
||||||
order by ordinal_position
|
order by ordinal_position
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<insert id="insertGenTableColumn" parameterType="GenTableColumn" useGeneratedKeys="true" keyProperty="columnId">
|
<insert id="insertGenTableColumn" parameterType="GenTableColumn" useGeneratedKeys="true" keyProperty="columnId">
|
||||||
insert into gen_table_column (
|
insert into gen_table_column (
|
||||||
<if test="tableId != null and tableId != ''">table_id,</if>
|
<if test="tableId != null and tableId != ''">table_id,</if>
|
||||||
@@ -88,7 +88,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
sysdate()
|
sysdate()
|
||||||
)
|
)
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<update id="updateGenTableColumn" parameterType="GenTableColumn">
|
<update id="updateGenTableColumn" parameterType="GenTableColumn">
|
||||||
update gen_table_column
|
update gen_table_column
|
||||||
<set>
|
<set>
|
||||||
@@ -111,14 +111,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
</update>
|
</update>
|
||||||
|
|
||||||
<delete id="deleteGenTableColumnByIds" parameterType="Long">
|
<delete id="deleteGenTableColumnByIds" parameterType="Long">
|
||||||
delete from gen_table_column where table_id in
|
delete from gen_table_column where table_id in
|
||||||
<foreach collection="array" item="tableId" open="(" separator="," close=")">
|
<foreach collection="array" item="tableId" open="(" separator="," close=")">
|
||||||
#{tableId}
|
#{tableId}
|
||||||
</foreach>
|
</foreach>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
<delete id="deleteGenTableColumns">
|
<delete id="deleteGenTableColumns">
|
||||||
delete from gen_table_column where column_id in
|
delete from gen_table_column where column_id in
|
||||||
<foreach collection="list" item="item" open="(" separator="," close=")">
|
<foreach collection="list" item="item" open="(" separator="," close=")">
|
||||||
#{item.columnId}
|
#{item.columnId}
|
||||||
</foreach>
|
</foreach>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.5</version>
|
<version>3.8.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class JobInvokeUtil
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Object bean = Class.forName(beanName).newInstance();
|
Object bean = Class.forName(beanName).getDeclaredConstructor().newInstance();
|
||||||
invokeMethod(bean, methodName, methodParams);
|
invokeMethod(bean, methodName, methodParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,6 +134,8 @@ public class ScheduleUtils
|
|||||||
return StringUtils.containsAnyIgnoreCase(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]);
|
||||||
return StringUtils.containsAnyIgnoreCase(obj.getClass().getPackage().getName(), Constants.JOB_WHITELIST_STR);
|
String beanPackageName = obj.getClass().getPackage().getName();
|
||||||
|
return StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_WHITELIST_STR)
|
||||||
|
&& !StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_ERROR_STR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.8.5</version>
|
<version>3.8.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ public class SysOperLog extends BaseEntity
|
|||||||
@Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
@Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date operTime;
|
private Date operTime;
|
||||||
|
|
||||||
|
/** 消耗时间 */
|
||||||
|
@Excel(name = "消耗时间", suffix = "毫秒")
|
||||||
|
private Long costTime;
|
||||||
|
|
||||||
public Long getOperId()
|
public Long getOperId()
|
||||||
{
|
{
|
||||||
return operId;
|
return operId;
|
||||||
@@ -252,4 +256,14 @@ public class SysOperLog extends BaseEntity
|
|||||||
{
|
{
|
||||||
this.operTime = operTime;
|
this.operTime = operTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getCostTime()
|
||||||
|
{
|
||||||
|
return costTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCostTime(Long costTime)
|
||||||
|
{
|
||||||
|
this.costTime = costTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,5 +85,5 @@ public interface ISysConfigService
|
|||||||
* @param config 参数信息
|
* @param config 参数信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkConfigKeyUnique(SysConfig config);
|
public boolean checkConfigKeyUnique(SysConfig config);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public interface ISysDeptService
|
|||||||
* @param dept 部门信息
|
* @param dept 部门信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkDeptNameUnique(SysDept dept);
|
public boolean checkDeptNameUnique(SysDept dept);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验部门是否有数据权限
|
* 校验部门是否有数据权限
|
||||||
|
|||||||
@@ -94,5 +94,5 @@ public interface ISysDictTypeService
|
|||||||
* @param dictType 字典类型
|
* @param dictType 字典类型
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkDictTypeUnique(SysDictType dictType);
|
public boolean checkDictTypeUnique(SysDictType dictType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,5 +140,5 @@ public interface ISysMenuService
|
|||||||
* @param menu 菜单信息
|
* @param menu 菜单信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkMenuNameUnique(SysMenu menu);
|
public boolean checkMenuNameUnique(SysMenu menu);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public interface ISysPostService
|
|||||||
* @param post 岗位信息
|
* @param post 岗位信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkPostNameUnique(SysPost post);
|
public boolean checkPostNameUnique(SysPost post);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验岗位编码
|
* 校验岗位编码
|
||||||
@@ -55,7 +55,7 @@ public interface ISysPostService
|
|||||||
* @param post 岗位信息
|
* @param post 岗位信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkPostCodeUnique(SysPost post);
|
public boolean checkPostCodeUnique(SysPost post);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过岗位ID查询岗位使用数量
|
* 通过岗位ID查询岗位使用数量
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public interface ISysRoleService
|
|||||||
* @param role 角色信息
|
* @param role 角色信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkRoleNameUnique(SysRole role);
|
public boolean checkRoleNameUnique(SysRole role);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验角色权限是否唯一
|
* 校验角色权限是否唯一
|
||||||
@@ -73,7 +73,7 @@ public interface ISysRoleService
|
|||||||
* @param role 角色信息
|
* @param role 角色信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkRoleKeyUnique(SysRole role);
|
public boolean checkRoleKeyUnique(SysRole role);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验角色是否允许操作
|
* 校验角色是否允许操作
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public interface ISysUserService
|
|||||||
* @param user 用户信息
|
* @param user 用户信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkUserNameUnique(SysUser user);
|
public boolean checkUserNameUnique(SysUser user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验手机号码是否唯一
|
* 校验手机号码是否唯一
|
||||||
@@ -80,7 +80,7 @@ public interface ISysUserService
|
|||||||
* @param user 用户信息
|
* @param user 用户信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkPhoneUnique(SysUser user);
|
public boolean checkPhoneUnique(SysUser user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验email是否唯一
|
* 校验email是否唯一
|
||||||
@@ -88,7 +88,7 @@ public interface ISysUserService
|
|||||||
* @param user 用户信息
|
* @param user 用户信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String checkEmailUnique(SysUser user);
|
public boolean checkEmailUnique(SysUser user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验用户是否允许操作
|
* 校验用户是否允许操作
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ public class SysConfigServiceImpl implements ISysConfigService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkConfigKeyUnique(SysConfig config)
|
public boolean checkConfigKeyUnique(SysConfig config)
|
||||||
{
|
{
|
||||||
Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId();
|
Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId();
|
||||||
SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey());
|
SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey());
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ public class SysDeptServiceImpl implements ISysDeptService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkDeptNameUnique(SysDept dept)
|
public boolean checkDeptNameUnique(SysDept dept)
|
||||||
{
|
{
|
||||||
Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId();
|
Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId();
|
||||||
SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId());
|
SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId());
|
||||||
|
|||||||
+1
-1
@@ -210,7 +210,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkDictTypeUnique(SysDictType dict)
|
public boolean checkDictTypeUnique(SysDictType dict)
|
||||||
{
|
{
|
||||||
Long dictId = StringUtils.isNull(dict.getDictId()) ? -1L : dict.getDictId();
|
Long dictId = StringUtils.isNull(dict.getDictId()) ? -1L : dict.getDictId();
|
||||||
SysDictType dictType = dictTypeMapper.checkDictTypeUnique(dict.getDictType());
|
SysDictType dictType = dictTypeMapper.checkDictTypeUnique(dict.getDictType());
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
router.setQuery(menu.getQuery());
|
router.setQuery(menu.getQuery());
|
||||||
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
|
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
|
||||||
List<SysMenu> cMenus = menu.getChildren();
|
List<SysMenu> cMenus = menu.getChildren();
|
||||||
if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
|
if (StringUtils.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
|
||||||
{
|
{
|
||||||
router.setAlwaysShow(true);
|
router.setAlwaysShow(true);
|
||||||
router.setRedirect("noRedirect");
|
router.setRedirect("noRedirect");
|
||||||
@@ -335,7 +335,7 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkMenuNameUnique(SysMenu menu)
|
public boolean checkMenuNameUnique(SysMenu menu)
|
||||||
{
|
{
|
||||||
Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
|
Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
|
||||||
SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
|
SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class SysPostServiceImpl implements ISysPostService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkPostNameUnique(SysPost post)
|
public boolean checkPostNameUnique(SysPost post)
|
||||||
{
|
{
|
||||||
Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
|
Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
|
||||||
SysPost info = postMapper.checkPostNameUnique(post.getPostName());
|
SysPost info = postMapper.checkPostNameUnique(post.getPostName());
|
||||||
@@ -97,7 +97,7 @@ public class SysPostServiceImpl implements ISysPostService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkPostCodeUnique(SysPost post)
|
public boolean checkPostCodeUnique(SysPost post)
|
||||||
{
|
{
|
||||||
Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
|
Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
|
||||||
SysPost info = postMapper.checkPostCodeUnique(post.getPostCode());
|
SysPost info = postMapper.checkPostCodeUnique(post.getPostCode());
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkRoleNameUnique(SysRole role)
|
public boolean checkRoleNameUnique(SysRole role)
|
||||||
{
|
{
|
||||||
Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
|
Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
|
||||||
SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName());
|
SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName());
|
||||||
@@ -164,7 +164,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkRoleKeyUnique(SysRole role)
|
public boolean checkRoleKeyUnique(SysRole role)
|
||||||
{
|
{
|
||||||
Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
|
Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
|
||||||
SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey());
|
SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey());
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ public class SysUserServiceImpl implements ISysUserService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkUserNameUnique(SysUser user)
|
public boolean checkUserNameUnique(SysUser user)
|
||||||
{
|
{
|
||||||
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
|
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
|
||||||
SysUser info = userMapper.checkUserNameUnique(user.getUserName());
|
SysUser info = userMapper.checkUserNameUnique(user.getUserName());
|
||||||
@@ -183,7 +183,7 @@ public class SysUserServiceImpl implements ISysUserService
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkPhoneUnique(SysUser user)
|
public boolean checkPhoneUnique(SysUser user)
|
||||||
{
|
{
|
||||||
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
|
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
|
||||||
SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber());
|
SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber());
|
||||||
@@ -201,7 +201,7 @@ public class SysUserServiceImpl implements ISysUserService
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String checkEmailUnique(SysUser user)
|
public boolean checkEmailUnique(SysUser user)
|
||||||
{
|
{
|
||||||
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
|
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
|
||||||
SysUser info = userMapper.checkEmailUnique(user.getEmail());
|
SysUser info = userMapper.checkEmailUnique(user.getEmail());
|
||||||
@@ -501,17 +501,18 @@ public class SysUserServiceImpl implements ISysUserService
|
|||||||
BeanValidators.validateWithException(validator, user);
|
BeanValidators.validateWithException(validator, user);
|
||||||
user.setPassword(SecurityUtils.encryptPassword(password));
|
user.setPassword(SecurityUtils.encryptPassword(password));
|
||||||
user.setCreateBy(operName);
|
user.setCreateBy(operName);
|
||||||
this.insertUser(user);
|
userMapper.insertUser(user);
|
||||||
successNum++;
|
successNum++;
|
||||||
successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
|
successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
|
||||||
}
|
}
|
||||||
else if (isUpdateSupport)
|
else if (isUpdateSupport)
|
||||||
{
|
{
|
||||||
BeanValidators.validateWithException(validator, user);
|
BeanValidators.validateWithException(validator, user);
|
||||||
checkUserAllowed(user);
|
checkUserAllowed(u);
|
||||||
checkUserDataScope(user.getUserId());
|
checkUserDataScope(u.getUserId());
|
||||||
|
user.setUserId(u.getUserId());
|
||||||
user.setUpdateBy(operName);
|
user.setUpdateBy(operName);
|
||||||
this.updateUser(user);
|
userMapper.updateUser(user);
|
||||||
successNum++;
|
successNum++;
|
||||||
successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
|
successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
AND user_name like concat('%', #{userName}, '%')
|
AND user_name like concat('%', #{userName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||||
and date_format(login_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
AND login_time >= #{params.beginTime}
|
||||||
</if>
|
</if>
|
||||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||||
and date_format(login_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
AND login_time <= #{params.endTime}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
order by info_id desc
|
order by info_id desc
|
||||||
|
|||||||
@@ -21,16 +21,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<result property="status" column="status" />
|
<result property="status" column="status" />
|
||||||
<result property="errorMsg" column="error_msg" />
|
<result property="errorMsg" column="error_msg" />
|
||||||
<result property="operTime" column="oper_time" />
|
<result property="operTime" column="oper_time" />
|
||||||
|
<result property="costTime" column="cost_time" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectOperLogVo">
|
<sql id="selectOperLogVo">
|
||||||
select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time
|
select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time, cost_time
|
||||||
from sys_oper_log
|
from sys_oper_log
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<insert id="insertOperlog" parameterType="SysOperLog">
|
<insert id="insertOperlog" parameterType="SysOperLog">
|
||||||
insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time)
|
insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, cost_time, oper_time)
|
||||||
values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, sysdate())
|
values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, #{costTime}, sysdate())
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<select id="selectOperLogList" parameterType="SysOperLog" resultMap="SysOperLogResult">
|
<select id="selectOperLogList" parameterType="SysOperLog" resultMap="SysOperLogResult">
|
||||||
@@ -55,10 +56,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
AND oper_name like concat('%', #{operName}, '%')
|
AND oper_name like concat('%', #{operName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||||
and date_format(oper_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
AND oper_time >= #{params.beginTime}
|
||||||
</if>
|
</if>
|
||||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||||
and date_format(oper_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
AND oper_time <= #{params.endTime}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
order by oper_id desc
|
order by oper_id desc
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ruoyi",
|
"name": "ruoyi",
|
||||||
"version": "3.8.5",
|
"version": "3.8.6",
|
||||||
"description": "若依管理系统",
|
"description": "若依管理系统",
|
||||||
"author": "若依",
|
"author": "若依",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
"clipboard": "2.0.8",
|
"clipboard": "2.0.8",
|
||||||
"core-js": "3.25.3",
|
"core-js": "3.25.3",
|
||||||
"echarts": "5.4.0",
|
"echarts": "5.4.0",
|
||||||
"element-ui": "2.15.10",
|
"element-ui": "2.15.13",
|
||||||
"file-saver": "2.0.5",
|
"file-saver": "2.0.5",
|
||||||
"fuse.js": "6.4.3",
|
"fuse.js": "6.4.3",
|
||||||
"highlight.js": "9.18.5",
|
"highlight.js": "9.18.5",
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 137 KiB |
@@ -1,191 +1,182 @@
|
|||||||
@import './variables.scss';
|
@import './variables.scss';
|
||||||
@import './mixin.scss';
|
@import './mixin.scss';
|
||||||
@import './transition.scss';
|
@import './transition.scss';
|
||||||
@import './element-ui.scss';
|
@import './element-ui.scss';
|
||||||
@import './sidebar.scss';
|
@import './sidebar.scss';
|
||||||
@import './btn.scss';
|
@import './btn.scss';
|
||||||
|
|
||||||
body {
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
|
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*:before,
|
*:before,
|
||||||
*:after {
|
*:after {
|
||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-padding {
|
.no-padding {
|
||||||
padding: 0px !important;
|
padding: 0px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.padding-content {
|
.padding-content {
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:focus,
|
a:focus,
|
||||||
a:active {
|
a:active {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a,
|
a,
|
||||||
a:focus,
|
a:focus,
|
||||||
a:hover {
|
a:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
div:focus {
|
div:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fr {
|
.fr {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fl {
|
.fl {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pr-5 {
|
.pr-5 {
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pl-5 {
|
.pl-5 {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pointer {
|
.pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inlineBlock {
|
.inlineBlock {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clearfix {
|
.clearfix {
|
||||||
&:after {
|
&:after {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
content: " ";
|
content: " ";
|
||||||
clear: both;
|
clear: both;
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aside {
|
aside {
|
||||||
background: #eef1f6;
|
background: #eef1f6;
|
||||||
padding: 8px 24px;
|
padding: 8px 24px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
display: block;
|
display: block;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #337ab7;
|
color: #337ab7;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: rgb(32, 160, 255);
|
color: rgb(32, 160, 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//main-container全局样式
|
//main-container全局样式
|
||||||
.app-container {
|
.app-container {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.components-container {
|
.components-container {
|
||||||
margin: 30px 50px;
|
margin: 30px 50px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-container {
|
.pagination-container {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-center {
|
.text-center {
|
||||||
text-align: center
|
text-align: center
|
||||||
}
|
}
|
||||||
|
|
||||||
.sub-navbar {
|
.sub-navbar {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
transition: 600ms ease position;
|
transition: 600ms ease position;
|
||||||
background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
|
background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.draft {
|
&.draft {
|
||||||
background: #d0d0d0;
|
background: #d0d0d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.deleted {
|
&.deleted {
|
||||||
background: #d0d0d0;
|
background: #d0d0d0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-type,
|
.link-type,
|
||||||
.link-type:focus {
|
.link-type:focus {
|
||||||
color: #337ab7;
|
color: #337ab7;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: rgb(32, 160, 255);
|
color: rgb(32, 160, 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-container {
|
.filter-container {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
|
||||||
.filter-item {
|
.filter-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//refine vue-multiselect plugin
|
|
||||||
.multiselect {
|
|
||||||
line-height: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.multiselect--active {
|
|
||||||
z-index: 1000 !important;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#app {
|
#app {
|
||||||
|
|
||||||
.main-container {
|
.main-container {
|
||||||
min-height: 100%;
|
height: 100%;
|
||||||
transition: margin-left .28s;
|
transition: margin-left .28s;
|
||||||
margin-left: $base-sidebar-width;
|
margin-left: $base-sidebar-width;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@@ -18,10 +18,6 @@
|
|||||||
transition: all .5s;
|
transition: all .5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-transform-leave-active {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-transform-enter {
|
.fade-transform-enter {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(-30px);
|
transform: translateX(-30px);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
:key="item.value"
|
:key="item.value"
|
||||||
:index="index"
|
:index="index"
|
||||||
:class="item.raw.cssClass"
|
:class="item.raw.cssClass"
|
||||||
>{{ item.label }}</span
|
>{{ item.label + " " }}</span
|
||||||
>
|
>
|
||||||
<el-tag
|
<el-tag
|
||||||
v-else
|
v-else
|
||||||
@@ -17,10 +17,13 @@
|
|||||||
:type="item.raw.listClass == 'primary' ? '' : item.raw.listClass"
|
:type="item.raw.listClass == 'primary' ? '' : item.raw.listClass"
|
||||||
:class="item.raw.cssClass"
|
:class="item.raw.cssClass"
|
||||||
>
|
>
|
||||||
{{ item.label }}
|
{{ item.label + " " }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="unmatch && showValue">
|
||||||
|
{{ unmatchArray | handleArray }}
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -33,20 +36,57 @@ export default {
|
|||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
value: [Number, String, Array],
|
value: [Number, String, Array],
|
||||||
|
// 当未找到匹配的数据时,显示value
|
||||||
|
showValue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
unmatchArray: [], // 记录未匹配的项
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
values() {
|
values() {
|
||||||
if (this.value !== null && typeof this.value !== 'undefined') {
|
if (this.value !== null && typeof this.value !== "undefined") {
|
||||||
return Array.isArray(this.value) ? this.value : [String(this.value)];
|
return Array.isArray(this.value) ? this.value : [String(this.value)];
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
unmatch() {
|
||||||
|
this.unmatchArray = [];
|
||||||
|
if (this.value !== null && typeof this.value !== "undefined") {
|
||||||
|
// 传入值为非数组
|
||||||
|
if (!Array.isArray(this.value)) {
|
||||||
|
if (this.options.some((v) => v.value == this.value)) return false;
|
||||||
|
this.unmatchArray.push(this.value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 传入值为Array
|
||||||
|
this.value.forEach((item) => {
|
||||||
|
if (!this.options.some((v) => v.value == item))
|
||||||
|
this.unmatchArray.push(item);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 没有value不显示
|
||||||
|
return false;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
filters: {
|
||||||
|
handleArray(array) {
|
||||||
|
if (array.length === 0) return "";
|
||||||
|
return array.reduce((pre, cur) => {
|
||||||
|
return pre + " " + cur;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.el-tag + .el-tag {
|
.el-tag + .el-tag {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,68 +1,104 @@
|
|||||||
<!-- @author zhengjie -->
|
<!-- @author zhengjie -->
|
||||||
<template>
|
<template>
|
||||||
<div class="icon-body">
|
<div class="icon-body">
|
||||||
<el-input v-model="name" style="position: relative;" clearable placeholder="请输入图标名称" @clear="filterIcons" @input.native="filterIcons">
|
<el-input v-model="name" class="icon-search" clearable placeholder="请输入图标名称" @clear="filterIcons" @input="filterIcons">
|
||||||
<i slot="suffix" class="el-icon-search el-input__icon" />
|
<i slot="suffix" class="el-icon-search el-input__icon" />
|
||||||
</el-input>
|
</el-input>
|
||||||
<div class="icon-list">
|
<div class="icon-list">
|
||||||
<div v-for="(item, index) in iconList" :key="index" @click="selectedIcon(item)">
|
<div class="list-container">
|
||||||
<svg-icon :icon-class="item" style="height: 30px;width: 16px;" />
|
<div v-for="(item, index) in iconList" class="icon-item-wrapper" :key="index" @click="selectedIcon(item)">
|
||||||
<span>{{ item }}</span>
|
<div :class="['icon-item', { active: activeIcon === item }]">
|
||||||
</div>
|
<svg-icon :icon-class="item" class-name="icon" style="height: 25px;width: 16px;"/>
|
||||||
</div>
|
<span>{{ item }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
|
</div>
|
||||||
<script>
|
</div>
|
||||||
import icons from './requireIcons'
|
</div>
|
||||||
export default {
|
</template>
|
||||||
name: 'IconSelect',
|
|
||||||
data() {
|
<script>
|
||||||
return {
|
import icons from './requireIcons'
|
||||||
name: '',
|
export default {
|
||||||
iconList: icons
|
name: 'IconSelect',
|
||||||
}
|
props: {
|
||||||
},
|
activeIcon: {
|
||||||
methods: {
|
type: String
|
||||||
filterIcons() {
|
}
|
||||||
this.iconList = icons
|
},
|
||||||
if (this.name) {
|
data() {
|
||||||
this.iconList = this.iconList.filter(item => item.includes(this.name))
|
return {
|
||||||
}
|
name: '',
|
||||||
},
|
iconList: icons
|
||||||
selectedIcon(name) {
|
}
|
||||||
this.$emit('selected', name)
|
},
|
||||||
document.body.click()
|
methods: {
|
||||||
},
|
filterIcons() {
|
||||||
reset() {
|
this.iconList = icons
|
||||||
this.name = ''
|
if (this.name) {
|
||||||
this.iconList = icons
|
this.iconList = this.iconList.filter(item => item.includes(this.name))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
selectedIcon(name) {
|
||||||
</script>
|
this.$emit('selected', name)
|
||||||
|
document.body.click()
|
||||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
},
|
||||||
.icon-body {
|
reset() {
|
||||||
width: 100%;
|
this.name = ''
|
||||||
padding: 10px;
|
this.iconList = icons
|
||||||
.icon-list {
|
}
|
||||||
height: 200px;
|
}
|
||||||
overflow-y: scroll;
|
}
|
||||||
div {
|
</script>
|
||||||
height: 30px;
|
|
||||||
line-height: 30px;
|
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||||
margin-bottom: -5px;
|
.icon-body {
|
||||||
cursor: pointer;
|
width: 100%;
|
||||||
width: 33%;
|
padding: 10px;
|
||||||
float: left;
|
.icon-search {
|
||||||
}
|
position: relative;
|
||||||
span {
|
margin-bottom: 5px;
|
||||||
display: inline-block;
|
}
|
||||||
vertical-align: -0.15em;
|
.icon-list {
|
||||||
fill: currentColor;
|
height: 200px;
|
||||||
overflow: hidden;
|
overflow: auto;
|
||||||
}
|
.list-container {
|
||||||
}
|
display: flex;
|
||||||
}
|
flex-wrap: wrap;
|
||||||
</style>
|
.icon-item-wrapper {
|
||||||
|
width: calc(100% / 3);
|
||||||
|
height: 25px;
|
||||||
|
line-height: 25px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
.icon-item {
|
||||||
|
display: flex;
|
||||||
|
max-width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 5px;
|
||||||
|
&:hover {
|
||||||
|
background: #ececec;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: -0.15em;
|
||||||
|
fill: currentColor;
|
||||||
|
padding-left: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.icon-item.active {
|
||||||
|
background: #ececec;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -127,7 +127,13 @@ export default {
|
|||||||
window.open(key, "_blank");
|
window.open(key, "_blank");
|
||||||
} else if (!route || !route.children) {
|
} else if (!route || !route.children) {
|
||||||
// 没有子路由路径内部打开
|
// 没有子路由路径内部打开
|
||||||
this.$router.push({ path: key });
|
const routeMenu = this.childrenMenus.find(item => item.path === key);
|
||||||
|
if (routeMenu && routeMenu.query) {
|
||||||
|
let query = JSON.parse(routeMenu.query);
|
||||||
|
this.$router.push({ path: key, query: query });
|
||||||
|
} else {
|
||||||
|
this.$router.push({ path: key });
|
||||||
|
}
|
||||||
this.$store.dispatch('app/toggleSideBarHide', true);
|
this.$store.dispatch('app/toggleSideBarHide', true);
|
||||||
} else {
|
} else {
|
||||||
// 显示左侧联动菜单
|
// 显示左侧联动菜单
|
||||||
|
|||||||
@@ -1,61 +1,75 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="app-main">
|
<section class="app-main">
|
||||||
<transition name="fade-transform" mode="out-in">
|
<transition name="fade-transform" mode="out-in">
|
||||||
<keep-alive :include="cachedViews">
|
<keep-alive :include="cachedViews">
|
||||||
<router-view v-if="!$route.meta.link" :key="key" />
|
<router-view v-if="!$route.meta.link" :key="key" />
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</transition>
|
</transition>
|
||||||
<iframe-toggle />
|
<iframe-toggle />
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import iframeToggle from "./IframeToggle/index"
|
import iframeToggle from "./IframeToggle/index"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AppMain',
|
name: 'AppMain',
|
||||||
components: { iframeToggle },
|
components: { iframeToggle },
|
||||||
computed: {
|
computed: {
|
||||||
cachedViews() {
|
cachedViews() {
|
||||||
return this.$store.state.tagsView.cachedViews
|
return this.$store.state.tagsView.cachedViews
|
||||||
},
|
},
|
||||||
key() {
|
key() {
|
||||||
return this.$route.path
|
return this.$route.path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.app-main {
|
.app-main {
|
||||||
/* 50= navbar 50 */
|
/* 50= navbar 50 */
|
||||||
min-height: calc(100vh - 50px);
|
min-height: calc(100vh - 50px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fixed-header + .app-main {
|
.fixed-header + .app-main {
|
||||||
padding-top: 50px;
|
padding-top: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hasTagsView {
|
.hasTagsView {
|
||||||
.app-main {
|
.app-main {
|
||||||
/* 84 = navbar + tags-view = 50 + 34 */
|
/* 84 = navbar + tags-view = 50 + 34 */
|
||||||
min-height: calc(100vh - 84px);
|
min-height: calc(100vh - 84px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fixed-header + .app-main {
|
.fixed-header + .app-main {
|
||||||
padding-top: 84px;
|
padding-top: 84px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
// fix css style bug in open el-dialog
|
// fix css style bug in open el-dialog
|
||||||
.el-popup-parent--hidden {
|
.el-popup-parent--hidden {
|
||||||
.fixed-header {
|
.fixed-header {
|
||||||
padding-right: 17px;
|
padding-right: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #c0c0c0;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: '若依管理系统',
|
title: process.env.VUE_APP_TITLE,
|
||||||
logo: logoImg
|
logo: logoImg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,94 +1,94 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
|
<el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
|
||||||
<slot />
|
<slot />
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const tagAndTagSpacing = 4 // tagAndTagSpacing
|
const tagAndTagSpacing = 4 // tagAndTagSpacing
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ScrollPane',
|
name: 'ScrollPane',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
left: 0
|
left: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
scrollWrapper() {
|
scrollWrapper() {
|
||||||
return this.$refs.scrollContainer.$refs.wrap
|
return this.$refs.scrollContainer.$refs.wrap
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.scrollWrapper.addEventListener('scroll', this.emitScroll, true)
|
this.scrollWrapper.addEventListener('scroll', this.emitScroll, true)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.scrollWrapper.removeEventListener('scroll', this.emitScroll)
|
this.scrollWrapper.removeEventListener('scroll', this.emitScroll)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleScroll(e) {
|
handleScroll(e) {
|
||||||
const eventDelta = e.wheelDelta || -e.deltaY * 40
|
const eventDelta = e.wheelDelta || -e.deltaY * 40
|
||||||
const $scrollWrapper = this.scrollWrapper
|
const $scrollWrapper = this.scrollWrapper
|
||||||
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
|
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
|
||||||
},
|
},
|
||||||
emitScroll() {
|
emitScroll() {
|
||||||
this.$emit('scroll')
|
this.$emit('scroll')
|
||||||
},
|
},
|
||||||
moveToTarget(currentTag) {
|
moveToTarget(currentTag) {
|
||||||
const $container = this.$refs.scrollContainer.$el
|
const $container = this.$refs.scrollContainer.$el
|
||||||
const $containerWidth = $container.offsetWidth
|
const $containerWidth = $container.offsetWidth
|
||||||
const $scrollWrapper = this.scrollWrapper
|
const $scrollWrapper = this.scrollWrapper
|
||||||
const tagList = this.$parent.$refs.tag
|
const tagList = this.$parent.$refs.tag
|
||||||
|
|
||||||
let firstTag = null
|
let firstTag = null
|
||||||
let lastTag = null
|
let lastTag = null
|
||||||
|
|
||||||
// find first tag and last tag
|
// find first tag and last tag
|
||||||
if (tagList.length > 0) {
|
if (tagList.length > 0) {
|
||||||
firstTag = tagList[0]
|
firstTag = tagList[0]
|
||||||
lastTag = tagList[tagList.length - 1]
|
lastTag = tagList[tagList.length - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstTag === currentTag) {
|
if (firstTag === currentTag) {
|
||||||
$scrollWrapper.scrollLeft = 0
|
$scrollWrapper.scrollLeft = 0
|
||||||
} else if (lastTag === currentTag) {
|
} else if (lastTag === currentTag) {
|
||||||
$scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
|
$scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
|
||||||
} else {
|
} else {
|
||||||
// find preTag and nextTag
|
// find preTag and nextTag
|
||||||
const currentIndex = tagList.findIndex(item => item === currentTag)
|
const currentIndex = tagList.findIndex(item => item === currentTag)
|
||||||
const prevTag = tagList[currentIndex - 1]
|
const prevTag = tagList[currentIndex - 1]
|
||||||
const nextTag = tagList[currentIndex + 1]
|
const nextTag = tagList[currentIndex + 1]
|
||||||
|
|
||||||
// the tag's offsetLeft after of nextTag
|
// the tag's offsetLeft after of nextTag
|
||||||
const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
|
const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
|
||||||
|
|
||||||
// the tag's offsetLeft before of prevTag
|
// the tag's offsetLeft before of prevTag
|
||||||
const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
|
const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
|
||||||
|
|
||||||
if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
|
if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
|
||||||
$scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
|
$scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
|
||||||
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
|
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
|
||||||
$scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
|
$scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.scroll-container {
|
.scroll-container {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
::v-deep {
|
::v-deep {
|
||||||
.el-scrollbar__bar {
|
.el-scrollbar__bar {
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
}
|
}
|
||||||
.el-scrollbar__wrap {
|
.el-scrollbar__wrap {
|
||||||
height: 49px;
|
height: 39px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ export default {
|
|||||||
},
|
},
|
||||||
isFirstView() {
|
isFirstView() {
|
||||||
try {
|
try {
|
||||||
return this.selectedTag.fullPath === this.visitedViews[1].fullPath || this.selectedTag.fullPath === '/index'
|
return this.selectedTag.fullPath === '/index' || this.selectedTag.fullPath === this.visitedViews[1].fullPath
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
closeOthersTags() {
|
closeOthersTags() {
|
||||||
this.$router.push(this.selectedTag).catch(()=>{});
|
this.$router.push(this.selectedTag.fullPath).catch(()=>{});
|
||||||
this.$tab.closeOtherPage(this.selectedTag).then(() => {
|
this.$tab.closeOtherPage(this.selectedTag).then(() => {
|
||||||
this.moveToCurrentTag()
|
this.moveToCurrentTag()
|
||||||
})
|
})
|
||||||
|
|||||||
+111
-111
@@ -1,111 +1,111 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
|
<div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
|
||||||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
|
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
|
||||||
<sidebar v-if="!sidebar.hide" class="sidebar-container" />
|
<sidebar v-if="!sidebar.hide" class="sidebar-container"/>
|
||||||
<div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container">
|
<div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container">
|
||||||
<div :class="{'fixed-header':fixedHeader}">
|
<div :class="{'fixed-header':fixedHeader}">
|
||||||
<navbar />
|
<navbar/>
|
||||||
<tags-view v-if="needTagsView" />
|
<tags-view v-if="needTagsView"/>
|
||||||
</div>
|
</div>
|
||||||
<app-main />
|
<app-main/>
|
||||||
<right-panel>
|
<right-panel>
|
||||||
<settings />
|
<settings/>
|
||||||
</right-panel>
|
</right-panel>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import RightPanel from '@/components/RightPanel'
|
import RightPanel from '@/components/RightPanel'
|
||||||
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
|
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
|
||||||
import ResizeMixin from './mixin/ResizeHandler'
|
import ResizeMixin from './mixin/ResizeHandler'
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import variables from '@/assets/styles/variables.scss'
|
import variables from '@/assets/styles/variables.scss'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Layout',
|
name: 'Layout',
|
||||||
components: {
|
components: {
|
||||||
AppMain,
|
AppMain,
|
||||||
Navbar,
|
Navbar,
|
||||||
RightPanel,
|
RightPanel,
|
||||||
Settings,
|
Settings,
|
||||||
Sidebar,
|
Sidebar,
|
||||||
TagsView
|
TagsView
|
||||||
},
|
},
|
||||||
mixins: [ResizeMixin],
|
mixins: [ResizeMixin],
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
theme: state => state.settings.theme,
|
theme: state => state.settings.theme,
|
||||||
sideTheme: state => state.settings.sideTheme,
|
sideTheme: state => state.settings.sideTheme,
|
||||||
sidebar: state => state.app.sidebar,
|
sidebar: state => state.app.sidebar,
|
||||||
device: state => state.app.device,
|
device: state => state.app.device,
|
||||||
needTagsView: state => state.settings.tagsView,
|
needTagsView: state => state.settings.tagsView,
|
||||||
fixedHeader: state => state.settings.fixedHeader
|
fixedHeader: state => state.settings.fixedHeader
|
||||||
}),
|
}),
|
||||||
classObj() {
|
classObj() {
|
||||||
return {
|
return {
|
||||||
hideSidebar: !this.sidebar.opened,
|
hideSidebar: !this.sidebar.opened,
|
||||||
openSidebar: this.sidebar.opened,
|
openSidebar: this.sidebar.opened,
|
||||||
withoutAnimation: this.sidebar.withoutAnimation,
|
withoutAnimation: this.sidebar.withoutAnimation,
|
||||||
mobile: this.device === 'mobile'
|
mobile: this.device === 'mobile'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return variables;
|
return variables;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleClickOutside() {
|
handleClickOutside() {
|
||||||
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "~@/assets/styles/mixin.scss";
|
@import "~@/assets/styles/mixin.scss";
|
||||||
@import "~@/assets/styles/variables.scss";
|
@import "~@/assets/styles/variables.scss";
|
||||||
|
|
||||||
.app-wrapper {
|
.app-wrapper {
|
||||||
@include clearfix;
|
@include clearfix;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
&.mobile.openSidebar {
|
&.mobile.openSidebar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-bg {
|
.drawer-bg {
|
||||||
background: #000;
|
background: #000;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fixed-header {
|
.fixed-header {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
width: calc(100% - #{$base-sidebar-width});
|
width: calc(100% - #{$base-sidebar-width});
|
||||||
transition: width 0.28s;
|
transition: width 0.28s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hideSidebar .fixed-header {
|
.hideSidebar .fixed-header {
|
||||||
width: calc(100% - 54px);
|
width: calc(100% - 54px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebarHide .fixed-header {
|
.sidebarHide .fixed-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile .fixed-header {
|
.mobile .fixed-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { isRelogin } from '@/utils/request'
|
|||||||
|
|
||||||
NProgress.configure({ showSpinner: false })
|
NProgress.configure({ showSpinner: false })
|
||||||
|
|
||||||
const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
|
const whiteList = ['/login', '/register']
|
||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
NProgress.start()
|
NProgress.start()
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ export default {
|
|||||||
url: url,
|
url: url,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
headers: { 'Authorization': 'Bearer ' + getToken() }
|
headers: { 'Authorization': 'Bearer ' + getToken() }
|
||||||
}).then(async (res) => {
|
}).then((res) => {
|
||||||
const isLogin = await blobValidate(res.data);
|
const isBlob = blobValidate(res.data);
|
||||||
if (isLogin) {
|
if (isBlob) {
|
||||||
const blob = new Blob([res.data])
|
const blob = new Blob([res.data])
|
||||||
this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
|
this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
|
||||||
} else {
|
} else {
|
||||||
@@ -32,9 +32,9 @@ export default {
|
|||||||
url: url,
|
url: url,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
headers: { 'Authorization': 'Bearer ' + getToken() }
|
headers: { 'Authorization': 'Bearer ' + getToken() }
|
||||||
}).then(async (res) => {
|
}).then((res) => {
|
||||||
const isLogin = await blobValidate(res.data);
|
const isBlob = blobValidate(res.data);
|
||||||
if (isLogin) {
|
if (isBlob) {
|
||||||
const blob = new Blob([res.data])
|
const blob = new Blob([res.data])
|
||||||
this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
|
this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
|
||||||
} else {
|
} else {
|
||||||
@@ -49,9 +49,9 @@ export default {
|
|||||||
url: url,
|
url: url,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
headers: { 'Authorization': 'Bearer ' + getToken() }
|
headers: { 'Authorization': 'Bearer ' + getToken() }
|
||||||
}).then(async (res) => {
|
}).then((res) => {
|
||||||
const isLogin = await blobValidate(res.data);
|
const isBlob = blobValidate(res.data);
|
||||||
if (isLogin) {
|
if (isBlob) {
|
||||||
const blob = new Blob([res.data], { type: 'application/zip' })
|
const blob = new Blob([res.data], { type: 'application/zip' })
|
||||||
this.saveAs(blob, name)
|
this.saveAs(blob, name)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -32,8 +32,12 @@ export default {
|
|||||||
// 关闭指定tab页签
|
// 关闭指定tab页签
|
||||||
closePage(obj) {
|
closePage(obj) {
|
||||||
if (obj === undefined) {
|
if (obj === undefined) {
|
||||||
return store.dispatch('tagsView/delView', router.currentRoute).then(({ lastPath }) => {
|
return store.dispatch('tagsView/delView', router.currentRoute).then(({ visitedViews }) => {
|
||||||
return router.push(lastPath || '/');
|
const latestView = visitedViews.slice(-1)[0]
|
||||||
|
if (latestView) {
|
||||||
|
return router.push(latestView.fullPath)
|
||||||
|
}
|
||||||
|
return router.push('/');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return store.dispatch('tagsView/delView', obj);
|
return store.dispatch('tagsView/delView', obj);
|
||||||
|
|||||||
@@ -166,9 +166,15 @@ export const dynamicRoutes = [
|
|||||||
|
|
||||||
// 防止连续点击多次路由报错
|
// 防止连续点击多次路由报错
|
||||||
let routerPush = Router.prototype.push;
|
let routerPush = Router.prototype.push;
|
||||||
|
let routerReplace = Router.prototype.replace;
|
||||||
|
// push
|
||||||
Router.prototype.push = function push(location) {
|
Router.prototype.push = function push(location) {
|
||||||
return routerPush.call(this, location).catch(err => err)
|
return routerPush.call(this, location).catch(err => err)
|
||||||
}
|
}
|
||||||
|
// replace
|
||||||
|
Router.prototype.replace = function push(location) {
|
||||||
|
return routerReplace.call(this, location).catch(err => err)
|
||||||
|
}
|
||||||
|
|
||||||
export default new Router({
|
export default new Router({
|
||||||
mode: 'history', // 去掉url中的#
|
mode: 'history', // 去掉url中的#
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { isArray } from 'util'
|
|
||||||
import { exportDefault, titleCase } from '@/utils/index'
|
import { exportDefault, titleCase } from '@/utils/index'
|
||||||
import { trigger } from './config'
|
import { trigger } from './config'
|
||||||
|
|
||||||
@@ -133,12 +132,12 @@ function buildRules(conf, ruleList) {
|
|||||||
const rules = []
|
const rules = []
|
||||||
if (trigger[conf.tag]) {
|
if (trigger[conf.tag]) {
|
||||||
if (conf.required) {
|
if (conf.required) {
|
||||||
const type = isArray(conf.defaultValue) ? 'type: \'array\',' : ''
|
const type = Array.isArray(conf.defaultValue) ? 'type: \'array\',' : ''
|
||||||
let message = isArray(conf.defaultValue) ? `请至少选择一个${conf.vModel}` : conf.placeholder
|
let message = Array.isArray(conf.defaultValue) ? `请至少选择一个${conf.vModel}` : conf.placeholder
|
||||||
if (message === undefined) message = `${conf.label}不能为空`
|
if (message === undefined) message = `${conf.label}不能为空`
|
||||||
rules.push(`{ required: true, ${type} message: '${message}', trigger: '${trigger[conf.tag]}' }`)
|
rules.push(`{ required: true, ${type} message: '${message}', trigger: '${trigger[conf.tag]}' }`)
|
||||||
}
|
}
|
||||||
if (conf.regList && isArray(conf.regList)) {
|
if (conf.regList && Array.isArray(conf.regList)) {
|
||||||
conf.regList.forEach(item => {
|
conf.regList.forEach(item => {
|
||||||
if (item.pattern) {
|
if (item.pattern) {
|
||||||
rules.push(`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${trigger[conf.tag]}' }`)
|
rules.push(`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${trigger[conf.tag]}' }`)
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ service.interceptors.response.use(res => {
|
|||||||
// 获取错误信息
|
// 获取错误信息
|
||||||
const msg = errorCode[code] || res.data.msg || errorCode['default']
|
const msg = errorCode[code] || res.data.msg || errorCode['default']
|
||||||
// 二进制数据则直接返回
|
// 二进制数据则直接返回
|
||||||
if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){
|
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
|
||||||
return res.data
|
return res.data
|
||||||
}
|
}
|
||||||
if (code === 401) {
|
if (code === 401) {
|
||||||
@@ -125,8 +125,8 @@ export function download(url, params, filename, config) {
|
|||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
...config
|
...config
|
||||||
}).then(async (data) => {
|
}).then(async (data) => {
|
||||||
const isLogin = await blobValidate(data);
|
const isBlob = blobValidate(data);
|
||||||
if (isLogin) {
|
if (isBlob) {
|
||||||
const blob = new Blob([data])
|
const blob = new Blob([data])
|
||||||
saveAs(blob, filename)
|
saveAs(blob, filename)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -228,12 +228,6 @@ export function tansParams(params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 验证是否为blob格式
|
// 验证是否为blob格式
|
||||||
export async function blobValidate(data) {
|
export function blobValidate(data) {
|
||||||
try {
|
return data.type !== 'application/json'
|
||||||
const text = await data.text();
|
|
||||||
JSON.parse(text);
|
|
||||||
return false;
|
|
||||||
} catch (error) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,12 +118,11 @@
|
|||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<i class="el-icon-user-solid"></i> QQ群:<s>满937441</s> <s>满887144332</s>
|
<i class="el-icon-user-solid"></i> QQ群:<s> 满937441 </s> <s> 满887144332 </s>
|
||||||
<s>满180251782</s> <s>满104180207</s> <s>满186866453</s> <s>满201396349</s>
|
<s> 满180251782 </s> <s> 满104180207 </s> <s> 满186866453 </s> <s> 满201396349 </s>
|
||||||
<s>满101456076</s> <s>满101539465</s> <s>满264312783</s> <s>满167385320</s>
|
<s> 满101456076 </s> <s> 满101539465 </s> <s> 满264312783 </s> <s> 满167385320 </s>
|
||||||
<s>满104748341</s> <s>满160110482</s> <a href="https://jq.qq.com/?_wv=1027&k=Xnbinl0U" target="_blank">
|
<s> 满104748341 </s> <s> 满160110482 </s> <s> 满170801498 </s> <s> 满108482800 </s>
|
||||||
170801498</a
|
<s> 满101046199 </s> <a href="https://jq.qq.com/?_wv=1027&k=tKEt51dz" target="_blank">136919097</a>
|
||||||
>
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<i class="el-icon-chat-dot-round"></i> 微信:<a
|
<i class="el-icon-chat-dot-round"></i> 微信:<a
|
||||||
@@ -147,6 +146,44 @@
|
|||||||
<span>更新日志</span>
|
<span>更新日志</span>
|
||||||
</div>
|
</div>
|
||||||
<el-collapse accordion>
|
<el-collapse accordion>
|
||||||
|
<el-collapse-item title="v3.8.6 - 2023-06-30">
|
||||||
|
<ol>
|
||||||
|
<li>支持登录IP黑名单限制</li>
|
||||||
|
<li>新增监控页面图标显示</li>
|
||||||
|
<li>操作日志新增消耗时间属性</li>
|
||||||
|
<li>屏蔽定时任务bean违规的字符</li>
|
||||||
|
<li>日志管理使用索引提升查询性能</li>
|
||||||
|
<li>日志注解支持排除指定的请求参数</li>
|
||||||
|
<li>支持自定义隐藏属性列过滤子对象</li>
|
||||||
|
<li>升级oshi到最新版本6.4.3</li>
|
||||||
|
<li>升级druid到最新版本1.2.16</li>
|
||||||
|
<li>升级fastjson到最新版2.0.34</li>
|
||||||
|
<li>升级spring-boot到最新版本2.5.15</li>
|
||||||
|
<li>升级element-ui到最新版本2.15.13</li>
|
||||||
|
<li>移除apache/commons-fileupload依赖</li>
|
||||||
|
<li>修复页面切换时布局错乱的问题</li>
|
||||||
|
<li>修复匿名注解Anonymous空指针问题</li>
|
||||||
|
<li>修复路由跳转被阻止时内部产生报错信息问题</li>
|
||||||
|
<li>修复isMatchedIp的参数判断产生空指针的问题</li>
|
||||||
|
<li>修复用户多角色数据权限可能出现权限抬升的情况</li>
|
||||||
|
<li>修复开启TopNav后一级菜单路由参数设置无效问题</li>
|
||||||
|
<li>修复DictTag组件value没有匹配的值时则展示value</li>
|
||||||
|
<li>优化文件下载出现的异常</li>
|
||||||
|
<li>优化选择图标组件高亮回显</li>
|
||||||
|
<li>优化弹窗后导航栏偏移的问题</li>
|
||||||
|
<li>优化修改密码日志存储明文问题</li>
|
||||||
|
<li>优化页签栏关闭其他出现的异常问题</li>
|
||||||
|
<li>优化页签关闭左侧选项排除首页选项</li>
|
||||||
|
<li>优化关闭当前tab页跳转最右侧tab页</li>
|
||||||
|
<li>优化缓存列表清除操作提示不变的问题</li>
|
||||||
|
<li>优化字符未使用下划线不进行驼峰式处理</li>
|
||||||
|
<li>优化用户导入更新时需获取用户编号问题</li>
|
||||||
|
<li>优化侧边栏的平台标题与VUE_APP_TITLE保持同步</li>
|
||||||
|
<li>优化导出Excel时设置dictType属性重复查缓存问题</li>
|
||||||
|
<li>连接池Druid支持新的配置connectTimeout和socketTimeout</li>
|
||||||
|
<li>其他细节优化</li>
|
||||||
|
</ol>
|
||||||
|
</el-collapse-item>
|
||||||
<el-collapse-item title="v3.8.5 - 2023-01-01">
|
<el-collapse-item title="v3.8.5 - 2023-01-01">
|
||||||
<ol>
|
<ol>
|
||||||
<li>定时任务违规的字符</li>
|
<li>定时任务违规的字符</li>
|
||||||
@@ -889,7 +926,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<img
|
<img
|
||||||
src="https://oscimg.oschina.net/oscnet/up-d6695f82666e5018f715c41cb7ee60d3b73.png"
|
src="@/assets/images/pay.png"
|
||||||
alt="donate"
|
alt="donate"
|
||||||
width="100%"
|
width="100%"
|
||||||
/>
|
/>
|
||||||
@@ -909,7 +946,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 版本号
|
// 版本号
|
||||||
version: "3.8.5"
|
version: "3.8.6"
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<!-- 底部 -->
|
<!-- 底部 -->
|
||||||
<div class="el-login-footer">
|
<div class="el-login-footer">
|
||||||
<span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
|
<span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
+3
-5
@@ -3,7 +3,7 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24" class="card-box">
|
<el-col :span="24" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header"><span>基本信息</span></div>
|
<div slot="header"><span><i class="el-icon-monitor"></i> 基本信息</span></div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%">
|
<table cellspacing="0" style="width: 100%">
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
<el-col :span="12" class="card-box">
|
<el-col :span="12" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header"><span>命令统计</span></div>
|
<div slot="header"><span><i class="el-icon-pie-chart"></i> 命令统计</span></div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<div ref="commandstats" style="height: 420px" />
|
<div ref="commandstats" style="height: 420px" />
|
||||||
</div>
|
</div>
|
||||||
@@ -54,9 +54,7 @@
|
|||||||
|
|
||||||
<el-col :span="12" class="card-box">
|
<el-col :span="12" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header">
|
<div slot="header"><span><i class="el-icon-odometer"></i> 内存信息</span></div>
|
||||||
<span>内存信息</span>
|
|
||||||
</div>
|
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<div ref="usedmemory" style="height: 420px" />
|
<div ref="usedmemory" style="height: 420px" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+4
-4
@@ -4,7 +4,7 @@
|
|||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card style="height: calc(100vh - 125px)">
|
<el-card style="height: calc(100vh - 125px)">
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<span>缓存列表</span>
|
<span><i class="el-icon-collection"></i> 缓存列表</span>
|
||||||
<el-button
|
<el-button
|
||||||
style="float: right; padding: 3px 0"
|
style="float: right; padding: 3px 0"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card style="height: calc(100vh - 125px)">
|
<el-card style="height: calc(100vh - 125px)">
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<span>键名列表</span>
|
<span><i class="el-icon-key"></i> 键名列表</span>
|
||||||
<el-button
|
<el-button
|
||||||
style="float: right; padding: 3px 0"
|
style="float: right; padding: 3px 0"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card :bordered="false" style="height: calc(100vh - 125px)">
|
<el-card :bordered="false" style="height: calc(100vh - 125px)">
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<span>缓存内容</span>
|
<span><i class="el-icon-document"></i> 缓存内容</span>
|
||||||
<el-button
|
<el-button
|
||||||
style="float: right; padding: 3px 0"
|
style="float: right; padding: 3px 0"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -187,7 +187,7 @@ export default {
|
|||||||
/** 清理指定名称缓存 */
|
/** 清理指定名称缓存 */
|
||||||
handleClearCacheName(row) {
|
handleClearCacheName(row) {
|
||||||
clearCacheName(row.cacheName).then(response => {
|
clearCacheName(row.cacheName).then(response => {
|
||||||
this.$modal.msgSuccess("清理缓存名称[" + this.nowCacheName + "]成功");
|
this.$modal.msgSuccess("清理缓存名称[" + row.cacheName + "]成功");
|
||||||
this.getCacheKeys();
|
this.getCacheKeys();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -38,11 +38,12 @@
|
|||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="dateRange"
|
v-model="dateRange"
|
||||||
style="width: 240px"
|
style="width: 240px"
|
||||||
value-format="yyyy-MM-dd"
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
type="daterange"
|
type="daterange"
|
||||||
range-separator="-"
|
range-separator="-"
|
||||||
start-placeholder="开始日期"
|
start-placeholder="开始日期"
|
||||||
end-placeholder="结束日期"
|
end-placeholder="结束日期"
|
||||||
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
></el-date-picker>
|
></el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -110,7 +111,7 @@
|
|||||||
<dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/>
|
<dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作信息" align="center" prop="msg" />
|
<el-table-column label="操作信息" align="center" prop="msg" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="登录日期" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
|
<el-table-column label="登录日期" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ parseTime(scope.row.loginTime) }}</span>
|
<span>{{ parseTime(scope.row.loginTime) }}</span>
|
||||||
|
|||||||
@@ -53,11 +53,12 @@
|
|||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="dateRange"
|
v-model="dateRange"
|
||||||
style="width: 240px"
|
style="width: 240px"
|
||||||
value-format="yyyy-MM-dd"
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
type="daterange"
|
type="daterange"
|
||||||
range-separator="-"
|
range-separator="-"
|
||||||
start-placeholder="开始日期"
|
start-placeholder="开始日期"
|
||||||
end-placeholder="结束日期"
|
end-placeholder="结束日期"
|
||||||
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
></el-date-picker>
|
></el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -102,16 +103,15 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-table ref="tables" v-loading="loading" :data="list" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
|
<el-table ref="tables" v-loading="loading" :data="list" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column type="selection" width="50" align="center" />
|
||||||
<el-table-column label="日志编号" align="center" prop="operId" />
|
<el-table-column label="日志编号" align="center" prop="operId" />
|
||||||
<el-table-column label="系统模块" align="center" prop="title" />
|
<el-table-column label="系统模块" align="center" prop="title" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="操作类型" align="center" prop="businessType">
|
<el-table-column label="操作类型" align="center" prop="businessType">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<dict-tag :options="dict.type.sys_oper_type" :value="scope.row.businessType"/>
|
<dict-tag :options="dict.type.sys_oper_type" :value="scope.row.businessType"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="请求方式" align="center" prop="requestMethod" />
|
<el-table-column label="操作人员" align="center" prop="operName" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
|
||||||
<el-table-column label="操作人员" align="center" prop="operName" width="100" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
|
|
||||||
<el-table-column label="操作地址" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
|
<el-table-column label="操作地址" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="操作地点" align="center" prop="operLocation" :show-overflow-tooltip="true" />
|
<el-table-column label="操作地点" align="center" prop="operLocation" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="操作状态" align="center" prop="status">
|
<el-table-column label="操作状态" align="center" prop="status">
|
||||||
@@ -119,11 +119,16 @@
|
|||||||
<dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/>
|
<dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作日期" align="center" prop="operTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
|
<el-table-column label="操作日期" align="center" prop="operTime" width="160" sortable="custom" :sort-orders="['descending', 'ascending']">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ parseTime(scope.row.operTime) }}</span>
|
<span>{{ parseTime(scope.row.operTime) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="消耗时间" align="center" prop="costTime" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ scope.row.costTime }}毫秒</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<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 slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button
|
||||||
@@ -168,13 +173,16 @@
|
|||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
|
<el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="6">
|
||||||
<el-form-item label="操作状态:">
|
<el-form-item label="操作状态:">
|
||||||
<div v-if="form.status === 0">正常</div>
|
<div v-if="form.status === 0">正常</div>
|
||||||
<div v-else-if="form.status === 1">失败</div>
|
<div v-else-if="form.status === 1">失败</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="8">
|
||||||
|
<el-form-item label="消耗时间:">{{ form.costTime }}毫秒</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="10">
|
||||||
<el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>
|
<el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12" class="card-box">
|
<el-col :span="12" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header"><span>CPU</span></div>
|
<div slot="header"><span><i class="el-icon-cpu"></i> CPU</span></div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
<el-col :span="12" class="card-box">
|
<el-col :span="12" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header"><span>内存</span></div>
|
<div slot="header"><span><i class="el-icon-tickets"></i> 内存</span></div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
<el-col :span="24" class="card-box">
|
<el-col :span="24" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<span>服务器信息</span>
|
<span><i class="el-icon-monitor"></i> 服务器信息</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
<el-col :span="24" class="card-box">
|
<el-col :span="24" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<span>Java虚拟机信息</span>
|
<span><i class="el-icon-coffee-cup"></i> Java虚拟机信息</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%;table-layout:fixed;">
|
<table cellspacing="0" style="width: 100%;table-layout:fixed;">
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
<el-col :span="24" class="card-box">
|
<el-col :span="24" class="card-box">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<span>磁盘状态</span>
|
<span><i class="el-icon-receiving"></i> 磁盘状态</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
@@ -204,4 +204,4 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<!-- 底部 -->
|
<!-- 底部 -->
|
||||||
<div class="el-register-footer">
|
<div class="el-register-footer">
|
||||||
<span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
|
<span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -107,7 +107,7 @@
|
|||||||
<el-table-column label="参数主键" align="center" prop="configId" />
|
<el-table-column label="参数主键" align="center" prop="configId" />
|
||||||
<el-table-column label="参数名称" align="center" prop="configName" :show-overflow-tooltip="true" />
|
<el-table-column label="参数名称" align="center" prop="configName" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="参数键名" align="center" prop="configKey" :show-overflow-tooltip="true" />
|
<el-table-column label="参数键名" align="center" prop="configKey" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="参数键值" align="center" prop="configValue" />
|
<el-table-column label="参数键值" align="center" prop="configValue" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="系统内置" align="center" prop="configType">
|
<el-table-column label="系统内置" align="center" prop="configType">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<dict-tag :options="dict.type.sys_yes_no" :value="scope.row.configType"/>
|
<dict-tag :options="dict.type.sys_yes_no" :value="scope.row.configType"/>
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<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 slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-edit"
|
icon="el-icon-edit"
|
||||||
@@ -134,14 +134,13 @@
|
|||||||
trigger="click"
|
trigger="click"
|
||||||
@show="$refs['iconSelect'].reset()"
|
@show="$refs['iconSelect'].reset()"
|
||||||
>
|
>
|
||||||
<IconSelect ref="iconSelect" @selected="selected" />
|
<IconSelect ref="iconSelect" @selected="selected" :active-icon="form.icon" />
|
||||||
<el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly>
|
<el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly>
|
||||||
<svg-icon
|
<svg-icon
|
||||||
v-if="form.icon"
|
v-if="form.icon"
|
||||||
slot="prefix"
|
slot="prefix"
|
||||||
:icon-class="form.icon"
|
:icon-class="form.icon"
|
||||||
class="el-input__icon"
|
style="width: 25px;"
|
||||||
style="height: 32px;width: 16px;"
|
|
||||||
/>
|
/>
|
||||||
<i v-else slot="prefix" class="el-icon-search el-input__icon" />
|
<i v-else slot="prefix" class="el-icon-search el-input__icon" />
|
||||||
</el-input>
|
</el-input>
|
||||||
|
|||||||
@@ -371,20 +371,6 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang='scss'>
|
<style lang='scss'>
|
||||||
body, html{
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
background: #fff;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;
|
|
||||||
}
|
|
||||||
|
|
||||||
input, textarea{
|
|
||||||
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor-tabs{
|
.editor-tabs{
|
||||||
background: #121315;
|
background: #121315;
|
||||||
.el-tabs__header{
|
.el-tabs__header{
|
||||||
@@ -779,5 +765,4 @@ $lighterBlue: #409EFF;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user