Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8988d0b4ab | |||
| ceefa20aa2 | |||
| 89e1f2a53f | |||
| 6800a12014 | |||
| e8f63b2994 | |||
| ecfe7006e2 | |||
| 9e387dc447 | |||
| 231bbf6928 | |||
| d6eac2dc8d | |||
| b368ad764f | |||
| ffd5f0ce5d | |||
| a50beae599 | |||
| cf7f51a633 | |||
| 4d46f4c1b5 | |||
| a941c1b488 | |||
| d6b6151aea | |||
| fbc071a573 | |||
| 6cfff90b4a | |||
| 474cca921e | |||
| 1657e06be6 | |||
| c01eeb8521 | |||
| f90899d72a | |||
| 7e78a9167f | |||
| 563e11d9c1 | |||
| ef92ad4d8c | |||
| d8b006c15f | |||
| 0e2b97a886 | |||
| 1c7a5faae8 | |||
| 23868c4fad | |||
| 3b2669d148 | |||
| 1147ea5f8a | |||
| a1bf5aaf8e | |||
| 2797c1eb3a | |||
| 1791d7cf40 | |||
| 01861f0aae | |||
| a69cc94f35 | |||
| c666faed66 | |||
| 6072239a40 | |||
| a3b86d6f6d | |||
| fd831d5a90 | |||
| e83412b9a5 | |||
| 90ac416e02 | |||
| 5b63f0cab9 | |||
| 8f145bba3a | |||
| 6bb166b89f | |||
| 823e95667e | |||
| 566053da0c | |||
| 0ef007240d | |||
| 0a75dcdd85 | |||
| 4c2626ffec | |||
| 082b19e33a | |||
| b779cf053d | |||
| 212012dc62 | |||
| 7de2cf77b4 | |||
| 2b9d46439f | |||
| 79265d59b7 | |||
| 093ba5b389 | |||
| 3807b11290 | |||
| c9f25cb34e | |||
| 203b54e5aa | |||
| 403f5c5dcf | |||
| c6d0b9a9ae | |||
| 08df2c93a9 | |||
| fbbdd94999 | |||
| 0cae7d0058 | |||
| b0965653bf | |||
| e472f62523 |
@ -8,7 +8,8 @@
|
||||
* 提供了一个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)
|
||||
* 感谢[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin),[eladmin-web](https://gitee.com/elunez/eladmin-web?_from=gitee_search)。
|
||||
* 阿里云优惠券:[点我进入](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)
|
||||
* 阿里云折扣场:[点我进入](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)
|
||||
|
||||
## 内置功能
|
||||
|
||||
|
||||
19
pom.xml
@ -6,30 +6,29 @@
|
||||
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.3.0</version>
|
||||
|
||||
<name>ruoyi</name>
|
||||
<url>http://www.ruoyi.vip</url>
|
||||
<description>若依管理系统</description>
|
||||
|
||||
<properties>
|
||||
<ruoyi.version>3.2.0</ruoyi.version>
|
||||
<ruoyi.version>3.3.0</ruoyi.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<mybatis.boot.version>1.3.2</mybatis.boot.version>
|
||||
<druid.version>1.2.1</druid.version>
|
||||
<bitwalker.version>1.19</bitwalker.version>
|
||||
<druid.version>1.2.2</druid.version>
|
||||
<bitwalker.version>1.21</bitwalker.version>
|
||||
<swagger.version>2.9.2</swagger.version>
|
||||
<kaptcha.version>2.3.2</kaptcha.version>
|
||||
<pagehelper.boot.version>1.2.5</pagehelper.boot.version>
|
||||
<pagehelper.boot.version>1.3.0</pagehelper.boot.version>
|
||||
<fastjson.version>1.2.74</fastjson.version>
|
||||
<oshi.version>5.2.5</oshi.version>
|
||||
<jna.version>5.5.0</jna.version>
|
||||
<oshi.version>5.3.6</oshi.version>
|
||||
<jna.version>5.6.0</jna.version>
|
||||
<commons.io.version>2.5</commons.io.version>
|
||||
<commons.fileupload.version>1.3.3</commons.fileupload.version>
|
||||
<poi.version>3.17</poi.version>
|
||||
<poi.version>4.1.2</poi.version>
|
||||
<velocity.version>1.7</velocity.version>
|
||||
<jwt.version>0.9.1</jwt.version>
|
||||
</properties>
|
||||
@ -42,7 +41,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>2.1.17.RELEASE</version>
|
||||
<version>2.1.18.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@ -5,6 +5,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@ -41,17 +42,15 @@ public class CommonController
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!FileUtils.isValidFilename(fileName))
|
||||
if (!FileUtils.checkAllowDownload(fileName))
|
||||
{
|
||||
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
|
||||
}
|
||||
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
|
||||
String filePath = RuoYiConfig.getDownloadPath() + fileName;
|
||||
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("multipart/form-data");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
FileUtils.setAttachmentResponseHeader(response, realFileName);
|
||||
FileUtils.writeBytes(filePath, response.getOutputStream());
|
||||
if (delete)
|
||||
{
|
||||
@ -92,18 +91,28 @@ public class CommonController
|
||||
* 本地资源通用下载
|
||||
*/
|
||||
@GetMapping("/common/download/resource")
|
||||
public void resourceDownload(String name, HttpServletRequest request, HttpServletResponse response) throws Exception
|
||||
public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
|
||||
throws Exception
|
||||
{
|
||||
// 本地资源路径
|
||||
String localPath = RuoYiConfig.getProfile();
|
||||
// 数据库资源地址
|
||||
String downloadPath = localPath + StringUtils.substringAfter(name, Constants.RESOURCE_PREFIX);
|
||||
// 下载名称
|
||||
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("multipart/form-data");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;fileName=" + FileUtils.setFileDownloadHeader(request, downloadName));
|
||||
FileUtils.writeBytes(downloadPath, response.getOutputStream());
|
||||
try
|
||||
{
|
||||
if (!FileUtils.checkAllowDownload(resource))
|
||||
{
|
||||
throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
|
||||
}
|
||||
// 本地资源路径
|
||||
String localPath = RuoYiConfig.getProfile();
|
||||
// 数据库资源地址
|
||||
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
|
||||
// 下载名称
|
||||
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
FileUtils.setAttachmentResponseHeader(response, downloadName);
|
||||
FileUtils.writeBytes(downloadPath, response.getOutputStream());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("下载文件失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
package com.ruoyi.web.controller.monitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisCallback;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 缓存监控
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/monitor/cache")
|
||||
public class CacheController
|
||||
{
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
|
||||
@GetMapping()
|
||||
public AjaxResult getInfo() throws Exception
|
||||
{
|
||||
Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
|
||||
Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
|
||||
Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
|
||||
|
||||
Map<String, Object> result = new HashMap<>(3);
|
||||
result.put("info", info);
|
||||
result.put("dbSize", dbSize);
|
||||
|
||||
List<Map<String, String>> pieList = new ArrayList<>();
|
||||
commandStats.stringPropertyNames().forEach(key -> {
|
||||
Map<String, String> data = new HashMap<>(2);
|
||||
String property = commandStats.getProperty(key);
|
||||
data.put("name", StringUtils.removeStart(key, "cmdstat_"));
|
||||
data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
|
||||
pieList.add(data);
|
||||
});
|
||||
result.put("commandStats", pieList);
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,6 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.framework.web.domain.Server;
|
||||
|
||||
@ -15,7 +14,7 @@ import com.ruoyi.framework.web.domain.Server;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/monitor/server")
|
||||
public class ServerController extends BaseController
|
||||
public class ServerController
|
||||
{
|
||||
@PreAuthorize("@ss.hasPermi('monitor:server:list')")
|
||||
@GetMapping()
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@ -19,6 +20,7 @@ import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.system.service.ISysDictDataService;
|
||||
import com.ruoyi.system.service.ISysDictTypeService;
|
||||
@ -73,7 +75,12 @@ public class SysDictDataController extends BaseController
|
||||
@GetMapping(value = "/type/{dictType}")
|
||||
public AjaxResult dictType(@PathVariable String dictType)
|
||||
{
|
||||
return AjaxResult.success(dictTypeService.selectDictDataByType(dictType));
|
||||
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
|
||||
if (StringUtils.isNull(data))
|
||||
{
|
||||
data = new ArrayList<SysDictData>();
|
||||
}
|
||||
return AjaxResult.success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -127,11 +127,13 @@ public class SysUserController extends BaseController
|
||||
{
|
||||
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
else if (StringUtils.isNotEmpty(user.getPhonenumber())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
{
|
||||
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
else if (StringUtils.isNotEmpty(user.getEmail())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
{
|
||||
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||
}
|
||||
@ -149,11 +151,13 @@ public class SysUserController extends BaseController
|
||||
public AjaxResult edit(@Validated @RequestBody SysUser user)
|
||||
{
|
||||
userService.checkUserAllowed(user);
|
||||
if (UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
if (StringUtils.isNotEmpty(user.getPhonenumber())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
|
||||
{
|
||||
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
else if (StringUtils.isNotEmpty(user.getEmail())
|
||||
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
|
||||
{
|
||||
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
|
||||
}
|
||||
@ -175,7 +179,7 @@ public class SysUserController extends BaseController
|
||||
/**
|
||||
* 重置密码
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:user:edit')")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
|
||||
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/resetPwd")
|
||||
public AjaxResult resetPwd(@RequestBody SysUser user)
|
||||
|
||||
@ -3,7 +3,7 @@ ruoyi:
|
||||
# 名称
|
||||
name: RuoYi
|
||||
# 版本
|
||||
version: 3.2.0
|
||||
version: 3.3.0
|
||||
# 版权年份
|
||||
copyrightYear: 2020
|
||||
# 实例演示开关
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -105,6 +105,27 @@ public @interface Excel
|
||||
*/
|
||||
public boolean isStatistics() default false;
|
||||
|
||||
/**
|
||||
* 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右)
|
||||
*/
|
||||
Align align() default Align.AUTO;
|
||||
|
||||
public enum Align
|
||||
{
|
||||
AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
|
||||
private final int value;
|
||||
|
||||
Align(int value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int value()
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
|
||||
*/
|
||||
|
||||
@ -37,7 +37,7 @@ public class GenConstants
|
||||
|
||||
/** 数据库数字类型 */
|
||||
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
|
||||
"bigint", "float", "float", "double", "decimal" };
|
||||
"bit", "bigint", "float", "double", "decimal" };
|
||||
|
||||
/** 页面不需要编辑字段 */
|
||||
public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
|
||||
@ -74,6 +74,9 @@ public class GenConstants
|
||||
/** 日期控件 */
|
||||
public static final String HTML_DATETIME = "datetime";
|
||||
|
||||
/** 上传控件 */
|
||||
public static final String HTML_UPLOAD_IMAGE = "uploadImage";
|
||||
|
||||
/** 富文本控件 */
|
||||
public static final String HTML_EDITOR = "editor";
|
||||
|
||||
|
||||
@ -54,6 +54,9 @@ public class UserConstants
|
||||
/** Layout组件标识 */
|
||||
public final static String LAYOUT = "Layout";
|
||||
|
||||
/** ParentView组件标识 */
|
||||
public final static String PARENT_VIEW = "ParentView";
|
||||
|
||||
/** 校验返回结果码 */
|
||||
public final static String UNIQUE = "0";
|
||||
public final static String NOT_UNIQUE = "1";
|
||||
|
||||
@ -5,7 +5,6 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* Entity基类
|
||||
@ -36,14 +35,6 @@ public class BaseEntity implements Serializable
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
/** 开始时间 */
|
||||
@JsonIgnore
|
||||
private String beginTime;
|
||||
|
||||
/** 结束时间 */
|
||||
@JsonIgnore
|
||||
private String endTime;
|
||||
|
||||
/** 请求参数 */
|
||||
private Map<String, Object> params;
|
||||
|
||||
@ -107,26 +98,6 @@ public class BaseEntity implements Serializable
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getBeginTime()
|
||||
{
|
||||
return beginTime;
|
||||
}
|
||||
|
||||
public void setBeginTime(String beginTime)
|
||||
{
|
||||
this.beginTime = beginTime;
|
||||
}
|
||||
|
||||
public String getEndTime()
|
||||
{
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(String endTime)
|
||||
{
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public Map<String, Object> getParams()
|
||||
{
|
||||
if (params == null)
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
package com.ruoyi.common.core.redis;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.BoundSetOperations;
|
||||
import org.springframework.data.redis.core.HashOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
@ -136,10 +138,15 @@ public class RedisCache
|
||||
* @param dataSet 缓存的数据
|
||||
* @return 缓存数据的对象
|
||||
*/
|
||||
public <T> long setCacheSet(final String key, final Set<T> dataSet)
|
||||
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
|
||||
{
|
||||
Long count = redisTemplate.opsForSet().add(key, dataSet);
|
||||
return count == null ? 0 : count;
|
||||
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
|
||||
Iterator<T> it = dataSet.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
setOperation.add(it.next());
|
||||
}
|
||||
return setOperation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -66,7 +66,7 @@ public class CharsetKit
|
||||
|
||||
if (null == destCharset)
|
||||
{
|
||||
srcCharset = StandardCharsets.UTF_8;
|
||||
destCharset = StandardCharsets.UTF_8;
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
package com.ruoyi.common.utils.file;
|
||||
|
||||
import java.io.File;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* 文件类型工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class FileTypeUtils
|
||||
{
|
||||
/**
|
||||
* 获取文件类型
|
||||
* <p>
|
||||
* 例如: ruoyi.txt, 返回: txt
|
||||
*
|
||||
* @param file 文件名
|
||||
* @return 后缀(不含".")
|
||||
*/
|
||||
public static String getFileType(File file)
|
||||
{
|
||||
if (null == file)
|
||||
{
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return getFileType(file.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件类型
|
||||
* <p>
|
||||
* 例如: ruoyi.txt, 返回: txt
|
||||
*
|
||||
* @param fileName 文件名
|
||||
* @return 后缀(不含".")
|
||||
*/
|
||||
public static String getFileType(String fileName)
|
||||
{
|
||||
int separatorIndex = fileName.lastIndexOf(".");
|
||||
if (separatorIndex < 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return fileName.substring(separatorIndex + 1).toLowerCase();
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,11 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 文件处理工具类
|
||||
@ -104,6 +108,30 @@ public class FileUtils extends org.apache.commons.io.FileUtils
|
||||
return filename.matches(FILENAME_PATTERN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否可下载
|
||||
*
|
||||
* @param resource 需要下载的文件
|
||||
* @return true 正常 false 非法
|
||||
*/
|
||||
public static boolean checkAllowDownload(String resource)
|
||||
{
|
||||
// 禁止目录上跳级别
|
||||
if (StringUtils.contains(resource, ".."))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查允许下载的文件规则
|
||||
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 不在允许下载的文件规则
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件名重新编码
|
||||
*
|
||||
@ -111,8 +139,7 @@ public class FileUtils extends org.apache.commons.io.FileUtils
|
||||
* @param fileName 文件名
|
||||
* @return 编码后的文件名
|
||||
*/
|
||||
public static String setFileDownloadHeader(HttpServletRequest request, String fileName)
|
||||
throws UnsupportedEncodingException
|
||||
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
|
||||
{
|
||||
final String agent = request.getHeader("USER-AGENT");
|
||||
String filename = fileName;
|
||||
@ -139,4 +166,38 @@ public class FileUtils extends org.apache.commons.io.FileUtils
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件名重新编码
|
||||
*
|
||||
* @param response 响应对象
|
||||
* @param realFileName 真实文件名
|
||||
* @return
|
||||
*/
|
||||
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
|
||||
{
|
||||
String percentEncodedFileName = percentEncode(realFileName);
|
||||
|
||||
StringBuilder contentDispositionValue = new StringBuilder();
|
||||
contentDispositionValue.append("attachment; filename=")
|
||||
.append(percentEncodedFileName)
|
||||
.append(";")
|
||||
.append("filename*=")
|
||||
.append("utf-8''")
|
||||
.append(percentEncodedFileName);
|
||||
|
||||
response.setHeader("Content-disposition", contentDispositionValue.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 百分号编码工具方法
|
||||
*
|
||||
* @param s 需要百分号编码的字符串
|
||||
* @return 百分号编码后的字符串
|
||||
*/
|
||||
public static String percentEncode(String s) throws UnsupportedEncodingException
|
||||
{
|
||||
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
|
||||
return encode.replaceAll("\\+", "%20");
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,6 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
@ -274,6 +273,10 @@ public class ExcelUtil<T>
|
||||
val = DateUtil.getJavaDate((Double) val);
|
||||
}
|
||||
}
|
||||
else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
|
||||
{
|
||||
val = Convert.toBool(val, false);
|
||||
}
|
||||
if (StringUtils.isNotNull(fieldType))
|
||||
{
|
||||
Excel attr = field.getAnnotation(Excel.class);
|
||||
@ -469,6 +472,21 @@ public class ExcelUtil<T>
|
||||
style.setFont(totalFont);
|
||||
styles.put("total", style);
|
||||
|
||||
style = wb.createCellStyle();
|
||||
style.cloneStyleFrom(styles.get("data"));
|
||||
style.setAlignment(HorizontalAlignment.LEFT);
|
||||
styles.put("data1", style);
|
||||
|
||||
style = wb.createCellStyle();
|
||||
style.cloneStyleFrom(styles.get("data"));
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
styles.put("data2", style);
|
||||
|
||||
style = wb.createCellStyle();
|
||||
style.cloneStyleFrom(styles.get("data"));
|
||||
style.setAlignment(HorizontalAlignment.RIGHT);
|
||||
styles.put("data3", style);
|
||||
|
||||
return styles;
|
||||
}
|
||||
|
||||
@ -497,12 +515,10 @@ public class ExcelUtil<T>
|
||||
{
|
||||
if (ColumnType.STRING == attr.cellType())
|
||||
{
|
||||
cell.setCellType(CellType.STRING);
|
||||
cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix());
|
||||
}
|
||||
else if (ColumnType.NUMERIC == attr.cellType())
|
||||
{
|
||||
cell.setCellType(CellType.NUMERIC);
|
||||
cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
|
||||
}
|
||||
}
|
||||
@ -551,7 +567,8 @@ public class ExcelUtil<T>
|
||||
{
|
||||
// 创建cell
|
||||
cell = row.createCell(column);
|
||||
cell.setCellStyle(styles.get("data"));
|
||||
int align = attr.align().value();
|
||||
cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : "")));
|
||||
|
||||
// 用于读取对象中的属性
|
||||
Object value = getTargetValue(vo, field, attr);
|
||||
@ -860,7 +877,7 @@ public class ExcelUtil<T>
|
||||
*/
|
||||
private Object getValue(Object o, String name) throws Exception
|
||||
{
|
||||
if (StringUtils.isNotEmpty(name))
|
||||
if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
|
||||
{
|
||||
Class<?> clazz = o.getClass();
|
||||
Field field = clazz.getDeclaredField(name);
|
||||
@ -960,10 +977,10 @@ public class ExcelUtil<T>
|
||||
Cell cell = row.getCell(column);
|
||||
if (StringUtils.isNotNull(cell))
|
||||
{
|
||||
if (cell.getCellTypeEnum() == CellType.NUMERIC || cell.getCellTypeEnum() == CellType.FORMULA)
|
||||
if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
|
||||
{
|
||||
val = cell.getNumericCellValue();
|
||||
if (HSSFDateUtil.isCellDateFormatted(cell))
|
||||
if (DateUtil.isCellDateFormatted(cell))
|
||||
{
|
||||
val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换
|
||||
}
|
||||
@ -979,15 +996,15 @@ public class ExcelUtil<T>
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cell.getCellTypeEnum() == CellType.STRING)
|
||||
else if (cell.getCellType() == CellType.STRING)
|
||||
{
|
||||
val = cell.getStringCellValue();
|
||||
}
|
||||
else if (cell.getCellTypeEnum() == CellType.BOOLEAN)
|
||||
else if (cell.getCellType() == CellType.BOOLEAN)
|
||||
{
|
||||
val = cell.getBooleanCellValue();
|
||||
}
|
||||
else if (cell.getCellTypeEnum() == CellType.ERROR)
|
||||
else if (cell.getCellType() == CellType.ERROR)
|
||||
{
|
||||
val = cell.getErrorCellValue();
|
||||
}
|
||||
|
||||
@ -204,6 +204,10 @@ public class ReflectUtils
|
||||
args[i] = DateUtil.getJavaDate((Double) args[i]);
|
||||
}
|
||||
}
|
||||
else if (cs[i] == boolean.class || cs[i] == Boolean.class)
|
||||
{
|
||||
args[i] = Convert.toBool(args[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (E) method.invoke(obj, args);
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.ruoyi.framework.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@ -210,8 +212,31 @@ public class LogAspect
|
||||
* @param o 对象信息。
|
||||
* @return 如果是需要过滤的对象,则返回true;否则返回false。
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public boolean isFilterObject(final Object o)
|
||||
{
|
||||
Class<?> clazz = o.getClass();
|
||||
if (clazz.isArray())
|
||||
{
|
||||
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
|
||||
}
|
||||
else if (Collection.class.isAssignableFrom(clazz))
|
||||
{
|
||||
Collection collection = (Collection) o;
|
||||
for (Iterator iter = collection.iterator(); iter.hasNext();)
|
||||
{
|
||||
return iter.next() instanceof MultipartFile;
|
||||
}
|
||||
}
|
||||
else if (Map.class.isAssignableFrom(clazz))
|
||||
{
|
||||
Map map = (Map) o;
|
||||
for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
return entry.getValue() instanceof MultipartFile;
|
||||
}
|
||||
}
|
||||
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.ruoyi.framework.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import javax.sql.DataSource;
|
||||
@ -21,6 +22,7 @@ import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* Mybatis支持*匹配扫描包
|
||||
@ -89,6 +91,28 @@ public class MyBatisConfig
|
||||
return typeAliasesPackage;
|
||||
}
|
||||
|
||||
public Resource[] resolveMapperLocations(String[] mapperLocations)
|
||||
{
|
||||
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
if (mapperLocations != null)
|
||||
{
|
||||
for (String mapperLocation : mapperLocations)
|
||||
{
|
||||
try
|
||||
{
|
||||
Resource[] mappers = resourceResolver.getResources(mapperLocation);
|
||||
resources.addAll(Arrays.asList(mappers));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return resources.toArray(new Resource[resources.size()]);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
|
||||
{
|
||||
@ -101,7 +125,7 @@ public class MyBatisConfig
|
||||
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
|
||||
sessionFactory.setDataSource(dataSource);
|
||||
sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
|
||||
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
|
||||
sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
|
||||
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
|
||||
return sessionFactory.getObject();
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ public class PermissionService
|
||||
for (SysRole sysRole : loginUser.getUser().getRoles())
|
||||
{
|
||||
String roleKey = sysRole.getRoleKey();
|
||||
if (SUPER_ADMIN.contains(roleKey) || roleKey.contains(StringUtils.trim(role)))
|
||||
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ public class GenTableColumn extends BaseEntity
|
||||
/** 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) */
|
||||
private String queryType;
|
||||
|
||||
/** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、editor富文本控件) */
|
||||
/** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、upload上传控件、editor富文本控件) */
|
||||
private String htmlType;
|
||||
|
||||
/** 字典类型 */
|
||||
|
||||
@ -111,6 +111,11 @@ public class GenUtils
|
||||
{
|
||||
column.setHtmlType(GenConstants.HTML_SELECT);
|
||||
}
|
||||
// 文件字段设置上传控件
|
||||
else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
|
||||
{
|
||||
column.setHtmlType(GenConstants.HTML_UPLOAD_IMAGE);
|
||||
}
|
||||
// 内容字段设置富文本控件
|
||||
else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
|
||||
{
|
||||
|
||||
@ -64,11 +64,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="tableComment != null and tableComment != ''">
|
||||
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
@ -84,11 +84,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="tableComment != null and tableComment != ''">
|
||||
AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
</select>
|
||||
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
-- 菜单 SQL
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
|
||||
values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', sysdate(), '', null, '${functionName}菜单');
|
||||
|
||||
-- 按钮父菜单ID
|
||||
SELECT @parentId := LAST_INSERT_ID();
|
||||
|
||||
-- 按钮 SQL
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}查询', @parentId, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
|
||||
values('${functionName}查询', @parentId, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', sysdate(), '', null, '');
|
||||
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}新增', @parentId, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
|
||||
values('${functionName}新增', @parentId, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', sysdate(), '', null, '');
|
||||
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}修改', @parentId, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
|
||||
values('${functionName}修改', @parentId, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', sysdate(), '', null, '');
|
||||
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}删除', @parentId, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
|
||||
values('${functionName}删除', @parentId, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', sysdate(), '', null, '');
|
||||
|
||||
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
|
||||
values('${functionName}导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
|
||||
values('${functionName}导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', sysdate(), '', null, '');
|
||||
@ -139,6 +139,10 @@
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "uploadImage")
|
||||
<el-form-item label="${comment}">
|
||||
<uploadImage v-model="form.${field}"/>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "editor")
|
||||
<el-form-item label="${comment}">
|
||||
<editor v-model="form.${field}" :min-height="192"/>
|
||||
@ -226,6 +230,12 @@ import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${Busin
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage")
|
||||
import UploadImage from '@/components/UploadImage';
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
|
||||
import Editor from '@/components/Editor';
|
||||
#break
|
||||
@ -236,6 +246,12 @@ export default {
|
||||
name: "${BusinessName}",
|
||||
components: {
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage")
|
||||
UploadImage,
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
|
||||
Editor,
|
||||
#break
|
||||
@ -420,19 +436,15 @@ export default {
|
||||
#end
|
||||
if (this.form.${pkColumn.javaField} != null) {
|
||||
update${BusinessName}(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
add${BusinessName}(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -449,7 +461,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -168,6 +168,10 @@
|
||||
<el-form-item label="${comment}" prop="${field}">
|
||||
<el-input v-model="form.${field}" placeholder="请输入${comment}" />
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "uploadImage")
|
||||
<el-form-item label="${comment}">
|
||||
<uploadImage v-model="form.${field}"/>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "editor")
|
||||
<el-form-item label="${comment}">
|
||||
<editor v-model="form.${field}" :min-height="192"/>
|
||||
@ -253,6 +257,12 @@
|
||||
<script>
|
||||
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}";
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage")
|
||||
import UploadImage from '@/components/UploadImage';
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
|
||||
import Editor from '@/components/Editor';
|
||||
#break
|
||||
@ -261,12 +271,20 @@ import Editor from '@/components/Editor';
|
||||
|
||||
export default {
|
||||
name: "${BusinessName}",
|
||||
components: {
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
|
||||
components: { Editor },
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage")
|
||||
UploadImage,
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
|
||||
Editor,
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
@ -436,19 +454,15 @@ export default {
|
||||
#end
|
||||
if (this.form.${pkColumn.javaField} != null) {
|
||||
update${BusinessName}(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
add${BusinessName}(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -466,7 +480,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -479,7 +493,7 @@ export default {
|
||||
return export${BusinessName}(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -35,11 +35,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="invokeTarget != null and invokeTarget != ''">
|
||||
AND invoke_target like concat('%', #{invokeTarget}, '%')
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -26,6 +26,14 @@ public interface SysRoleMenuMapper
|
||||
*/
|
||||
public int deleteRoleMenuByRoleId(Long roleId);
|
||||
|
||||
/**
|
||||
* 批量删除角色菜单关联信息
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRoleMenu(Long[] ids);
|
||||
|
||||
/**
|
||||
* 批量新增角色菜单信息
|
||||
*
|
||||
|
||||
@ -364,6 +364,10 @@ public class SysMenuServiceImpl implements ISysMenuService
|
||||
{
|
||||
component = menu.getComponent();
|
||||
}
|
||||
else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))
|
||||
{
|
||||
component = UserConstants.PARENT_VIEW;
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
@ -379,6 +383,17 @@ public class SysMenuServiceImpl implements ISysMenuService
|
||||
&& menu.getIsFrame().equals(UserConstants.NO_FRAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为parent_view组件
|
||||
*
|
||||
* @param menu 菜单信息
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isParentView(SysMenu menu)
|
||||
{
|
||||
return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据父节点的ID获取所有子节点
|
||||
*
|
||||
|
||||
@ -290,8 +290,13 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteRoleById(Long roleId)
|
||||
{
|
||||
// 删除角色与菜单关联
|
||||
roleMenuMapper.deleteRoleMenuByRoleId(roleId);
|
||||
// 删除角色与部门关联
|
||||
roleDeptMapper.deleteRoleDeptByRoleId(roleId);
|
||||
return roleMapper.deleteRoleById(roleId);
|
||||
}
|
||||
|
||||
@ -302,6 +307,7 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteRoleByIds(Long[] roleIds)
|
||||
{
|
||||
for (Long roleId : roleIds)
|
||||
@ -313,6 +319,10 @@ public class SysRoleServiceImpl implements ISysRoleService
|
||||
throw new CustomException(String.format("%1$s已分配,不能删除", role.getRoleName()));
|
||||
}
|
||||
}
|
||||
// 删除角色与菜单关联
|
||||
roleMenuMapper.deleteRoleMenu(roleIds);
|
||||
// 删除角色与部门关联
|
||||
roleDeptMapper.deleteRoleDept(roleIds);
|
||||
return roleMapper.deleteRoleByIds(roleIds);
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,6 +363,7 @@ public class SysUserServiceImpl implements ISysUserService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteUserById(Long userId)
|
||||
{
|
||||
// 删除用户与角色关联
|
||||
@ -379,12 +380,17 @@ public class SysUserServiceImpl implements ISysUserService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteUserByIds(Long[] userIds)
|
||||
{
|
||||
for (Long userId : userIds)
|
||||
{
|
||||
checkUserAllowed(new SysUser(userId));
|
||||
}
|
||||
// 删除用户与角色关联
|
||||
userRoleMapper.deleteUserRole(userIds);
|
||||
// 删除用户与岗位关联
|
||||
userPostMapper.deleteUserPost(userIds);
|
||||
return userMapper.deleteUserByIds(userIds);
|
||||
}
|
||||
|
||||
|
||||
@ -50,11 +50,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="configKey != null and configKey != ''">
|
||||
AND config_key like concat('%', #{configKey}, '%')
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
@ -32,11 +32,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="dictType != null and dictType != ''">
|
||||
AND dict_type like concat('%', #{dictType}, '%')
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
@ -33,11 +33,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="userName != null and userName != ''">
|
||||
AND user_name like concat('%', #{userName}, '%')
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(login_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(login_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(login_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(login_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
</where>
|
||||
order by info_id desc
|
||||
|
||||
@ -54,11 +54,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="operName != null and operName != ''">
|
||||
AND oper_name like concat('%', #{operName}, '%')
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(oper_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(oper_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(oper_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(oper_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
</where>
|
||||
order by oper_id desc
|
||||
|
||||
@ -42,11 +42,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="roleKey != null and roleKey != ''">
|
||||
AND r.role_key like concat('%', #{roleKey}, '%')
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(r.create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
and date_format(r.create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(r.create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
and date_format(r.create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
<!-- 数据范围过滤 -->
|
||||
${params.dataScope}
|
||||
|
||||
@ -17,6 +17,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
delete from sys_role_menu where role_id=#{roleId}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteRoleMenu" parameterType="Long">
|
||||
delete from sys_role_menu where role_id in
|
||||
<foreach collection="array" item="roleId" open="(" separator="," close=")">
|
||||
#{roleId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<insert id="batchRoleMenu">
|
||||
insert into sys_role_menu(role_id, menu_id) values
|
||||
<foreach item="item" index="index" collection="list" separator=",">
|
||||
|
||||
@ -68,11 +68,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="phonenumber != null and phonenumber != ''">
|
||||
AND u.phonenumber like concat('%', #{phonenumber}, '%')
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(u.create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
|
||||
AND date_format(u.create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(u.create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
|
||||
AND date_format(u.create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="deptId != null and deptId != 0">
|
||||
AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) ))
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ruoyi",
|
||||
"version": "3.2.0",
|
||||
"version": "3.3.0",
|
||||
"description": "若依管理系统",
|
||||
"author": "若依",
|
||||
"license": "MIT",
|
||||
@ -9,11 +9,7 @@
|
||||
"build:prod": "vue-cli-service build",
|
||||
"build:stage": "vue-cli-service build --mode staging",
|
||||
"preview": "node build/index.js --preview",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"test:unit": "jest --clearCache && vue-cli-service test:unit",
|
||||
"test:ci": "npm run lint && npm run test:unit",
|
||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
|
||||
"new": "plop"
|
||||
"lint": "eslint --ext .js,.vue src"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
@ -41,59 +37,45 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@riophae/vue-treeselect": "0.4.0",
|
||||
"axios": "0.18.1",
|
||||
"clipboard": "2.0.4",
|
||||
"core-js": "3.6.5",
|
||||
"echarts": "4.2.1",
|
||||
"element-ui": "2.13.2",
|
||||
"file-saver": "2.0.1",
|
||||
"js-beautify": "1.10.2",
|
||||
"fuse.js": "3.4.4",
|
||||
"js-cookie": "2.2.0",
|
||||
"axios": "0.21.0",
|
||||
"clipboard": "2.0.6",
|
||||
"core-js": "3.8.1",
|
||||
"echarts": "4.9.0",
|
||||
"element-ui": "2.14.1",
|
||||
"file-saver": "2.0.4",
|
||||
"fuse.js": "6.4.3",
|
||||
"highlight.js": "10.4.1",
|
||||
"js-beautify": "1.13.0",
|
||||
"js-cookie": "2.2.1",
|
||||
"jsencrypt": "3.0.0-rc.1",
|
||||
"normalize.css": "7.0.0",
|
||||
"nprogress": "0.2.0",
|
||||
"path-to-regexp": "2.4.0",
|
||||
"screenfull": "4.2.0",
|
||||
"sortablejs": "1.8.4",
|
||||
"vue": "2.6.10",
|
||||
"vue-count-to": "1.0.13",
|
||||
"path-to-regexp": "6.2.0",
|
||||
"quill": "1.3.7",
|
||||
"vue-cropper": "0.4.9",
|
||||
"vue-router": "3.0.2",
|
||||
"vue-splitpane": "1.0.4",
|
||||
"vuedraggable": "2.20.0",
|
||||
"vuex": "3.1.0"
|
||||
"screenfull": "5.0.2",
|
||||
"sortablejs": "1.10.2",
|
||||
"vue": "2.6.12",
|
||||
"vue-count-to": "1.0.13",
|
||||
"vue-cropper": "0.5.5",
|
||||
"vue-router": "3.4.9",
|
||||
"vuedraggable": "2.24.3",
|
||||
"vuex": "3.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "4.4.4",
|
||||
"@vue/cli-plugin-eslint": "4.4.4",
|
||||
"@vue/cli-plugin-unit-jest": "4.4.4",
|
||||
"@vue/cli-service": "4.4.4",
|
||||
"@vue/test-utils": "1.0.0-beta.29",
|
||||
"autoprefixer": "9.5.1",
|
||||
"@vue/cli-plugin-babel": "4.4.6",
|
||||
"@vue/cli-plugin-eslint": "4.4.6",
|
||||
"@vue/cli-service": "4.4.6",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-jest": "23.6.0",
|
||||
"babel-plugin-dynamic-import-node": "2.3.3",
|
||||
"chalk": "2.4.2",
|
||||
"chokidar": "2.1.5",
|
||||
"chalk": "4.1.0",
|
||||
"connect": "3.6.6",
|
||||
"eslint": "6.7.2",
|
||||
"eslint-plugin-vue": "6.2.2",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"husky": "1.3.1",
|
||||
"lint-staged": "8.1.5",
|
||||
"mockjs": "1.0.1-beta3",
|
||||
"plop": "2.3.0",
|
||||
"runjs": "4.3.2",
|
||||
"node-sass": "4.14.1",
|
||||
"sass-loader": "8.0.2",
|
||||
"script-ext-html-webpack-plugin": "2.1.3",
|
||||
"script-loader": "0.7.2",
|
||||
"serve-static": "1.13.2",
|
||||
"svg-sprite-loader": "4.1.3",
|
||||
"svgo": "1.2.0",
|
||||
"vue-template-compiler": "2.6.10"
|
||||
"eslint": "7.15.0",
|
||||
"eslint-plugin-vue": "7.2.0",
|
||||
"lint-staged": "10.5.3",
|
||||
"sass": "1.30.0",
|
||||
"runjs": "4.4.2",
|
||||
"sass-loader": "10.1.0",
|
||||
"script-ext-html-webpack-plugin": "2.1.5",
|
||||
"svg-sprite-loader": "5.1.1",
|
||||
"vue-template-compiler": "2.6.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9",
|
||||
|
||||
9
ruoyi-ui/src/api/monitor/cache.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询缓存详细
|
||||
export function getCache() {
|
||||
return request({
|
||||
url: '/monitor/cache',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
1
ruoyi-ui/src/assets/icons/svg/redis.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1605865043777" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="856" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M1023.786667 611.84c-0.426667 9.770667-13.354667 20.693333-39.893334 34.56-54.613333 28.458667-337.749333 144.896-397.994666 176.298667-60.288 31.402667-93.738667 31.104-141.354667 8.32-47.616-22.741333-348.842667-144.469333-403.114667-170.368-27.093333-12.970667-40.917333-23.893333-41.386666-34.218667v103.509333c0 10.325333 14.250667 21.290667 41.386666 34.261334 54.272 25.941333 355.541333 147.626667 403.114667 170.368 47.616 22.784 81.066667 23.082667 141.354667-8.362667 60.245333-31.402667 343.338667-147.797333 397.994666-176.298667 27.776-14.464 40.106667-25.728 40.106667-35.925333v-102.058667l-0.213333-0.085333z m0-168.746667c-0.512 9.770667-13.397333 20.650667-39.893334 34.517334-54.613333 28.458667-337.749333 144.896-397.994666 176.298666-60.288 31.402667-93.738667 31.104-141.354667 8.362667-47.616-22.741333-348.842667-144.469333-403.114667-170.410667-27.093333-12.928-40.917333-23.893333-41.386666-34.176v103.509334c0 10.325333 14.250667 21.248 41.386666 34.218666 54.272 25.941333 355.498667 147.626667 403.114667 170.368 47.616 22.784 81.066667 23.082667 141.354667-8.32 60.245333-31.402667 343.338667-147.84 397.994666-176.298666 27.776-14.506667 40.106667-25.770667 40.106667-35.968v-102.058667l-0.256-0.042667z m0-175.018666c0.469333-10.410667-13.141333-19.541333-40.533334-29.610667-53.248-19.498667-334.634667-131.498667-388.522666-151.253333-53.888-19.712-75.818667-18.901333-139.093334 3.84C392.234667 113.706667 92.629333 231.253333 39.338667 252.074667c-26.666667 10.496-39.68 20.181333-39.253334 30.506666V386.133333c0 10.325333 14.250667 21.248 41.386667 34.218667 54.272 25.941333 355.498667 147.669333 403.114667 170.410667 47.616 22.741333 81.066667 23.04 141.354666-8.362667 60.245333-31.402667 343.338667-147.84 397.994667-176.298667 27.776-14.506667 40.106667-25.770667 40.106667-35.968V268.074667h-0.341334zM366.677333 366.08l237.269334-36.437333-71.68 105.088-165.546667-68.650667z m524.8-94.634667l-140.330666 55.466667-15.232 5.973333-140.245334-55.466666 155.392-61.44 140.373334 55.466666z m-411.989333-101.674666l-22.954667-42.325334 71.594667 27.989334 67.498667-22.101334-18.261334 43.733334 68.778667 25.770666-88.704 9.216-19.882667 47.786667-32.085333-53.290667-102.4-9.216 76.416-27.562666z m-176.768 59.733333c70.058667 0 126.805333 21.973333 126.805333 49.109333s-56.746667 49.152-126.805333 49.152-126.848-22.058667-126.848-49.152c0-27.136 56.789333-49.152 126.848-49.152z" p-id="857"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
39
ruoyi-ui/src/assets/images/dark.svg
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
|
||||
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
||||
<feMerge>
|
||||
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
||||
<feMergeNode in="SourceGraphic"></feMergeNode>
|
||||
</feMerge>
|
||||
</filter>
|
||||
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
|
||||
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
|
||||
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
||||
</filter>
|
||||
</defs>
|
||||
<g id="配置面板" width="48" height="40" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="setting-copy-2" width="48" height="40" transform="translate(-1190.000000, -136.000000)">
|
||||
<g id="Group-8" width="48" height="40" transform="translate(1167.000000, 0.000000)">
|
||||
<g id="Group-5-Copy-5" filter="url(#filter-1)" transform="translate(25.000000, 137.000000)">
|
||||
<mask id="mask-3" fill="white">
|
||||
<use xlink:href="#path-2"></use>
|
||||
</mask>
|
||||
<g id="Rectangle-18">
|
||||
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
|
||||
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
|
||||
</g>
|
||||
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
|
||||
<rect id="Rectangle-18" fill="#303648" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
39
ruoyi-ui/src/assets/images/light.svg
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
|
||||
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
||||
<feMerge>
|
||||
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
||||
<feMergeNode in="SourceGraphic"></feMergeNode>
|
||||
</feMerge>
|
||||
</filter>
|
||||
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
|
||||
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
|
||||
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
||||
</filter>
|
||||
</defs>
|
||||
<g id="配置面板" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="setting-copy-2" transform="translate(-1254.000000, -136.000000)">
|
||||
<g id="Group-8" transform="translate(1167.000000, 0.000000)">
|
||||
<g id="Group-5" filter="url(#filter-1)" transform="translate(89.000000, 137.000000)">
|
||||
<mask id="mask-3" fill="white">
|
||||
<use xlink:href="#path-2"></use>
|
||||
</mask>
|
||||
<g id="Rectangle-18">
|
||||
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
|
||||
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
|
||||
</g>
|
||||
<rect id="Rectangle-18" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
|
||||
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 509 KiB After Width: | Height: | Size: 509 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
@ -220,8 +220,8 @@
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(50%, -50%);
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
overflow: hidden;
|
||||
@ -237,4 +237,4 @@
|
||||
.top-right-btn {
|
||||
position: relative;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
-webkit-transition: width .28s;
|
||||
transition: width 0.28s;
|
||||
width: $sideBarWidth !important;
|
||||
background-color: $menuBg;
|
||||
@ -19,6 +20,8 @@
|
||||
left: 0;
|
||||
z-index: 1001;
|
||||
overflow: hidden;
|
||||
-webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
|
||||
box-shadow: 2px 0 6px rgba(0,21,41,.35);
|
||||
|
||||
// reset element-ui css
|
||||
.horizontal-collapse-transition {
|
||||
@ -73,17 +76,25 @@
|
||||
.submenu-title-noDropdown,
|
||||
.el-submenu__title {
|
||||
&:hover {
|
||||
background-color: $menuHover !important;
|
||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.is-active>.el-submenu__title {
|
||||
& .theme-dark .is-active > .el-submenu__title {
|
||||
color: $subMenuActiveText !important;
|
||||
}
|
||||
|
||||
& .nest-menu .el-submenu>.el-submenu__title,
|
||||
& .el-submenu .el-menu-item {
|
||||
min-width: $sideBarWidth !important;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||
}
|
||||
}
|
||||
|
||||
& .theme-dark .nest-menu .el-submenu>.el-submenu__title,
|
||||
& .theme-dark .el-submenu .el-menu-item {
|
||||
background-color: $subMenuBg !important;
|
||||
|
||||
&:hover {
|
||||
@ -190,7 +201,7 @@
|
||||
.el-menu-item {
|
||||
&:hover {
|
||||
// you can use $subMenuHover
|
||||
background-color: $menuHover !important;
|
||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,11 @@ $subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
|
||||
|
||||
$menuBg:#304156;
|
||||
$menuHover:#263445;
|
||||
$sidebarTitle: #ffffff;
|
||||
|
||||
$menuLightBg:#ffffff;
|
||||
$menuLightHover:#f0f1f5;
|
||||
$sidebarLightTitle: #001529;
|
||||
|
||||
$subMenuBg:#1f2d3d;
|
||||
$subMenuHover:#001528;
|
||||
@ -29,7 +34,11 @@ $sideBarWidth: 200px;
|
||||
subMenuActiveText: $subMenuActiveText;
|
||||
menuBg: $menuBg;
|
||||
menuHover: $menuHover;
|
||||
menuLightBg: $menuLightBg;
|
||||
menuLightHover: $menuLightHover;
|
||||
subMenuBg: $subMenuBg;
|
||||
subMenuHover: $subMenuHover;
|
||||
sideBarWidth: $sideBarWidth;
|
||||
sidebarTitle: $sidebarTitle;
|
||||
sidebarLightTitle: $sidebarLightTitle
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
class="header-search-select"
|
||||
@change="change"
|
||||
>
|
||||
<el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" />
|
||||
<el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
@ -167,7 +167,7 @@ export default {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
/deep/ .el-input__inner {
|
||||
::v-deep .el-input__inner {
|
||||
border-radius: 0;
|
||||
border: 0;
|
||||
padding-left: 0;
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
<template >
|
||||
<router-view />
|
||||
</template>
|
||||
<template >
|
||||
<router-view />
|
||||
</template>
|
||||
@ -22,11 +22,8 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
click() {
|
||||
if (!screenfull.enabled) {
|
||||
this.$message({
|
||||
message: 'you browser can not work',
|
||||
type: 'warning'
|
||||
})
|
||||
if (!screenfull.isEnabled) {
|
||||
this.$message({ message: '你的浏览器不支持全屏', type: 'warning' })
|
||||
return false
|
||||
}
|
||||
screenfull.toggle()
|
||||
@ -35,12 +32,12 @@ export default {
|
||||
this.isFullscreen = screenfull.isFullscreen
|
||||
},
|
||||
init() {
|
||||
if (screenfull.enabled) {
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.on('change', this.change)
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
if (screenfull.enabled) {
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.off('change', this.change)
|
||||
}
|
||||
}
|
||||
|
||||
68
ruoyi-ui/src/components/UploadImage/index.vue
Normal file
@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<div class="component-upload-image">
|
||||
<el-upload
|
||||
:action="uploadImgUrl"
|
||||
list-type="picture-card"
|
||||
:on-success="handleUploadSuccess"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:on-error="handleUploadError"
|
||||
name="file"
|
||||
:show-file-list="false"
|
||||
:headers="headers"
|
||||
style="display: inline-block; vertical-align: top"
|
||||
>
|
||||
<img v-if="value" :src="value" class="avatar" />
|
||||
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
|
||||
headers: {
|
||||
Authorization: "Bearer " + getToken(),
|
||||
},
|
||||
};
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleUploadSuccess(res) {
|
||||
this.$emit("input", res.url);
|
||||
this.loading.close();
|
||||
},
|
||||
handleBeforeUpload() {
|
||||
this.loading = this.$loading({
|
||||
lock: true,
|
||||
text: "上传中",
|
||||
background: "rgba(0, 0, 0, 0.7)",
|
||||
});
|
||||
},
|
||||
handleUploadError() {
|
||||
this.$message({
|
||||
type: "error",
|
||||
message: "上传失败",
|
||||
});
|
||||
this.loading.close();
|
||||
},
|
||||
},
|
||||
watch: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,7 +1,8 @@
|
||||
<!-- @author ruoyi 20201128 支持三级以上菜单缓存 -->
|
||||
<template>
|
||||
<section class="app-main">
|
||||
<transition name="fade-transform" mode="out-in">
|
||||
<keep-alive :include="cachedViews">
|
||||
<keep-alive :max="20" :exclude="notCacheName">
|
||||
<router-view :key="key" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
@ -9,17 +10,119 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Global from "@/layout/components/global.js";
|
||||
|
||||
export default {
|
||||
name: 'AppMain',
|
||||
computed: {
|
||||
cachedViews() {
|
||||
return this.$store.state.tagsView.cachedViews
|
||||
notCacheName() {
|
||||
var visitedViews = this.$store.state.tagsView.visitedViews;
|
||||
var noCacheViews = [];
|
||||
Object.keys(visitedViews).some((index) => {
|
||||
if (visitedViews[index].meta.noCache) {
|
||||
noCacheViews.push(visitedViews[index].name);
|
||||
}
|
||||
});
|
||||
return noCacheViews;
|
||||
},
|
||||
key() {
|
||||
return this.$route.path
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.$route.path;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// 关闭标签触发
|
||||
Global.$on("removeCache", (name, view) => {
|
||||
this.removeCache(name, view);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
// 获取有keep-alive子节点的Vnode
|
||||
getVnode() {
|
||||
// 判断子集非空
|
||||
if (this.$children.length == 0) return false;
|
||||
let vnode;
|
||||
for (let item of this.$children) {
|
||||
// 如果data中有key则代表找到了keep-alive下面的子集,这个key就是router-view上的key
|
||||
if (item.$vnode.data.key) {
|
||||
vnode = item.$vnode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return vnode ? vnode : false;
|
||||
},
|
||||
// 移除keep-alive缓存
|
||||
removeCache(name, view = {}) {
|
||||
let vnode = this.getVnode();
|
||||
if (!vnode) return false;
|
||||
let componentInstance = vnode.parent.componentInstance;
|
||||
// 这个key是用来获取前缀用来后面正则匹配用的
|
||||
let keyStart = vnode.key.split("/")[0];
|
||||
let thisKey = `${keyStart}${view.fullPath}`;
|
||||
let regKey = `${keyStart}${view.path}`;
|
||||
|
||||
this[name]({ componentInstance, thisKey, regKey });
|
||||
},
|
||||
// 移除其他
|
||||
closeOthersTags({ componentInstance, thisKey }) {
|
||||
Object.keys(componentInstance.cache).forEach((key, index) => {
|
||||
if (key != thisKey) {
|
||||
// 销毁实例(这里存在多个key指向一个缓存的情况可能前面一个已经清除掉了所有要加判断)
|
||||
if (componentInstance.cache[key]) {
|
||||
componentInstance.cache[key].componentInstance.$destroy();
|
||||
}
|
||||
// 删除缓存
|
||||
delete componentInstance.cache[key];
|
||||
// 移除key中对应的key
|
||||
componentInstance.keys.splice(index, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
// 移除所有缓存
|
||||
closeAllTags({ componentInstance }) {
|
||||
// 销毁实例
|
||||
Object.keys(componentInstance.cache).forEach((key) => {
|
||||
if (componentInstance.cache[key]) {
|
||||
componentInstance.cache[key].componentInstance.$destroy();
|
||||
}
|
||||
});
|
||||
// 删除缓存
|
||||
componentInstance.cache = {};
|
||||
// 移除key中对应的key
|
||||
componentInstance.keys = [];
|
||||
},
|
||||
// 移除单个缓存
|
||||
closeSelectedTag({ componentInstance, regKey }) {
|
||||
let reg = new RegExp(`^${regKey}`);
|
||||
Object.keys(componentInstance.cache).forEach((key, i) => {
|
||||
if (reg.test(key)) {
|
||||
// 销毁实例
|
||||
if (componentInstance.cache[key]) {
|
||||
componentInstance.cache[key].componentInstance.$destroy();
|
||||
}
|
||||
// 删除缓存
|
||||
delete componentInstance.cache[key];
|
||||
// 移除key中对应的key
|
||||
componentInstance.keys.splice(i, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
// 刷新单个缓存
|
||||
refreshSelectedTag({ componentInstance, thisKey }) {
|
||||
Object.keys(componentInstance.cache).forEach((key, index) => {
|
||||
if (null != thisKey && key.replace("/redirect", "") == thisKey) {
|
||||
// 1 销毁实例(这里存在多个key指向一个缓存的情况可能前面一个已经清除掉了所有要加判断)
|
||||
if (componentInstance.cache[key]) {
|
||||
componentInstance.cache[key].componentInstance.$destroy();
|
||||
}
|
||||
// 2 删除缓存
|
||||
delete componentInstance.cache[key];
|
||||
// 3 移除key中对应的key
|
||||
componentInstance.keys.splice(index, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -31,7 +134,7 @@ export default {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fixed-header+.app-main {
|
||||
.fixed-header + .app-main {
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
@ -41,7 +144,7 @@ export default {
|
||||
min-height: calc(100vh - 84px);
|
||||
}
|
||||
|
||||
.fixed-header+.app-main {
|
||||
.fixed-header + .app-main {
|
||||
padding-top: 84px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,47 @@
|
||||
<template>
|
||||
<div class="drawer-container">
|
||||
<div>
|
||||
<h3 class="drawer-title">系统布局配置</h3>
|
||||
<div class="setting-drawer-content">
|
||||
<div class="setting-drawer-title">
|
||||
<h3 class="drawer-title">主题风格设置</h3>
|
||||
</div>
|
||||
<div class="setting-drawer-block-checbox">
|
||||
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')">
|
||||
<img src="@/assets/images/dark.svg" alt="dark">
|
||||
<div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
|
||||
<i aria-label="图标: check" class="anticon anticon-check">
|
||||
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true"
|
||||
focusable="false" class="">
|
||||
<path
|
||||
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')">
|
||||
<img src="@/assets/images/light.svg" alt="light">
|
||||
<div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
|
||||
<i aria-label="图标: check" class="anticon anticon-check">
|
||||
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true"
|
||||
focusable="false" class="">
|
||||
<path
|
||||
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>主题颜色</span>
|
||||
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
|
||||
<div class="drawer-item">
|
||||
<span>主题颜色</span>
|
||||
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-divider/>
|
||||
|
||||
<h3 class="drawer-title">系统布局配置</h3>
|
||||
|
||||
<div class="drawer-item">
|
||||
<span>开启 Tags-Views</span>
|
||||
<el-switch v-model="tagsView" class="drawer-switch" />
|
||||
@ -36,6 +70,12 @@ export default {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
theme() {
|
||||
return this.$store.state.settings.theme
|
||||
},
|
||||
sideTheme() {
|
||||
return this.$store.state.settings.sideTheme
|
||||
},
|
||||
fixedHeader: {
|
||||
get() {
|
||||
return this.$store.state.settings.fixedHeader
|
||||
@ -76,33 +116,82 @@ export default {
|
||||
key: 'theme',
|
||||
value: val
|
||||
})
|
||||
},
|
||||
handleTheme(val) {
|
||||
this.$store.dispatch('settings/changeSetting', {
|
||||
key: 'sideTheme',
|
||||
value: val
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.drawer-container {
|
||||
padding: 24px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
word-wrap: break-word;
|
||||
.setting-drawer-content {
|
||||
.setting-drawer-title {
|
||||
margin-bottom: 12px;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.drawer-title {
|
||||
margin-bottom: 12px;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
.setting-drawer-block-checbox {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.setting-drawer-block-checbox-item {
|
||||
position: relative;
|
||||
margin-right: 16px;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.setting-drawer-block-checbox-selectIcon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-top: 15px;
|
||||
padding-left: 24px;
|
||||
color: #1890ff;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-container {
|
||||
padding: 24px;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
line-height: 1.5;
|
||||
word-wrap: break-word;
|
||||
|
||||
.drawer-item {
|
||||
color: rgba(0, 0, 0, .65);
|
||||
font-size: 14px;
|
||||
padding: 12px 0;
|
||||
}
|
||||
.drawer-title {
|
||||
margin-bottom: 12px;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.drawer-switch {
|
||||
float: right
|
||||
.drawer-item {
|
||||
color: rgba(0, 0, 0, .65);
|
||||
font-size: 14px;
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
.drawer-switch {
|
||||
float: right
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div class="sidebar-logo-container" :class="{'collapse':collapse}">
|
||||
<div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }">
|
||||
<transition name="sidebarLogoFade">
|
||||
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
|
||||
<img v-if="logo" :src="logo" class="sidebar-logo">
|
||||
<h1 v-else class="sidebar-title">{{ title }} </h1>
|
||||
<h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.sidebarTitle : variables.sidebarLightTitle }">{{ title }} </h1>
|
||||
</router-link>
|
||||
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
|
||||
<img v-if="logo" :src="logo" class="sidebar-logo">
|
||||
<h1 class="sidebar-title">{{ title }} </h1>
|
||||
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.sidebarTitle : variables.sidebarLightTitle }">{{ title }} </h1>
|
||||
</router-link>
|
||||
</transition>
|
||||
</div>
|
||||
@ -15,6 +15,7 @@
|
||||
|
||||
<script>
|
||||
import logoImg from '@/assets/logo/logo.png'
|
||||
import variables from '@/assets/styles/variables.scss'
|
||||
|
||||
export default {
|
||||
name: 'SidebarLogo',
|
||||
@ -24,6 +25,14 @@ export default {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
variables() {
|
||||
return variables;
|
||||
},
|
||||
sideTheme() {
|
||||
return this.$store.state.settings.sideTheme
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: '若依管理系统',
|
||||
|
||||
@ -56,6 +56,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
hasOneShowingChild(children = [], parent) {
|
||||
if (!children) {
|
||||
children = [];
|
||||
}
|
||||
const showingChildren = children.filter(item => {
|
||||
if (item.hidden) {
|
||||
return false
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div :class="{'has-logo':showLogo}">
|
||||
<div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }">
|
||||
<logo v-if="showLogo" :collapse="isCollapse" />
|
||||
<el-scrollbar wrap-class="scrollbar-wrapper">
|
||||
<el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
|
||||
<el-menu
|
||||
:default-active="activeMenu"
|
||||
:collapse="isCollapse"
|
||||
:background-color="variables.menuBg"
|
||||
:text-color="variables.menuText"
|
||||
:background-color="settings.sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg"
|
||||
:text-color="settings.sideTheme === 'theme-dark' ? variables.menuText : 'rgba(0,0,0,.65)'"
|
||||
:unique-opened="true"
|
||||
:active-text-color="settings.theme"
|
||||
:collapse-transition="false"
|
||||
|
||||
@ -82,7 +82,7 @@ export default {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
/deep/ {
|
||||
::v-deep {
|
||||
.el-scrollbar__bar {
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
<script>
|
||||
import ScrollPane from './ScrollPane'
|
||||
import path from 'path'
|
||||
import Global from "@/layout/components/global.js";
|
||||
|
||||
export default {
|
||||
components: { ScrollPane },
|
||||
@ -144,6 +145,7 @@ export default {
|
||||
})
|
||||
})
|
||||
})
|
||||
Global.$emit("removeCache", "refreshSelectedTag", this.selectedTag);
|
||||
},
|
||||
closeSelectedTag(view) {
|
||||
this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
|
||||
@ -151,12 +153,14 @@ export default {
|
||||
this.toLastView(visitedViews, view)
|
||||
}
|
||||
})
|
||||
Global.$emit("removeCache", "closeSelectedTag", view);
|
||||
},
|
||||
closeOthersTags() {
|
||||
this.$router.push(this.selectedTag)
|
||||
this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
|
||||
this.moveToCurrentTag()
|
||||
})
|
||||
Global.$emit("removeCache", "closeOthersTags", this.selectedTag);
|
||||
},
|
||||
closeAllTags(view) {
|
||||
this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
|
||||
@ -165,6 +169,7 @@ export default {
|
||||
}
|
||||
this.toLastView(visitedViews, view)
|
||||
})
|
||||
Global.$emit("removeCache", "closeAllTags");
|
||||
},
|
||||
toLastView(visitedViews, view) {
|
||||
const latestView = visitedViews.slice(-1)[0]
|
||||
|
||||
3
ruoyi-ui/src/layout/components/global.js
Normal file
@ -0,0 +1,3 @@
|
||||
import Vue from 'vue'
|
||||
const global = new Vue()
|
||||
export default global
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div :class="classObj" class="app-wrapper">
|
||||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
|
||||
<sidebar class="sidebar-container" />
|
||||
<div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
|
||||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
|
||||
<sidebar class="sidebar-container" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }" />
|
||||
<div :class="{hasTagsView:needTagsView}" class="main-container">
|
||||
<div :class="{'fixed-header':fixedHeader}">
|
||||
<navbar />
|
||||
@ -20,6 +20,7 @@ import RightPanel from '@/components/RightPanel'
|
||||
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
|
||||
import ResizeMixin from './mixin/ResizeHandler'
|
||||
import { mapState } from 'vuex'
|
||||
import variables from '@/assets/styles/variables.scss'
|
||||
|
||||
export default {
|
||||
name: 'Layout',
|
||||
@ -34,6 +35,8 @@ export default {
|
||||
mixins: [ResizeMixin],
|
||||
computed: {
|
||||
...mapState({
|
||||
theme: state => state.settings.theme,
|
||||
sideTheme: state => state.settings.sideTheme,
|
||||
sidebar: state => state.app.sidebar,
|
||||
device: state => state.app.device,
|
||||
showSettings: state => state.settings.showSettings,
|
||||
@ -47,6 +50,9 @@ export default {
|
||||
withoutAnimation: this.sidebar.withoutAnimation,
|
||||
mobile: this.device === 'mobile'
|
||||
}
|
||||
},
|
||||
variables() {
|
||||
return variables;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@ -2,8 +2,6 @@ import Vue from 'vue'
|
||||
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
import 'normalize.css/normalize.css' // a modern alternative to CSS resets
|
||||
|
||||
import Element from 'element-ui'
|
||||
import './assets/styles/element-variables.scss'
|
||||
|
||||
@ -20,8 +18,11 @@ import { getDicts } from "@/api/system/dict/data";
|
||||
import { getConfigKey } from "@/api/system/config";
|
||||
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, download, handleTree } from "@/utils/ruoyi";
|
||||
import Pagination from "@/components/Pagination";
|
||||
//自定义表格工具扩展
|
||||
// 自定义表格工具扩展
|
||||
import RightToolbar from "@/components/RightToolbar"
|
||||
// 代码高亮插件
|
||||
import hljs from 'highlight.js'
|
||||
import 'highlight.js/styles/github-gist.css'
|
||||
|
||||
// 全局方法挂载
|
||||
Vue.prototype.getDicts = getDicts
|
||||
@ -51,6 +52,7 @@ Vue.component('Pagination', Pagination)
|
||||
Vue.component('RightToolbar', RightToolbar)
|
||||
|
||||
Vue.use(permission)
|
||||
Vue.use(hljs.vuePlugin);
|
||||
|
||||
/**
|
||||
* If you don't want to use mock-server
|
||||
|
||||
@ -5,6 +5,7 @@ Vue.use(Router)
|
||||
|
||||
/* Layout */
|
||||
import Layout from '@/layout'
|
||||
import ParentView from '@/components/ParentView';
|
||||
|
||||
/**
|
||||
* Note: 路由配置项
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
module.exports = {
|
||||
title: '若依管理系统',
|
||||
|
||||
/**
|
||||
* 侧边栏主题 深色主题theme-dark,浅色主题theme-light
|
||||
*/
|
||||
sideTheme: 'theme-dark',
|
||||
|
||||
/**
|
||||
* 是否系统布局配置
|
||||
*/
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { constantRoutes } from '@/router'
|
||||
import { getRouters } from '@/api/menu'
|
||||
import Layout from '@/layout/index'
|
||||
import ParentView from '@/components/ParentView';
|
||||
|
||||
const permission = {
|
||||
state: {
|
||||
@ -33,9 +34,11 @@ const permission = {
|
||||
function filterAsyncRouter(asyncRouterMap) {
|
||||
return asyncRouterMap.filter(route => {
|
||||
if (route.component) {
|
||||
// Layout组件特殊处理
|
||||
// Layout ParentView 组件特殊处理
|
||||
if (route.component === 'Layout') {
|
||||
route.component = Layout
|
||||
} else if (route.component === 'ParentView') {
|
||||
route.component = ParentView
|
||||
} else {
|
||||
route.component = loadView(route.component)
|
||||
}
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import variables from '@/assets/styles/element-variables.scss'
|
||||
import defaultSettings from '@/settings'
|
||||
|
||||
const { showSettings, tagsView, fixedHeader, sidebarLogo } = defaultSettings
|
||||
const { sideTheme, showSettings, tagsView, fixedHeader, sidebarLogo } = defaultSettings
|
||||
|
||||
const state = {
|
||||
theme: variables.theme,
|
||||
sideTheme: sideTheme,
|
||||
showSettings: showSettings,
|
||||
tagsView: tagsView,
|
||||
fixedHeader: fixedHeader,
|
||||
|
||||
@ -51,7 +51,7 @@ const user = {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInfo(state.token).then(res => {
|
||||
const user = res.user
|
||||
const avatar = user.avatar == "" ? require("@/assets/image/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar;
|
||||
const avatar = user.avatar == "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar;
|
||||
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
commit('SET_ROLES', res.roles)
|
||||
commit('SET_PERMISSIONS', res.permissions)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import JSEncrypt from 'jsencrypt/bin/jsencrypt'
|
||||
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
|
||||
|
||||
// 密钥对生成 http://web.chacuo.net/netrsakeypair
|
||||
|
||||
|
||||
@ -19,6 +19,28 @@ service.interceptors.request.use(config => {
|
||||
if (getToken() && !isToken) {
|
||||
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||
}
|
||||
// get请求映射params参数
|
||||
if (config.method === 'get' && config.params) {
|
||||
let url = config.url + '?';
|
||||
for (const propName of Object.keys(config.params)) {
|
||||
const value = config.params[propName];
|
||||
var part = encodeURIComponent(propName) + "=";
|
||||
if (value && typeof(value) !== "undefined") {
|
||||
if (typeof value === 'object') {
|
||||
for (const key of Object.keys(value)) {
|
||||
let params = propName + '[' + key + ']';
|
||||
var subPart = encodeURIComponent(params) + "=";
|
||||
url += subPart + encodeURIComponent(value[key]) + "&";
|
||||
}
|
||||
} else {
|
||||
url += part + encodeURIComponent(value) + "&";
|
||||
}
|
||||
}
|
||||
}
|
||||
url = url.slice(0, -1);
|
||||
config.params = {};
|
||||
config.url = url;
|
||||
}
|
||||
return config
|
||||
}, error => {
|
||||
console.log(error)
|
||||
|
||||
@ -54,13 +54,17 @@ export function resetForm(refName) {
|
||||
}
|
||||
|
||||
// 添加日期范围
|
||||
export function addDateRange(params, dateRange) {
|
||||
export function addDateRange(params, dateRange, propName) {
|
||||
var search = params;
|
||||
search.beginTime = "";
|
||||
search.endTime = "";
|
||||
search.params = {};
|
||||
if (null != dateRange && '' != dateRange) {
|
||||
search.beginTime = dateRange[0];
|
||||
search.endTime = dateRange[1];
|
||||
if (typeof(propName) === "undefined") {
|
||||
search.params["beginTime"] = dateRange[0];
|
||||
search.params["endTime"] = dateRange[1];
|
||||
} else {
|
||||
search.params[propName + "BeginTime"] = dateRange[0];
|
||||
search.params[propName + "EndTime"] = dateRange[1];
|
||||
}
|
||||
}
|
||||
return search;
|
||||
}
|
||||
|
||||
@ -1,98 +1,570 @@
|
||||
<template>
|
||||
<div class="dashboard-editor-container">
|
||||
<div class="app-container home">
|
||||
<el-row :gutter="20">
|
||||
<el-col :sm="24" :lg="24">
|
||||
<blockquote class="text-warning" style="font-size: 14px">
|
||||
领取阿里云通用云产品1888优惠券
|
||||
<br />
|
||||
<el-link
|
||||
href="https://www.aliyun.com/minisite/goods?userCode=brki8iof"
|
||||
type="primary"
|
||||
target="_blank"
|
||||
>https://www.aliyun.com/minisite/goods?userCode=brki8iof</el-link
|
||||
>
|
||||
<br />
|
||||
领取腾讯云通用云产品2860优惠券
|
||||
<br />
|
||||
<el-link
|
||||
href="https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console"
|
||||
type="primary"
|
||||
target="_blank"
|
||||
>https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console</el-link
|
||||
>
|
||||
<br />
|
||||
阿里云服务器折扣区
|
||||
<el-link href="http://aly.ruoyi.vip" type="primary" target="_blank"
|
||||
>>☛☛点我进入☚☚</el-link
|
||||
>
|
||||
腾讯云服务器秒杀区
|
||||
<el-link href="http://txy.ruoyi.vip" type="primary" target="_blank"
|
||||
>>☛☛点我进入☚☚</el-link
|
||||
><br />
|
||||
<h4 class="text-danger">
|
||||
云产品通用红包,可叠加官网常规优惠使用。(仅限新用户)
|
||||
</h4>
|
||||
</blockquote>
|
||||
|
||||
<panel-group @handleSetLineChartData="handleSetLineChartData" />
|
||||
|
||||
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
|
||||
<line-chart :chart-data="lineChartData" />
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="32">
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<raddar-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<pie-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<bar-chart />
|
||||
</div>
|
||||
<hr />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :sm="24" :lg="12" style="padding-left: 20px">
|
||||
<h2>若依后台管理框架</h2>
|
||||
<p>
|
||||
一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适自己的。于是利用空闲休息时间开始自己写一套后台系统。如此有了若依管理系统。,她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
|
||||
</p>
|
||||
<p>
|
||||
<b>当前版本:</b> <span>v{{ version }}</span>
|
||||
</p>
|
||||
<p>
|
||||
<el-tag type="danger">¥免费开源</el-tag>
|
||||
</p>
|
||||
<p>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
icon="el-icon-cloudy"
|
||||
plain
|
||||
@click="goTarget('https://gitee.com/y_project/RuoYi-Vue')"
|
||||
>访问码云</el-button
|
||||
>
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-s-home"
|
||||
plain
|
||||
@click="goTarget('http://ruoyi.vip')"
|
||||
>访问主页</el-button
|
||||
>
|
||||
</p>
|
||||
</el-col>
|
||||
|
||||
|
||||
<el-col :sm="24" :lg="12" style="padding-left: 50px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<h2>技术选型</h2>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<h4>后端技术</h4>
|
||||
<ul>
|
||||
<li>SpringBoot</li>
|
||||
<li>Spring Security</li>
|
||||
<li>JWT</li>
|
||||
<li>MyBatis</li>
|
||||
<li>Druid</li>
|
||||
<li>Fastjson</li>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<h4>前端技术</h4>
|
||||
<ul>
|
||||
<li>Vue</li>
|
||||
<li>Vuex</li>
|
||||
<li>Element-ui</li>
|
||||
<li>Axios</li>
|
||||
<li>Sass</li>
|
||||
<li>Quill</li>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-divider />
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="8">
|
||||
<el-card class="update-log">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>联系信息</span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<p>
|
||||
<i class="el-icon-s-promotion"></i> 官网:<el-link
|
||||
href="http://www.ruoyi.vip"
|
||||
target="_blank"
|
||||
>http://www.ruoyi.vip</el-link
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
<i class="el-icon-user-solid"></i> QQ群:<s>满937441</s>
|
||||
<s>满887144332</s> <s>满180251782</s>
|
||||
<a href="https://jq.qq.com/?_wv=1027&k=4WWwqNxN" target="_blank"
|
||||
> 104180207</a
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
<i class="el-icon-chat-dot-round"></i> 微信:<a
|
||||
href="javascript:;"
|
||||
>/ *若依</a
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
<i class="el-icon-money"></i> 支付宝:<a
|
||||
href="javascript:;"
|
||||
class="支付宝信息"
|
||||
>/ *若依</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="8">
|
||||
<el-card class="update-log">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>更新日志</span>
|
||||
</div>
|
||||
<el-collapse accordion>
|
||||
<el-collapse-item title="v3.3.0 - 2020-12-14">
|
||||
<ol>
|
||||
<li>新增缓存监控功能</li>
|
||||
<li>支持主题风格配置</li>
|
||||
<li>修复多级菜单之间切换无法缓存的问题</li>
|
||||
<li>多级菜单自动配置组件</li>
|
||||
<li>代码生成预览支持高亮显示</li>
|
||||
<li>支持Get请求映射Params参数</li>
|
||||
<li>删除用户和角色解绑关联</li>
|
||||
<li>去除用户手机邮箱部门必填验证</li>
|
||||
<li>Excel支持注解align对齐方式</li>
|
||||
<li>Excel支持导入Boolean型数据</li>
|
||||
<li>优化头像样式,鼠标移入悬停遮罩</li>
|
||||
<li>代码生成预览提供滚动机制</li>
|
||||
<li>代码生成删除多余的数字float类型</li>
|
||||
<li>修正转换字符串的目标字符集属性</li>
|
||||
<li>回显数据字典防止空值报错</li>
|
||||
<li>日志记录增加过滤多文件场景</li>
|
||||
<li>修改缓存Set方法可能导致嵌套的问题</li>
|
||||
<li>移除前端一些多余的依赖</li>
|
||||
<li>防止安全扫描YUI出现的风险提示</li>
|
||||
<li>修改node-sass为dart-sass</li>
|
||||
<li>升级SpringBoot到最新版本2.1.18</li>
|
||||
<li>升级poi到最新版本4.1.2</li>
|
||||
<li>升级oshi到最新版本v5.3.6</li>
|
||||
<li>升级bitwalker到最新版本1.21</li>
|
||||
<li>升级axios到最新版本0.21.0</li>
|
||||
<li>升级element-ui到最新版本2.14.1</li>
|
||||
<li>升级vue到最新版本2.6.12</li>
|
||||
<li>升级vuex到最新版本3.6.0</li>
|
||||
<li>升级vue-cli到版本4.5.9</li>
|
||||
<li>升级vue-router到最新版本3.4.9</li>
|
||||
<li>升级vue-cli到最新版本4.4.6</li>
|
||||
<li>升级vue-cropper到最新版本0.5.5</li>
|
||||
<li>升级clipboard到最新版本2.0.6</li>
|
||||
<li>升级core-js到最新版本3.8.1</li>
|
||||
<li>升级echarts到最新版本4.9.0</li>
|
||||
<li>升级file-saver到最新版本2.0.4</li>
|
||||
<li>升级fuse.js到最新版本6.4.3</li>
|
||||
<li>升级js-beautify到最新版本1.13.0</li>
|
||||
<li>升级js-cookie到最新版本2.2.1</li>
|
||||
<li>升级path-to-regexp到最新版本6.2.0</li>
|
||||
<li>升级quill到最新版本1.3.7</li>
|
||||
<li>升级screenfull到最新版本5.0.2</li>
|
||||
<li>升级sortablejs到最新版本1.10.2</li>
|
||||
<li>升级vuedraggable到最新版本2.24.3</li>
|
||||
<li>升级chalk到最新版本4.1.0</li>
|
||||
<li>升级eslint到最新版本7.15.0</li>
|
||||
<li>升级eslint-plugin-vue到最新版本7.2.0</li>
|
||||
<li>升级lint-staged到最新版本10.5.3</li>
|
||||
<li>升级runjs到最新版本4.4.2</li>
|
||||
<li>升级sass-loader到最新版本10.1.0</li>
|
||||
<li>升级script-ext-html-webpack-plugin到最新版本2.1.5</li>
|
||||
<li>升级svg-sprite-loader到最新版本5.1.1</li>
|
||||
<li>升级vue-template-compiler到最新版本2.6.12</li>
|
||||
<li>其他细节优化</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="v3.2.1 - 2020-11-18">
|
||||
<ol>
|
||||
<li>阻止任意文件下载漏洞</li>
|
||||
<li>代码生成支持上传控件</li>
|
||||
<li>新增图片上传组件</li>
|
||||
<li>调整默认首页</li>
|
||||
<li>升级druid到最新版本v1.2.2</li>
|
||||
<li>mapperLocations配置支持分隔符</li>
|
||||
<li>权限信息调整</li>
|
||||
<li>调整sql默认时间</li>
|
||||
<li>解决代码生成没有bit类型的问题</li>
|
||||
<li>升级pagehelper到最新版1.3.0</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="v3.2.0 - 2020-10-10">
|
||||
<ol>
|
||||
<li>升级springboot版本到2.1.17 提升安全性</li>
|
||||
<li>升级oshi到最新版本v5.2.5</li>
|
||||
<li>升级druid到最新版本v1.2.1</li>
|
||||
<li>升级jjwt到版本0.9.1</li>
|
||||
<li>升级fastjson到最新版1.2.74</li>
|
||||
<li>修改sass为node-sass,避免el-icon图标乱码</li>
|
||||
<li>代码生成支持同步数据库</li>
|
||||
<li>代码生成支持富文本控件</li>
|
||||
<li>代码生成页面时不忽略remark属性</li>
|
||||
<li>代码生成添加select必填选项</li>
|
||||
<li>Excel导出类型NUMERIC支持精度浮点类型</li>
|
||||
<li>Excel导出targetAttr优化获取值,防止get方法不规范</li>
|
||||
<li>Excel注解支持自动统计数据总和</li>
|
||||
<li>Excel注解支持设置BigDecimal精度&舍入规则</li>
|
||||
<li>菜单&数据权限新增(展开/折叠 全选/全不选 父子联动)</li>
|
||||
<li>允许用户分配到部门父节点</li>
|
||||
<li>菜单新增是否缓存keep-alive</li>
|
||||
<li>表格操作列间距调整</li>
|
||||
<li>限制系统内置参数不允许删除</li>
|
||||
<li>富文本组件优化,支持自定义高度&图片冲突问题</li>
|
||||
<li>富文本工具栏样式对齐</li>
|
||||
<li>导入excel整形值校验优化</li>
|
||||
<li>修复页签关闭所有时固定标签路由不刷新问题</li>
|
||||
<li>表单构建布局型组件新增按钮</li>
|
||||
<li>左侧菜单文字过长显示省略号</li>
|
||||
<li>修正根节点为子部门时,树状结构显示问题</li>
|
||||
<li>修正调用目标字符串最大长度</li>
|
||||
<li>修正菜单提示信息错误</li>
|
||||
<li>修正定时任务执行一次权限标识</li>
|
||||
<li>修正数据库字符串类型nvarchar</li>
|
||||
<li>优化递归子节点</li>
|
||||
<li>优化数据权限判断</li>
|
||||
<li>其他细节优化</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
|
||||
<el-collapse-item title="v3.1.0 - 2020-08-13">
|
||||
<ol>
|
||||
<li>表格工具栏右侧添加刷新&显隐查询组件</li>
|
||||
<li>后端支持CORS跨域请求</li>
|
||||
<li>代码生成支持选择上级菜单</li>
|
||||
<li>代码生成支持自定义路径</li>
|
||||
<li>代码生成支持复选框</li>
|
||||
<li>Excel导出导入支持dictType字典类型</li>
|
||||
<li>Excel支持分割字符串组内容</li>
|
||||
<li>验证码类型支持(数组计算、字符验证)</li>
|
||||
<li>升级vue-cli版本到4.4.4</li>
|
||||
<li>修改 node-sass 为 dart-sass</li>
|
||||
<li>表单类型为Integer/Long设置整形默认值</li>
|
||||
<li>代码生成器默认mapper路径与默认mapperScan路径不一致</li>
|
||||
<li>优化防重复提交拦截器</li>
|
||||
<li>优化上级菜单不能选择自己</li>
|
||||
<li>修复角色的权限分配后,未实时生效问题</li>
|
||||
<li>修复在线用户日志记录类型</li>
|
||||
<li>修复富文本空格和缩进保存后不生效问题</li>
|
||||
<li>修复在线用户判断逻辑</li>
|
||||
<li>唯一限制条件只返回单条数据</li>
|
||||
<li>添加获取当前的环境配置方法</li>
|
||||
<li>超时登录后页面跳转到首页</li>
|
||||
<li>全局异常状态汉化拦截处理</li>
|
||||
<li>HTML过滤器改为将html转义</li>
|
||||
<li>检查字符支持小数点&降级改成异常提醒</li>
|
||||
<li>其他细节优化</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
|
||||
<el-collapse-item title="v3.0.0 - 2020-07-20">
|
||||
<ol>
|
||||
<li>单应用调整为多模块项目</li>
|
||||
<li>升级element-ui版本到2.13.2</li>
|
||||
<li>删除babel,提高编译速度。</li>
|
||||
<li>新增菜单默认主类目</li>
|
||||
<li>编码文件名修改为uuid方式</li>
|
||||
<li>定时任务cron表达式验证</li>
|
||||
<li>角色权限修改时已有权限未自动勾选异常修复</li>
|
||||
<li>防止切换权限用户后登录出现404</li>
|
||||
<li>Excel支持sort导出排序</li>
|
||||
<li>创建用户不允许选择超级管理员角色</li>
|
||||
<li>修复代码生成导入表结构出现异常页面不提醒问题</li>
|
||||
<li>修复代码生成点击多次表修改数据不变化的问题</li>
|
||||
<li>修复头像上传成功二次打开无法改变裁剪框大小和位置问题</li>
|
||||
<li>修复布局为small者mini用户表单显示错位问题</li>
|
||||
<li>修复热部署导致的强换异常问题</li>
|
||||
<li>修改用户管理复选框宽度,防止部分浏览器出现省略号</li>
|
||||
<li>IpUtils工具,清除Xss特殊字符,防止Xff注入攻击</li>
|
||||
<li>生成domain 如果是浮点型 统一用BigDecimal</li>
|
||||
<li>定时任务调整label-width,防止部署出现错位</li>
|
||||
<li>调整表头固定列默认样式</li>
|
||||
<li>代码生成模板调整,字段为String并且必填则加空串条件</li>
|
||||
<li>代码生成字典Integer/Long使用parseInt</li>
|
||||
<li>
|
||||
修复dict_sort不可update为0的问题&查询返回增加dict_sort升序排序
|
||||
</li>
|
||||
<li>修正岗位导出权限注解</li>
|
||||
<li>禁止加密密文返回前端</li>
|
||||
<li>修复代码生成页面中的查询条件创建时间未生效的问题</li>
|
||||
<li>修复首页搜索菜单外链无法点击跳转问题</li>
|
||||
<li>修复菜单管理选择图标,backspace删除时不过滤数据</li>
|
||||
<li>用户管理部门分支节点不可检查&显示计数</li>
|
||||
<li>数据范围过滤属性调整</li>
|
||||
<li>其他细节优化</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
|
||||
<el-collapse-item title="v2.3.0 - 2020-06-01">
|
||||
<ol>
|
||||
<li>升级fastjson到最新版1.2.70 修复高危安全漏洞</li>
|
||||
<li>dev启动默认打开浏览器</li>
|
||||
<li>vue-cli使用默认source-map</li>
|
||||
<li>slidebar eslint报错优化</li>
|
||||
<li>当tags-view滚动关闭右键菜单</li>
|
||||
<li>字典管理添加缓存读取</li>
|
||||
<li>参数管理支持缓存操作</li>
|
||||
<li>支持一级菜单(和主页同级)在main区域显示</li>
|
||||
<li>限制外链地址必须以http(s)开头</li>
|
||||
<li>tagview & sidebar 主题颜色与element ui(全局)同步</li>
|
||||
<li>修改数据源类型优先级,先根据方法,再根据类</li>
|
||||
<li>支持是否需要设置token属性,自定义返回码消息。</li>
|
||||
<li>swagger请求前缀加入配置。</li>
|
||||
<li>登录地点设置内容过长则隐藏显示</li>
|
||||
<li>修复定时任务执行一次按钮后不提示消息问题</li>
|
||||
<li>修改上级部门(选择项排除本身和下级)</li>
|
||||
<li>通用http发送方法增加参数 contentType 编码类型</li>
|
||||
<li>更换IP地址查询接口</li>
|
||||
<li>修复页签变量undefined</li>
|
||||
<li>添加校验部门包含未停用的子部门</li>
|
||||
<li>修改定时任务详情下次执行时间日期显示错误</li>
|
||||
<li>角色管理查询设置默认排序字段</li>
|
||||
<li>swagger添加enable参数控制是否启用</li>
|
||||
<li>只对json类型请求构建可重复读取inputStream的request</li>
|
||||
<li>修改代码生成字典字段int类型没有自动选中问题</li>
|
||||
<li>vuex用户名取值修正</li>
|
||||
<li>表格树模板去掉多余的)</li>
|
||||
<li>代码生成序号修正</li>
|
||||
<li>全屏情况下不调整上外边距</li>
|
||||
<li>代码生成Date字段添加默认格式</li>
|
||||
<li>用户管理角色选择权限控制</li>
|
||||
<li>修复路由懒加载报错问题</li>
|
||||
<li>模板sql.vm添加菜单状态</li>
|
||||
<li>设置用户名称不能修改</li>
|
||||
<li>dialog添加append-to-body属性,防止ie遮罩</li>
|
||||
<li>菜单区分状态和显示隐藏功能</li>
|
||||
<li>升级fastjson到最新版1.2.68 修复安全加固</li>
|
||||
<li>修复代码生成如果选择字典类型缺失逗号问题</li>
|
||||
<li>登录请求params更换为data,防止暴露url</li>
|
||||
<li>日志返回时间格式处理</li>
|
||||
<li>添加handle控制允许拖动的元素</li>
|
||||
<li>布局设置点击扩大范围</li>
|
||||
<li>代码生成列属性排序查询</li>
|
||||
<li>代码生成列支持拖动排序</li>
|
||||
<li>修复时间格式不支持ios问题</li>
|
||||
<li>表单构建添加父级class,防止冲突</li>
|
||||
<li>定时任务并发属性修正</li>
|
||||
<li>角色禁用&菜单隐藏不查询权限</li>
|
||||
<li>其他细节优化</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
|
||||
<el-collapse-item title="v2.2.0 - 2020-03-18">
|
||||
<ol>
|
||||
<li>系统监控新增定时任务功能</li>
|
||||
<li>添加一个打包Web工程bat</li>
|
||||
<li>修复页签鼠标滚轮按下的时候,可以关闭不可关闭的tag</li>
|
||||
<li>修复点击退出登录有时会无提示问题</li>
|
||||
<li>修复防重复提交注解无效问题</li>
|
||||
<li>修复通知公告批量删除异常问题</li>
|
||||
<li>添加菜单时路由地址必填限制</li>
|
||||
<li>代码生成字段描述可编辑</li>
|
||||
<li>修复用户修改个人信息导致缓存不过期问题</li>
|
||||
<li>个人信息创建时间获取正确属性值</li>
|
||||
<li>操作日志详细显示正确类型</li>
|
||||
<li>导入表单击行数据时选中对应的复选框</li>
|
||||
<li>批量替换表前缀逻辑调整</li>
|
||||
<li>固定重定向路径表达式</li>
|
||||
<li>升级element-ui版本到2.13.0</li>
|
||||
<li>操作日志排序调整</li>
|
||||
<li>修复charts切换侧边栏或者缩放窗口显示bug</li>
|
||||
<li>其他细节优化</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
|
||||
<el-collapse-item title="v2.1.0 - 2020-02-24">
|
||||
<ol>
|
||||
<li>新增表单构建</li>
|
||||
<li>代码生成支持树表结构</li>
|
||||
<li>新增用户导入</li>
|
||||
<li>修复动态加载路由页面刷新问题</li>
|
||||
<li>修复地址开关无效问题</li>
|
||||
<li>汉化错误提示页面</li>
|
||||
<li>代码生成已知问题修改</li>
|
||||
<li>修复多数据源下配置关闭出现异常处理</li>
|
||||
<li>添加HTML过滤器,用于去除XSS漏洞隐患</li>
|
||||
<li>修复上传头像控制台出现异常</li>
|
||||
<li>修改用户管理分页不正确的问题</li>
|
||||
<li>修复验证码记录提示错误</li>
|
||||
<li>修复request.js缺少Message引用</li>
|
||||
<li>修复表格时间为空出现的异常</li>
|
||||
<li>添加Jackson日期反序列化时区配置</li>
|
||||
<li>调整根据用户权限加载菜单数据树形结构</li>
|
||||
<li>调整成功登陆不恢复按钮,防止多次点击</li>
|
||||
<li>修改用户个人资料同步缓存信息</li>
|
||||
<li>修复页面同时出现el-upload和Editor不显示处理</li>
|
||||
<li>修复在角色管理页修改菜单权限偶尔未选中问题</li>
|
||||
<li>配置文件新增redis密码属性</li>
|
||||
<li>设置mybatis全局的配置文件</li>
|
||||
<li>其他细节优化</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
|
||||
<el-collapse-item title="v2.0.0 - 2019-12-02">
|
||||
<ol>
|
||||
<li>新增代码生成</li>
|
||||
<li>新增@RepeatSubmit注解,防止重复提交</li>
|
||||
<li>新增菜单主目录添加/删除操作</li>
|
||||
<li>日志记录过滤特殊对象,防止转换异常</li>
|
||||
<li>修改代码生成路由脚本错误</li>
|
||||
<li>用户上传头像实时同步缓存,无需重新登录</li>
|
||||
<li>调整切换页签后不重新加载数据</li>
|
||||
<li>添加jsencrypt实现参数的前端加密</li>
|
||||
<li>系统退出删除用户缓存记录</li>
|
||||
<li>其他细节优化</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="v1.1.0 - 2019-11-11">
|
||||
<ol>
|
||||
<li>新增在线用户管理</li>
|
||||
<li>新增按钮组功能实现(批量删除、导出、清空)</li>
|
||||
<li>新增查询条件重置按钮</li>
|
||||
<li>新增Swagger全局Token配置</li>
|
||||
<li>新增后端参数校验</li>
|
||||
<li>修复字典管理页面的日期查询异常</li>
|
||||
<li>修改时间函数命名防止冲突</li>
|
||||
<li>去除菜单上级校验,默认为顶级</li>
|
||||
<li>修复用户密码无法修改问题</li>
|
||||
<li>修复菜单类型为按钮时不显示权限标识</li>
|
||||
<li>其他细节优化</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="v1.0.0 - 2019-10-08">
|
||||
<ol>
|
||||
<li>若依前后端分离系统正式发布</li>
|
||||
</ol>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="8">
|
||||
<el-card class="update-log">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>捐赠支持</span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<img
|
||||
src="https://oscimg.oschina.net/oscnet/up-d6695f82666e5018f715c41cb7ee60d3b73.png"
|
||||
alt="donate"
|
||||
width="100%"
|
||||
/>
|
||||
<span style="display: inline-block; height: 30px; line-height: 30px"
|
||||
>你可以请作者喝杯咖啡表示鼓励</span
|
||||
>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PanelGroup from './dashboard/PanelGroup'
|
||||
import LineChart from './dashboard/LineChart'
|
||||
import RaddarChart from './dashboard/RaddarChart'
|
||||
import PieChart from './dashboard/PieChart'
|
||||
import BarChart from './dashboard/BarChart'
|
||||
|
||||
const lineChartData = {
|
||||
newVisitis: {
|
||||
expectedData: [100, 120, 161, 134, 105, 160, 165],
|
||||
actualData: [120, 82, 91, 154, 162, 140, 145]
|
||||
},
|
||||
messages: {
|
||||
expectedData: [200, 192, 120, 144, 160, 130, 140],
|
||||
actualData: [180, 160, 151, 106, 145, 150, 130]
|
||||
},
|
||||
purchases: {
|
||||
expectedData: [80, 100, 121, 104, 105, 90, 100],
|
||||
actualData: [120, 90, 100, 138, 142, 130, 130]
|
||||
},
|
||||
shoppings: {
|
||||
expectedData: [130, 140, 141, 142, 145, 150, 160],
|
||||
actualData: [120, 82, 91, 154, 162, 140, 130]
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: {
|
||||
PanelGroup,
|
||||
LineChart,
|
||||
RaddarChart,
|
||||
PieChart,
|
||||
BarChart
|
||||
},
|
||||
name: "index",
|
||||
data() {
|
||||
return {
|
||||
lineChartData: lineChartData.newVisitis
|
||||
}
|
||||
// 版本号
|
||||
version: "3.3.0",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleSetLineChartData(type) {
|
||||
this.lineChartData = lineChartData[type]
|
||||
}
|
||||
}
|
||||
}
|
||||
goTarget(href) {
|
||||
window.open(href, "_blank");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dashboard-editor-container {
|
||||
padding: 32px;
|
||||
background-color: rgb(240, 242, 245);
|
||||
position: relative;
|
||||
|
||||
.chart-wrapper {
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
margin-bottom: 32px;
|
||||
<style scoped lang="scss">
|
||||
.home {
|
||||
blockquote {
|
||||
padding: 10px 20px;
|
||||
margin: 0 0 20px;
|
||||
font-size: 17.5px;
|
||||
border-left: 5px solid #eee;
|
||||
}
|
||||
hr {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
border: 0;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
.col-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:1024px) {
|
||||
.chart-wrapper {
|
||||
padding: 8px;
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
color: #676a6c;
|
||||
overflow-x: hidden;
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 10px;
|
||||
font-size: 26px;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 10px;
|
||||
|
||||
b {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.update-log {
|
||||
ol {
|
||||
display: block;
|
||||
list-style-type: decimal;
|
||||
margin-block-start: 1em;
|
||||
margin-block-end: 1em;
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: 0;
|
||||
padding-inline-start: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
98
ruoyi-ui/src/views/index_v1.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<div class="dashboard-editor-container">
|
||||
|
||||
<panel-group @handleSetLineChartData="handleSetLineChartData" />
|
||||
|
||||
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
|
||||
<line-chart :chart-data="lineChartData" />
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="32">
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<raddar-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<pie-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<bar-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PanelGroup from './dashboard/PanelGroup'
|
||||
import LineChart from './dashboard/LineChart'
|
||||
import RaddarChart from './dashboard/RaddarChart'
|
||||
import PieChart from './dashboard/PieChart'
|
||||
import BarChart from './dashboard/BarChart'
|
||||
|
||||
const lineChartData = {
|
||||
newVisitis: {
|
||||
expectedData: [100, 120, 161, 134, 105, 160, 165],
|
||||
actualData: [120, 82, 91, 154, 162, 140, 145]
|
||||
},
|
||||
messages: {
|
||||
expectedData: [200, 192, 120, 144, 160, 130, 140],
|
||||
actualData: [180, 160, 151, 106, 145, 150, 130]
|
||||
},
|
||||
purchases: {
|
||||
expectedData: [80, 100, 121, 104, 105, 90, 100],
|
||||
actualData: [120, 90, 100, 138, 142, 130, 130]
|
||||
},
|
||||
shoppings: {
|
||||
expectedData: [130, 140, 141, 142, 145, 150, 160],
|
||||
actualData: [120, 82, 91, 154, 162, 140, 130]
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: {
|
||||
PanelGroup,
|
||||
LineChart,
|
||||
RaddarChart,
|
||||
PieChart,
|
||||
BarChart
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
lineChartData: lineChartData.newVisitis
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSetLineChartData(type) {
|
||||
this.lineChartData = lineChartData[type]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dashboard-editor-container {
|
||||
padding: 32px;
|
||||
background-color: rgb(240, 242, 245);
|
||||
position: relative;
|
||||
|
||||
.chart-wrapper {
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:1024px) {
|
||||
.chart-wrapper {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -48,7 +48,7 @@
|
||||
</el-form>
|
||||
<!-- 底部 -->
|
||||
<div class="el-login-footer">
|
||||
<span>Copyright © 2018-2019 ruoyi.vip All Rights Reserved.</span>
|
||||
<span>Copyright © 2018-2020 ruoyi.vip All Rights Reserved.</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -148,7 +148,7 @@ export default {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
background-image: url("../assets/image/login-background.jpg");
|
||||
background-image: url("../assets/images/login-background.jpg");
|
||||
background-size: cover;
|
||||
}
|
||||
.title {
|
||||
|
||||
153
ruoyi-ui/src/views/monitor/cache/index.vue
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row>
|
||||
<el-col :span="24" class="card-box">
|
||||
<el-card>
|
||||
<div slot="header"><span>基本信息</span></div>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<table cellspacing="0" style="width: 100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><div class="cell">Redis版本</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ cache.info.redis_version }}</div></td>
|
||||
<td><div class="cell">运行模式</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ cache.info.redis_mode == "standalone" ? "单机" : "集群" }}</div></td>
|
||||
<td><div class="cell">端口</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ cache.info.tcp_port }}</div></td>
|
||||
<td><div class="cell">客户端数</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ cache.info.connected_clients }}</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div class="cell">运行时间(天)</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ cache.info.uptime_in_days }}</div></td>
|
||||
<td><div class="cell">使用内存</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ cache.info.used_memory_human }}</div></td>
|
||||
<td><div class="cell">使用CPU</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div></td>
|
||||
<td><div class="cell">内存配置</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ cache.info.maxmemory_human }}</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div class="cell">AOF是否开启</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ cache.info.aof_enabled == "0" ? "否" : "是" }}</div></td>
|
||||
<td><div class="cell">RDB是否成功</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ cache.info.rdb_last_bgsave_status }}</div></td>
|
||||
<td><div class="cell">Key数量</div></td>
|
||||
<td><div class="cell" v-if="cache.dbSize">{{ cache.dbSize }} </div></td>
|
||||
<td><div class="cell">网络入口/出口</div></td>
|
||||
<td><div class="cell" v-if="cache.info">{{ cache.info.instantaneous_input_kbps }}kps/{{cache.info.instantaneous_output_kbps}}kps</div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="card-box">
|
||||
<el-card>
|
||||
<div slot="header"><span>命令统计</span></div>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<div ref="commandstats" style="height: 420px" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="card-box">
|
||||
<el-card>
|
||||
<div slot="header">
|
||||
<span>内存信息</span>
|
||||
</div>
|
||||
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||
<div ref="usedmemory" style="height: 420px" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getCache } from "@/api/monitor/cache";
|
||||
import echarts from "echarts";
|
||||
|
||||
export default {
|
||||
name: "Server",
|
||||
data() {
|
||||
return {
|
||||
// 加载层信息
|
||||
loading: [],
|
||||
// 统计命令信息
|
||||
commandstats: null,
|
||||
// 使用内存
|
||||
usedmemory: null,
|
||||
// cache信息
|
||||
cache: [],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.openLoading();
|
||||
},
|
||||
methods: {
|
||||
/** 查缓存询信息 */
|
||||
getList() {
|
||||
getCache().then((response) => {
|
||||
this.cache = response.data;
|
||||
this.loading.close();
|
||||
|
||||
this.commandstats = echarts.init(this.$refs.commandstats, "macarons");
|
||||
this.commandstats.setOption({
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: "{a} <br/>{b} : {c} ({d}%)",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "命令",
|
||||
type: "pie",
|
||||
roseType: "radius",
|
||||
radius: [15, 95],
|
||||
center: ["50%", "38%"],
|
||||
data: response.data.commandStats,
|
||||
animationEasing: "cubicInOut",
|
||||
animationDuration: 1000,
|
||||
},
|
||||
],
|
||||
});
|
||||
this.usedmemory = echarts.init(this.$refs.usedmemory, "macarons");
|
||||
this.usedmemory.setOption({
|
||||
tooltip: {
|
||||
formatter: "{b} <br/>{a} : " + this.cache.info.used_memory_human,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "峰值",
|
||||
type: "gauge",
|
||||
min: 0,
|
||||
max: 1000,
|
||||
detail: {
|
||||
formatter: this.cache.info.used_memory_human,
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: parseFloat(this.cache.info.used_memory_human),
|
||||
name: "内存消耗",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
},
|
||||
// 打开加载层
|
||||
openLoading() {
|
||||
this.loading = this.$loading({
|
||||
lock: true,
|
||||
text: "拼命读取中",
|
||||
spinner: "el-icon-loading",
|
||||
background: "rgba(0, 0, 0, 0.7)",
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -402,7 +402,7 @@ export default {
|
||||
return runJob(row.jobId, row.jobGroup);
|
||||
}).then(() => {
|
||||
this.msgSuccess("执行成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 任务详细信息 */
|
||||
handleView(row) {
|
||||
@ -437,19 +437,15 @@ export default {
|
||||
if (valid) {
|
||||
if (this.form.jobId != undefined) {
|
||||
updateJob(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addJob(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -467,7 +463,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -480,7 +476,7 @@ export default {
|
||||
return exportJob(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -263,7 +263,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 清空按钮操作 */
|
||||
handleClean() {
|
||||
@ -276,7 +276,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("清空成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -289,7 +289,7 @@ export default {
|
||||
return exportJobLog(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -196,7 +196,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 清空按钮操作 */
|
||||
handleClean() {
|
||||
@ -209,7 +209,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("清空成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -222,7 +222,7 @@ export default {
|
||||
return exportLogininfor(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -120,7 +120,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("强退成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -284,7 +284,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 清空按钮操作 */
|
||||
handleClean() {
|
||||
@ -297,7 +297,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("清空成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -310,7 +310,7 @@ export default {
|
||||
return exportOperlog(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -304,19 +304,15 @@ export default {
|
||||
if (valid) {
|
||||
if (this.form.configId != undefined) {
|
||||
updateConfig(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addConfig(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -334,7 +330,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -347,14 +343,12 @@ export default {
|
||||
return exportConfig(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 清理缓存按钮操作 */
|
||||
handleClearCache() {
|
||||
clearCache().then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("清理成功");
|
||||
}
|
||||
this.msgSuccess("清理成功");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ export default {
|
||||
{ required: true, message: "部门名称不能为空", trigger: "blur" }
|
||||
],
|
||||
orderNum: [
|
||||
{ required: true, message: "菜单顺序不能为空", trigger: "blur" }
|
||||
{ required: true, message: "显示排序不能为空", trigger: "blur" }
|
||||
],
|
||||
email: [
|
||||
{
|
||||
@ -284,19 +284,15 @@ export default {
|
||||
if (valid) {
|
||||
if (this.form.deptId != undefined) {
|
||||
updateDept(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addDept(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -313,7 +309,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -304,19 +304,15 @@ export default {
|
||||
if (valid) {
|
||||
if (this.form.dictCode != undefined) {
|
||||
updateData(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addData(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -334,7 +330,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -347,7 +343,7 @@ export default {
|
||||
return exportData(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -308,19 +308,15 @@ export default {
|
||||
if (valid) {
|
||||
if (this.form.dictId != undefined) {
|
||||
updateType(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addType(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -338,7 +334,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -351,14 +347,12 @@ export default {
|
||||
return exportType(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 清理缓存按钮操作 */
|
||||
handleClearCache() {
|
||||
clearCache().then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("清理成功");
|
||||
}
|
||||
this.msgSuccess("清理成功");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,19 +367,15 @@ export default {
|
||||
if (valid) {
|
||||
if (this.form.menuId != undefined) {
|
||||
updateMenu(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addMenu(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -396,7 +392,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -221,7 +221,7 @@ export default {
|
||||
{ required: true, message: "公告标题不能为空", trigger: "blur" }
|
||||
],
|
||||
noticeType: [
|
||||
{ required: true, message: "公告类型不能为空", trigger: "blur" }
|
||||
{ required: true, message: "公告类型不能为空", trigger: "change" }
|
||||
]
|
||||
}
|
||||
};
|
||||
@ -307,19 +307,15 @@ export default {
|
||||
if (valid) {
|
||||
if (this.form.noticeId != undefined) {
|
||||
updateNotice(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addNotice(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -337,7 +333,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -276,19 +276,15 @@ export default {
|
||||
if (valid) {
|
||||
if (this.form.postId != undefined) {
|
||||
updatePost(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addPost(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -306,7 +302,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -319,7 +315,7 @@ export default {
|
||||
return exportPost(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -368,18 +368,18 @@ export default {
|
||||
// 所有菜单节点数据
|
||||
getMenuAllCheckedKeys() {
|
||||
// 目前被选中的菜单节点
|
||||
let checkedKeys = this.$refs.menu.getHalfCheckedKeys();
|
||||
let checkedKeys = this.$refs.menu.getCheckedKeys();
|
||||
// 半选中的菜单节点
|
||||
let halfCheckedKeys = this.$refs.menu.getCheckedKeys();
|
||||
let halfCheckedKeys = this.$refs.menu.getHalfCheckedKeys();
|
||||
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||
return checkedKeys;
|
||||
},
|
||||
// 所有部门节点数据
|
||||
getDeptAllCheckedKeys() {
|
||||
// 目前被选中的部门节点
|
||||
let checkedKeys = this.$refs.dept.getHalfCheckedKeys();
|
||||
let checkedKeys = this.$refs.dept.getCheckedKeys();
|
||||
// 半选中的部门节点
|
||||
let halfCheckedKeys = this.$refs.dept.getCheckedKeys();
|
||||
let halfCheckedKeys = this.$refs.dept.getHalfCheckedKeys();
|
||||
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
|
||||
return checkedKeys;
|
||||
},
|
||||
@ -440,7 +440,7 @@ export default {
|
||||
menuIds: [],
|
||||
deptIds: [],
|
||||
menuCheckStrictly: true,
|
||||
deptCheckStrictly: true,
|
||||
deptCheckStrictly: true,
|
||||
remark: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
@ -537,20 +537,16 @@ export default {
|
||||
if (this.form.roleId != undefined) {
|
||||
this.form.menuIds = this.getMenuAllCheckedKeys();
|
||||
updateRole(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
this.form.menuIds = this.getMenuAllCheckedKeys();
|
||||
addRole(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -561,11 +557,9 @@ export default {
|
||||
if (this.form.roleId != undefined) {
|
||||
this.form.deptIds = this.getDeptAllCheckedKeys();
|
||||
dataScope(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.openDataScope = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.openDataScope = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
},
|
||||
@ -581,7 +575,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -594,7 +588,7 @@ export default {
|
||||
return exportRole(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -421,14 +421,10 @@ export default {
|
||||
nickName: [
|
||||
{ required: true, message: "用户昵称不能为空", trigger: "blur" }
|
||||
],
|
||||
deptId: [
|
||||
{ required: true, message: "归属部门不能为空", trigger: "blur" }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: "用户密码不能为空", trigger: "blur" }
|
||||
],
|
||||
email: [
|
||||
{ required: true, message: "邮箱地址不能为空", trigger: "blur" },
|
||||
{
|
||||
type: "email",
|
||||
message: "'请输入正确的邮箱地址",
|
||||
@ -436,7 +432,6 @@ export default {
|
||||
}
|
||||
],
|
||||
phonenumber: [
|
||||
{ required: true, message: "手机号码不能为空", trigger: "blur" },
|
||||
{
|
||||
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
|
||||
message: "请输入正确的手机号码",
|
||||
@ -582,9 +577,7 @@ export default {
|
||||
cancelButtonText: "取消"
|
||||
}).then(({ value }) => {
|
||||
resetUserPwd(row.userId, value).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功,新密码是:" + value);
|
||||
}
|
||||
this.msgSuccess("修改成功,新密码是:" + value);
|
||||
});
|
||||
}).catch(() => {});
|
||||
},
|
||||
@ -594,19 +587,15 @@ export default {
|
||||
if (valid) {
|
||||
if (this.form.userId != undefined) {
|
||||
updateUser(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addUser(this.form).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -624,7 +613,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
@ -637,7 +626,7 @@ export default {
|
||||
return exportUser(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 导入按钮操作 */
|
||||
handleImport() {
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
<script>
|
||||
import { updateUserPwd } from "@/api/system/user";
|
||||
import Global from "@/layout/components/global.js";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -57,15 +58,14 @@ export default {
|
||||
if (valid) {
|
||||
updateUserPwd(this.user.oldPassword, this.user.newPassword).then(
|
||||
response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
close() {
|
||||
Global.$emit("removeCache", "closeSelectedTag", this.$route);
|
||||
this.$store.dispatch("tagsView/delView", this.$route);
|
||||
this.$router.push({ path: "/index" });
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<img v-bind:src="options.img" @click="editCropper()" title="点击上传头像" class="img-circle img-lg" />
|
||||
<div class="user-info-head" @click="editCropper()"><img v-bind:src="options.img" title="点击上传头像" class="img-circle img-lg" /></div>
|
||||
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body @opened="modalOpened">
|
||||
<el-row>
|
||||
<el-col :xs="24" :md="12" :style="{height: '350px'}">
|
||||
@ -27,7 +27,7 @@
|
||||
<el-col :lg="2" :md="2">
|
||||
<el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
|
||||
<el-button size="small">
|
||||
上传
|
||||
选择
|
||||
<i class="el-icon-upload el-icon--right"></i>
|
||||
</el-button>
|
||||
</el-upload>
|
||||
@ -125,12 +125,10 @@ export default {
|
||||
let formData = new FormData();
|
||||
formData.append("avatarfile", data);
|
||||
uploadAvatar(formData).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.open = false;
|
||||
this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl;
|
||||
store.commit('SET_AVATAR', this.options.img);
|
||||
this.msgSuccess("修改成功");
|
||||
}
|
||||
this.open = false;
|
||||
this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl;
|
||||
store.commit('SET_AVATAR', this.options.img);
|
||||
this.msgSuccess("修改成功");
|
||||
this.visible = false;
|
||||
});
|
||||
});
|
||||
@ -141,4 +139,29 @@ export default {
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.user-info-head {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.user-info-head:hover:after {
|
||||
content: '+';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
color: #eee;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
font-size: 24px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
cursor: pointer;
|
||||
line-height: 110px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
<script>
|
||||
import { updateUserProfile } from "@/api/system/user";
|
||||
import Global from "@/layout/components/global.js";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@ -62,14 +63,13 @@ export default {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
updateUserProfile(this.user).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.msgSuccess("修改成功");
|
||||
}
|
||||
this.msgSuccess("修改成功");
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
close() {
|
||||
Global.$emit("removeCache", "closeSelectedTag", this.$route);
|
||||
this.$store.dispatch("tagsView/delView", this.$route);
|
||||
this.$router.push({ path: "/index" });
|
||||
}
|
||||
|
||||
@ -90,6 +90,7 @@
|
||||
<el-option label="单选框" value="radio" />
|
||||
<el-option label="复选框" value="checkbox" />
|
||||
<el-option label="日期控件" value="datetime" />
|
||||
<el-option label="上传控件" value="uploadImage" />
|
||||
<el-option label="富文本控件" value="editor" />
|
||||
</el-select>
|
||||
</template>
|
||||
@ -126,6 +127,7 @@
|
||||
import { getGenTable, updateGenTable } from "@/api/tool/gen";
|
||||
import { optionselect as getDictOptionselect } from "@/api/system/dict/type";
|
||||
import { listMenu as getMenuTreeselect } from "@/api/system/menu";
|
||||
import Global from "@/layout/components/global.js";
|
||||
import basicInfoForm from "./basicInfoForm";
|
||||
import genInfoForm from "./genInfoForm";
|
||||
import Sortable from 'sortablejs'
|
||||
@ -206,6 +208,7 @@ export default {
|
||||
},
|
||||
/** 关闭按钮 */
|
||||
close() {
|
||||
Global.$emit("removeCache", "closeSelectedTag", this.$route);
|
||||
this.$store.dispatch("tagsView/delView", this.$route);
|
||||
this.$router.push({ path: "/tool/gen", query: { t: Date.now()}})
|
||||
}
|
||||
|
||||
@ -91,21 +91,21 @@
|
||||
align="center"
|
||||
prop="tableName"
|
||||
:show-overflow-tooltip="true"
|
||||
width="130"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
label="表描述"
|
||||
align="center"
|
||||
prop="tableComment"
|
||||
:show-overflow-tooltip="true"
|
||||
width="130"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
label="实体"
|
||||
align="center"
|
||||
prop="className"
|
||||
:show-overflow-tooltip="true"
|
||||
width="130"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="160" />
|
||||
<el-table-column label="更新时间" align="center" prop="updateTime" width="160" />
|
||||
@ -165,7 +165,7 @@
|
||||
:name="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))"
|
||||
:key="key"
|
||||
>
|
||||
<pre>{{ value }}</pre>
|
||||
<highlightjs autodetect :code="value" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-dialog>
|
||||
@ -177,6 +177,7 @@
|
||||
import { listTable, previewTable, delTable, genCode, synchDb } from "@/api/tool/gen";
|
||||
import importTable from "./importTable";
|
||||
import { downLoadZip } from "@/utils/zipdownload";
|
||||
|
||||
export default {
|
||||
name: "Gen",
|
||||
components: { importTable },
|
||||
@ -270,7 +271,7 @@ export default {
|
||||
return synchDb(tableName);
|
||||
}).then(() => {
|
||||
this.msgSuccess("同步成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
},
|
||||
/** 打开导入表弹窗 */
|
||||
openImportTable() {
|
||||
@ -313,7 +314,7 @@ export default {
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
}).catch(function() {});
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||