26 Commits
v2.2 ... v2.3.0

Author SHA1 Message Date
RuoYi
1abf802a09 若依 2.3.0 2020-11-20 08:39:32 +08:00
RuoYi
2bb0eb1edb 增加分布式文件FastDFS支持 2020-11-19 18:51:22 +08:00
RuoYi
1a12d56cc3 优化头像样式,鼠标移入悬停遮罩 2020-11-19 09:33:32 +08:00
RuoYi
45e5395550 README 2020-11-18 20:29:13 +08:00
RuoYi
692cc84693 README 2020-11-18 20:15:17 +08:00
RuoYi
b812e01100 新增文件服务应用 2020-11-18 19:57:55 +08:00
RuoYi
594329127f AjaxResult重写put方法,以方便链式调用 2020-11-18 16:49:01 +08:00
RuoYi
cdc813c453 代码生成支持上传控件 2020-11-17 20:37:41 +08:00
RuoYi
3d7fe2a288 Copyright 2018-2020 2020-11-17 20:36:59 +08:00
RuoYi
93920707b5 新增图片上传组件 2020-11-17 18:57:20 +08:00
RuoYi
84ffdaefe2 调整默认首页 2020-11-07 11:06:22 +08:00
RuoYi
0422f858f7 2020年双十一云服务器优惠,错过又要等一年 2020-11-04 16:59:04 +08:00
RuoYi
01c3019cea 添加新群号 2020-11-04 12:09:11 +08:00
JuJu
24fb0b712a 删除无用代码 2020-10-26 15:39:36 +08:00
JuJu
8fdcd576c9 修正hasRole匹配为equals 2020-10-23 16:00:39 +08:00
JuJu
07df90f99b 修正数组权限为空判断 2020-10-23 15:33:06 +08:00
RuoYi
7bd762267b 删除不必要的代码 2020-10-13 17:58:36 +08:00
RuoYi
512c6acebc 修正注释选中节点和半选节点获取 2020-10-13 17:44:56 +08:00
RuoYi
ad928ee719 升级pagehelper到最新版1.3.0 2020-10-13 17:43:03 +08:00
RuoYi
04d8c97c62 升级fastjson到最新版1.2.74 2020-10-13 17:41:28 +08:00
RuoYi
9fc5d74f6e 使用参数dateRange而非bind在model上的dateRange 2020-10-13 17:40:36 +08:00
RuoYi
f245105b58 修正定时任务执行一次权限标识 2020-10-13 17:39:25 +08:00
RuoYi
c0cc0bdf84 修复页签关闭所有固定标签路由不刷新问题 2020-10-13 17:38:38 +08:00
RuoYi
c04ea0221a 表单构建布局型组件新增按钮 2020-10-13 17:37:12 +08:00
RuoYi
d52f6673bc 调整日志路径到模块目录 2020-10-13 17:36:00 +08:00
RuoYi
dce8ee4236 修正菜单提示信息错误 2020-10-03 10:54:47 +08:00
88 changed files with 2457 additions and 519 deletions

View File

@@ -5,7 +5,8 @@
* 注册中心、配置中心选型Nacos权限认证使用Redis。 * 注册中心、配置中心选型Nacos权限认证使用Redis。
* 流量控制框架选型Sentinel。 * 流量控制框架选型Sentinel。
* 如需不分离应用,请移步 [RuoYi](https://gitee.com/y_project/RuoYi),如需分离应用,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) * 如需不分离应用,请移步 [RuoYi](https://gitee.com/y_project/RuoYi),如需分离应用,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)
* 阿里云优惠券[点我进入](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)  
#### 友情链接 [若依/RuoYi-Cloud](https://gitee.com/zhangmrit/ruoyi-cloud) Ant Design版本。 #### 友情链接 [若依/RuoYi-Cloud](https://gitee.com/zhangmrit/ruoyi-cloud) Ant Design版本。
@@ -29,6 +30,7 @@ com.ruoyi
│ └── ruoyi-system // 系统模块 [9201] │ └── ruoyi-system // 系统模块 [9201]
│ └── ruoyi-gen // 代码生成 [9202] │ └── ruoyi-gen // 代码生成 [9202]
│ └── ruoyi-job // 定时任务 [9203] │ └── ruoyi-job // 定时任务 [9203]
│ └── ruoyi-file // 文件服务 [9300]
├── ruoyi-visual // 图形化管理模块 ├── ruoyi-visual // 图形化管理模块
│ └── ruoyi-visual-monitor // 监控中心 [9100] │ └── ruoyi-visual-monitor // 监控中心 [9100]
├──pom.xml // 公共依赖 ├──pom.xml // 公共依赖
@@ -36,7 +38,7 @@ com.ruoyi
## 架构图 ## 架构图
<img src="https://oscimg.oschina.net/oscnet/up-aaa2d885b0fba37e52b56f0948edde1c4fe.png"/> <img src="https://oscimg.oschina.net/oscnet/up-8b9f92ed62f8aa17bd95999272f12a5927c.png"/>
## 内置功能 ## 内置功能
@@ -102,7 +104,7 @@ com.ruoyi
<td><img src="https://oscimg.oschina.net/oscnet/up-92ffb7f3835855cff100fa0f754a6be0d99.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-92ffb7f3835855cff100fa0f754a6be0d99.png"/></td>
</tr> </tr>
<tr> <tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-d69a19493e5aff7ecdd5d02410862bcea40.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-ff9e3066561574aca73005c5730c6a41f15.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-6d73c2140ce694e3de4c05035fdc1868d4c.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-6d73c2140ce694e3de4c05035fdc1868d4c.png"/></td>
</tr> </tr>
</table> </table>
@@ -110,4 +112,4 @@ com.ruoyi
## 若依微服务交流群 ## 若依微服务交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) 点击按钮入群。 QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) 点击按钮入群。

10
pom.xml
View File

@@ -6,14 +6,14 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>2.2.0</version> <version>2.3.0</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依微服务系统</description> <description>若依微服务系统</description>
<properties> <properties>
<ruoyi.version>2.2.0</ruoyi.version> <ruoyi.version>2.3.0</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
@@ -21,15 +21,15 @@
<spring-cloud.version>Hoxton.SR8</spring-cloud.version> <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version> <spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version>
<spring-boot-admin.version>2.3.0</spring-boot-admin.version> <spring-boot-admin.version>2.3.0</spring-boot-admin.version>
<spring-boot.mybatis>2.1.2</spring-boot.mybatis> <spring-boot.mybatis>2.1.3</spring-boot.mybatis>
<swagger.fox.version>2.9.2</swagger.fox.version> <swagger.fox.version>2.9.2</swagger.fox.version>
<swagger.core.version>1.5.24</swagger.core.version> <swagger.core.version>1.5.24</swagger.core.version>
<kaptcha.version>2.3.2</kaptcha.version> <kaptcha.version>2.3.2</kaptcha.version>
<pagehelper.boot.version>1.2.12</pagehelper.boot.version> <pagehelper.boot.version>1.3.0</pagehelper.boot.version>
<commons.io.version>2.5</commons.io.version> <commons.io.version>2.5</commons.io.version>
<commons.fileupload.version>1.3.3</commons.fileupload.version> <commons.fileupload.version>1.3.3</commons.fileupload.version>
<velocity.version>1.7</velocity.version> <velocity.version>1.7</velocity.version>
<fastjson.version>1.2.73</fastjson.version> <fastjson.version>1.2.74</fastjson.version>
<poi.version>3.17</poi.version> <poi.version>3.17</poi.version>
<common-pool.version>2.6.2</common-pool.version> <common-pool.version>2.6.2</common-pool.version>
</properties> </properties>

View File

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

View File

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

View File

@@ -0,0 +1,29 @@
package com.ruoyi.system.api;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.domain.SysFile;
import com.ruoyi.system.api.factory.RemoteFileFallbackFactory;
/**
* 文件服务
*
* @author ruoyi
*/
@FeignClient(contextId = "remoteFileService", value = ServiceNameConstants.FILE_SERVICE, fallbackFactory = RemoteFileFallbackFactory.class)
public interface RemoteFileService
{
/**
* 上传文件
*
* @param file 文件信息
* @return 结果
*/
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file);
}

View File

@@ -0,0 +1,50 @@
package com.ruoyi.system.api.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 文件信息
*
* @author ruoyi
*/
public class SysFile
{
/**
* 文件名称
*/
private String name;
/**
* 文件地址
*/
private String url;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("name", getName())
.append("url", getUrl())
.toString();
}
}

View File

@@ -0,0 +1,35 @@
package com.ruoyi.system.api.factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.RemoteFileService;
import com.ruoyi.system.api.domain.SysFile;
import feign.hystrix.FallbackFactory;
/**
* 文件服务降级处理
*
* @author ruoyi
*/
@Component
public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileService>
{
private static final Logger log = LoggerFactory.getLogger(RemoteFileFallbackFactory.class);
@Override
public RemoteFileService create(Throwable throwable)
{
log.error("文件服务调用失败:{}", throwable.getMessage());
return new RemoteFileService()
{
@Override
public R<SysFile> upload(MultipartFile file)
{
return R.fail("上传文件失败:" + throwable.getMessage());
}
};
}
}

View File

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

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/ruoyi-auth" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

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

View File

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

View File

@@ -74,6 +74,9 @@ public class GenConstants
/** 日期控件 */ /** 日期控件 */
public static final String HTML_DATETIME = "datetime"; public static final String HTML_DATETIME = "datetime";
/** 上传控件 */
public static final String HTML_UPLOAD_IMAGE = "uploadImage";
/** 富文本控件 */ /** 富文本控件 */
public static final String HTML_EDITOR = "editor"; public static final String HTML_EDITOR = "editor";

View File

@@ -16,4 +16,9 @@ public class ServiceNameConstants
* 系统模块的serviceid * 系统模块的serviceid
*/ */
public static final String SYSTEM_SERVICE = "ruoyi-system"; public static final String SYSTEM_SERVICE = "ruoyi-system";
/**
* 文件服务的serviceid
*/
public static final String FILE_SERVICE = "ruoyi-file";
} }

View File

@@ -0,0 +1,19 @@
package com.ruoyi.common.core.exception.file;
import com.ruoyi.common.core.exception.BaseException;
/**
* 文件信息异常类
*
* @author ruoyi
*/
public class FileException extends BaseException
{
private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args)
{
super("file", code, args, null);
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.core.exception.file;
/**
* 文件名称超长限制异常类
*
* @author ruoyi
*/
public class FileNameLengthLimitExceededException extends FileException
{
private static final long serialVersionUID = 1L;
public FileNameLengthLimitExceededException(int defaultFileNameLength)
{
super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.core.exception.file;
/**
* 文件名大小限制异常类
*
* @author ruoyi
*/
public class FileSizeLimitExceededException extends FileException
{
private static final long serialVersionUID = 1L;
public FileSizeLimitExceededException(long defaultMaxSize)
{
super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
}
}

View File

@@ -0,0 +1,81 @@
package com.ruoyi.common.core.exception.file;
import java.util.Arrays;
import org.apache.commons.fileupload.FileUploadException;
/**
* 文件上传 误异常类
*
* @author ruoyi
*/
public class InvalidExtensionException extends FileUploadException
{
private static final long serialVersionUID = 1L;
private String[] allowedExtension;
private String extension;
private String filename;
public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
{
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
this.allowedExtension = allowedExtension;
this.extension = extension;
this.filename = filename;
}
public String[] getAllowedExtension()
{
return allowedExtension;
}
public String getExtension()
{
return extension;
}
public String getFilename()
{
return filename;
}
public static class InvalidImageExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidFlashExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidMediaExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidVideoExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
}

View File

@@ -0,0 +1,47 @@
package com.ruoyi.common.core.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();
}
}

View File

@@ -7,7 +7,11 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import com.ruoyi.common.core.utils.StringUtils;
/** /**
* 文件处理工具类 * 文件处理工具类
@@ -16,6 +20,12 @@ import javax.servlet.http.HttpServletRequest;
*/ */
public class FileUtils extends org.apache.commons.io.FileUtils public class FileUtils extends org.apache.commons.io.FileUtils
{ {
/** 字符常量:斜杠 {@code '/'} */
public static final char SLASH = '/';
/** 字符常量:反斜杠 {@code '\\'} */
public static final char BACKSLASH = '\\';
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/** /**
@@ -104,6 +114,30 @@ public class FileUtils extends org.apache.commons.io.FileUtils
return filename.matches(FILENAME_PATTERN); 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 +145,7 @@ public class FileUtils extends org.apache.commons.io.FileUtils
* @param fileName 文件名 * @param fileName 文件名
* @return 编码后的文件名 * @return 编码后的文件名
*/ */
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
throws UnsupportedEncodingException
{ {
final String agent = request.getHeader("USER-AGENT"); final String agent = request.getHeader("USER-AGENT");
String filename = fileName; String filename = fileName;
@@ -139,4 +172,89 @@ public class FileUtils extends org.apache.commons.io.FileUtils
} }
return filename; return filename;
} }
/**
* 返回文件名
*
* @param filePath 文件
* @return 文件名
*/
public static String getName(String filePath)
{
if (null == filePath)
{
return null;
}
int len = filePath.length();
if (0 == len)
{
return filePath;
}
if (isFileSeparator(filePath.charAt(len - 1)))
{
// 以分隔符结尾的去掉结尾分隔符
len--;
}
int begin = 0;
char c;
for (int i = len - 1; i > -1; i--)
{
c = filePath.charAt(i);
if (isFileSeparator(c))
{
// 查找最后一个路径分隔符(/或者\
begin = i + 1;
break;
}
}
return filePath.substring(begin, len);
}
/**
* 是否为Windows或者LinuxUnix文件分隔符<br>
* Windows平台下分隔符为\LinuxUnix为/
*
* @param c 字符
* @return 是否为Windows或者LinuxUnix文件分隔符
*/
public static boolean isFileSeparator(char c)
{
return SLASH == c || BACKSLASH == c;
}
/**
* 下载文件名重新编码
*
* @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");
}
} }

View File

@@ -0,0 +1,59 @@
package com.ruoyi.common.core.utils.file;
/**
* 媒体类型工具类
*
* @author ruoyi
*/
public class MimeTypeUtils
{
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_JPG = "image/jpg";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif";
public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
public static final String[] FLASH_EXTENSION = { "swf", "flv" };
public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
"asf", "rm", "rmvb" };
public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf
"pdf" };
public static String getExtension(String prefix)
{
switch (prefix)
{
case IMAGE_PNG:
return "png";
case IMAGE_JPG:
return "jpg";
case IMAGE_JPEG:
return "jpeg";
case IMAGE_BMP:
return "bmp";
case IMAGE_GIF:
return "gif";
default:
return "";
}
}
}

View File

@@ -57,6 +57,20 @@ public class AjaxResult extends HashMap<String, Object>
super.put(DATA_TAG, data); super.put(DATA_TAG, data);
} }
} }
/**
* 方便链式调用
*
* @param key
* @param value
* @return
*/
@Override
public AjaxResult put(String key, Object value)
{
super.put(key, value);
return this;
}
/** /**
* 返回成功消息 * 返回成功消息

View File

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

View File

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

View File

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

View File

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

View File

@@ -35,6 +35,9 @@ public class PreAuthorizeAspect
/** 管理员角色权限标识 */ /** 管理员角色权限标识 */
private static final String SUPER_ADMIN = "admin"; private static final String SUPER_ADMIN = "admin";
/** 数组为0时 */
private static final Integer ARRAY_EMPTY = 0;
@Around("@annotation(com.ruoyi.common.security.annotation.PreAuthorize)") @Around("@annotation(com.ruoyi.common.security.annotation.PreAuthorize)")
public Object around(ProceedingJoinPoint point) throws Throwable public Object around(ProceedingJoinPoint point) throws Throwable
{ {
@@ -63,7 +66,7 @@ public class PreAuthorizeAspect
} }
throw new PreAuthorizeException(); throw new PreAuthorizeException();
} }
else if (!StringUtils.isEmpty(annotation.hasAnyPermi())) else if (ARRAY_EMPTY < annotation.hasAnyPermi().length)
{ {
if (hasAnyPermi(annotation.hasAnyPermi())) if (hasAnyPermi(annotation.hasAnyPermi()))
{ {
@@ -87,7 +90,7 @@ public class PreAuthorizeAspect
} }
throw new PreAuthorizeException(); throw new PreAuthorizeException();
} }
else if (!StringUtils.isEmpty(annotation.hasAnyRoles())) else if (ARRAY_EMPTY < annotation.hasAnyRoles().length)
{ {
if (hasAnyRoles(annotation.hasAnyRoles())) if (hasAnyRoles(annotation.hasAnyRoles()))
{ {
@@ -165,7 +168,7 @@ public class PreAuthorizeAspect
} }
for (String roleKey : userInfo.getRoles()) for (String roleKey : userInfo.getRoles())
{ {
if (SUPER_ADMIN.contains(roleKey) || roleKey.contains(role)) if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(role))
{ {
return true; return true;
} }

View File

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

View File

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

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/ruoyi-gateway" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>2.2.0</version> <version>2.3.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -12,6 +12,7 @@
<module>ruoyi-system</module> <module>ruoyi-system</module>
<module>ruoyi-gen</module> <module>ruoyi-gen</module>
<module>ruoyi-job</module> <module>ruoyi-job</module>
<module>ruoyi-file</module>
</modules> </modules>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>2.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-modules-file</artifactId>
<description>
ruoyi-modules-file文件服务
</description>
<dependencies>
<!-- SpringCloud Ailibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Ailibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Ailibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- FastDFS -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.5</version>
</dependency>
<!-- Ruoyi Common Security -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-security</artifactId>
</dependency>
<!-- Ruoyi Common Swagger -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,35 @@
package com.ruoyi.file;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
/**
* 文件服务
*
* @author ruoyi
*/
@EnableCustomSwagger2
@EnableRyFeignClients
@EnableDiscoveryClient
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class RuoYFileApplication
{
public static void main(String[] args)
{
SpringApplication.run(RuoYFileApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 文件服务模块启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}

View File

@@ -0,0 +1,36 @@
package com.ruoyi.file.config;
import java.io.File;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 通用映射配置
*
* @author ruoyi
*/
@Configuration
public class ResourcesConfig implements WebMvcConfigurer
{
/**
* 上传文件存储在本地的根路径
*/
@Value("${file.path}")
private String localFilePath;
/**
* 资源映射路径 前缀
*/
@Value("${file.prefix}")
public String localFilePrefix;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
/** 本地文件上传路径 */
registry.addResourceHandler(localFilePrefix + "/**")
.addResourceLocations("file:" + localFilePath + File.separator);
}
}

View File

@@ -0,0 +1,55 @@
package com.ruoyi.file.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.system.api.domain.SysFile;
/**
* 文件请求处理
*
* @author ruoyi
*/
@RestController
public class SysFileController
{
private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
/**
* 上传文件存储在本地的根路径
*/
@Value("${file.path}")
private String localFilePath;
@Autowired
private ISysFileService sysFileService;
/**
* 文件上传请求
*/
@PostMapping("upload")
public R<SysFile> upload(MultipartFile file)
{
try
{
// 上传并返回访问地址
String url = sysFileService.uploadFile(file, localFilePath);
SysFile sysFile = new SysFile();
sysFile.setName(FileUtils.getName(url));
sysFile.setUrl(url);
return R.ok(sysFile);
}
catch (Exception e)
{
log.error("上传文件失败", e);
return R.fail(e.getMessage());
}
}
}

View File

@@ -0,0 +1,43 @@
package com.ruoyi.file.service;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
/**
* FastDFS文件存储
*
* @author ruoyi
*/
@Service
public class FastDfsSysFileServiceImpl implements ISysFileService
{
/**
* 域名或本机访问地址
*/
@Value("${fdfs.domain}")
public String domain;
@Autowired
private FastFileStorageClient storageClient;
/**
* FastDfs文件上传接口
*
* @param file 上传的文件
* @param baseDir 相对应用的基目录
* @return 访问地址
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file, String baseDir) throws Exception
{
StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
FilenameUtils.getExtension(file.getOriginalFilename()), null);
return domain + "/" + storePath.getFullPath();
}
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.file.service;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件上传接口
*
* @author ruoyi
*/
public interface ISysFileService
{
/**
* 文件上传接口
*
* @param file 上传的文件
* @param baseDir 相对应用的基目录
* @return 访问地址
* @throws Exception
*/
public String uploadFile(MultipartFile file, String baseDir) throws Exception;
}

View File

@@ -0,0 +1,44 @@
package com.ruoyi.file.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.file.utils.FileUploadUtils;
/**
* 本地文件存储
*
* @author ruoyi
*/
@Primary
@Service
public class LocalSysFileServiceImpl implements ISysFileService
{
/**
* 资源映射路径 前缀
*/
@Value("${file.prefix}")
public String localFilePrefix;
/**
* 域名或本机访问地址
*/
@Value("${file.domain}")
public String domain;
/**
* 本地文件上传接口
*
* @param file 上传的文件
* @param baseDir 相对应用的基目录
* @return 访问地址
* @throws Exception
*/
public String uploadFile(MultipartFile file, String baseDir) throws Exception
{
String name = FileUploadUtils.upload(baseDir, file);
String url = domain + localFilePrefix + name;
return url;
}
}

View File

@@ -0,0 +1,204 @@
package com.ruoyi.file.utils;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.core.exception.file.InvalidExtensionException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.IdUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.MimeTypeUtils;
/**
* 文件上传工具类
*
* @author ruoyi
*/
public class FileUploadUtils
{
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 资源映射路径 前缀
*/
@Value("${file.prefix}")
public String localFilePrefix;
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param extension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = file.getOriginalFilename().length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
File desc = getAbsoluteFile(baseDir, fileName);
file.transferTo(desc);
String pathFileName = getPathFileName(fileName);
return pathFileName;
}
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file)
{
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
return fileName;
}
private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc;
}
private static final String getPathFileName(String fileName) throws IOException
{
String pathFileName = "/" + fileName;
return pathFileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @return
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException
{
long size = file.getSize();
if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE)
{
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
{
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
{
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
{
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
{
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
{
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
}
else
{
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension
* @param allowedExtension
* @return
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
{
for (String str : allowedExtension)
{
if (str.equalsIgnoreCase(extension))
{
return true;
}
}
return false;
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public static final String getExtension(MultipartFile file)
{
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension))
{
extension = MimeTypeUtils.getExtension(file.getContentType());
}
return extension;
}
}

View File

@@ -0,0 +1,10 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
_ __ _ _
(_) / _|(_)| |
_ __ _ _ ___ _ _ _ ______ | |_ _ | | ___
| '__|| | | | / _ \ | | | || ||______|| _|| || | / _ \
| | | |_| || (_) || |_| || | | | | || || __/
|_| \__,_| \___/ \__, ||_| |_| |_||_| \___|
__/ |
|___/

View File

@@ -0,0 +1,24 @@
# Tomcat
server:
port: 9300
# Spring
spring:
application:
# 应用名称
name: ruoyi-file
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/ruoyi-file" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>2.2.0</version> <version>2.3.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -60,7 +60,7 @@ public class GenTableColumn extends BaseEntity
/** 查询方式EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围 */ /** 查询方式EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围 */
private String queryType; private String queryType;
/** 显示类型input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、editor富文本控件 */ /** 显示类型input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、upload上传控件、editor富文本控件 */
private String htmlType; private String htmlType;
/** 字典类型 */ /** 字典类型 */

View File

@@ -111,6 +111,11 @@ public class GenUtils
{ {
column.setHtmlType(GenConstants.HTML_SELECT); column.setHtmlType(GenConstants.HTML_SELECT);
} }
// 文件字段设置上传控件
else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
{
column.setHtmlType(GenConstants.HTML_UPLOAD_IMAGE);
}
// 内容字段设置富文本控件 // 内容字段设置富文本控件
else if (StringUtils.endsWithIgnoreCase(columnName, "content")) else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
{ {

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false"> <configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 --> <!-- 日志存放路径 -->
<property name="log.path" value="/home/ruoyi/logs/ruoyi-gen" /> <property name="log.path" value="logs/ruoyi-gen" />
<!-- 日志输出格式 --> <!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />:ss} %-5level ${springAppName:-} %thread %logger %msg%n"/> <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 --> <!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">

View File

@@ -139,6 +139,10 @@
<el-form-item label="${comment}" prop="${field}"> <el-form-item label="${comment}" prop="${field}">
<el-input v-model="form.${field}" placeholder="请输入${comment}" /> <el-input v-model="form.${field}" placeholder="请输入${comment}" />
</el-form-item> </el-form-item>
#elseif($column.htmlType == "uploadImage")
<el-form-item label="${comment}">
<uploadImage v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "editor") #elseif($column.htmlType == "editor")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<editor v-model="form.${field}" :min-height="192"/> <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 Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import "@riophae/vue-treeselect/dist/vue-treeselect.css";
#foreach($column in $columns) #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") #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
import Editor from '@/components/Editor'; import Editor from '@/components/Editor';
#break #break
@@ -236,6 +246,12 @@ export default {
name: "${BusinessName}", name: "${BusinessName}",
components: { components: {
#foreach($column in $columns) #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") #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
Editor, Editor,
#break #break
@@ -420,19 +436,15 @@ export default {
#end #end
if (this.form.${pkColumn.javaField} != null) { if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -449,7 +461,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
} }
} }
}; };

View File

@@ -168,6 +168,10 @@
<el-form-item label="${comment}" prop="${field}"> <el-form-item label="${comment}" prop="${field}">
<el-input v-model="form.${field}" placeholder="请输入${comment}" /> <el-input v-model="form.${field}" placeholder="请输入${comment}" />
</el-form-item> </el-form-item>
#elseif($column.htmlType == "uploadImage")
<el-form-item label="${comment}">
<uploadImage v-model="form.${field}"/>
</el-form-item>
#elseif($column.htmlType == "editor") #elseif($column.htmlType == "editor")
<el-form-item label="${comment}"> <el-form-item label="${comment}">
<editor v-model="form.${field}" :min-height="192"/> <editor v-model="form.${field}" :min-height="192"/>
@@ -253,6 +257,12 @@
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}"; import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
#foreach($column in $columns) #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") #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
import Editor from '@/components/Editor'; import Editor from '@/components/Editor';
#break #break
@@ -261,12 +271,20 @@ import Editor from '@/components/Editor';
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
components: {
#foreach($column in $columns) #foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor") #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage")
components: { Editor }, UploadImage,
#break #break
#end #end
#end #end
#foreach($column in $columns)
#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
Editor,
#break
#end
#end
},
data() { data() {
return { return {
// 遮罩层 // 遮罩层
@@ -436,19 +454,15 @@ export default {
#end #end
if (this.form.${pkColumn.javaField} != null) { if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -466,7 +480,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>2.2.0</version> <version>2.3.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false"> <configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 --> <!-- 日志存放路径 -->
<property name="log.path" value="/home/ruoyi/logs/ruoyi-job" /> <property name="log.path" value="logs/ruoyi-job" />
<!-- 日志输出格式 --> <!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />:ss} %-5level ${springAppName:-} %thread %logger %msg%n"/> <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 --> <!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>2.2.0</version> <version>2.3.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -118,11 +118,11 @@ public class SysMenuController extends BaseController
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) else if (UserConstants.YES_FRAME.equals(menu.getIsFrame())
&& !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS)) && !StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS))
{ {
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头"); return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
} }
else if (menu.getMenuId().equals(menu.getParentId())) else if (menu.getMenuId().equals(menu.getParentId()))
{ {
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
} }
menu.setUpdateBy(SecurityUtils.getUsername()); menu.setUpdateBy(SecurityUtils.getUsername());
return toAjax(menuService.updateMenu(menu)); return toAjax(menuService.updateMenu(menu));

View File

@@ -1,17 +1,26 @@
package com.ruoyi.system.controller; package com.ruoyi.system.controller;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.service.TokenService; import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.RemoteFileService;
import com.ruoyi.system.api.domain.SysFile;
import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser; import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
@@ -30,6 +39,9 @@ public class SysProfileController extends BaseController
@Autowired @Autowired
private TokenService tokenService; private TokenService tokenService;
@Autowired
private RemoteFileService remoteFileService;
/** /**
* 个人信息 * 个人信息
@@ -94,4 +106,33 @@ public class SysProfileController extends BaseController
} }
return AjaxResult.error("修改密码异常,请联系管理员"); return AjaxResult.error("修改密码异常,请联系管理员");
} }
/**
* 头像上传
*/
@Log(title = "用户头像", businessType = BusinessType.UPDATE)
@PostMapping("/avatar")
public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws IOException
{
if (!file.isEmpty())
{
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
R<SysFile> fileResult = remoteFileService.upload(file);
if (StringUtils.isNull(fileResult) || StringUtils.isNull(fileResult.getData()))
{
return AjaxResult.error("文件服务异常,请联系管理员");
}
String url = fileResult.getData().getUrl();
if (userService.updateUserAvatar(loginUser.getUsername(), url))
{
AjaxResult ajax = AjaxResult.success();
ajax.put("imgUrl", url);
// 更新缓存用户头像
loginUser.getSysUser().setAvatar(url);
tokenService.setLoginUser(loginUser);
return ajax;
}
}
return AjaxResult.error("上传图片异常,请联系管理员");
}
} }

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false"> <configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 --> <!-- 日志存放路径 -->
<property name="log.path" value="/home/ruoyi/logs/ruoyi-system" /> <property name="log.path" value="logs/ruoyi-system" />
<!-- 日志输出格式 --> <!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />:ss} %-5level ${springAppName:-} %thread %logger %msg%n"/> <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 --> <!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">

View File

@@ -1,6 +1,6 @@
{ {
"name": "ruoyi", "name": "ruoyi",
"version": "2.2.0", "version": "2.3.0",
"description": "若依管理系统", "description": "若依管理系统",
"author": "若依", "author": "若依",
"license": "MIT", "license": "MIT",

View 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="1588670460195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1314" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M230.4 307.712c13.824 0 25.088-11.264 25.088-25.088 0-100.352 81.92-182.272 182.272-182.272s182.272 81.408 182.272 182.272c0 13.824 11.264 25.088 25.088 25.088s25.088-11.264 24.576-25.088c0-127.488-103.936-231.936-231.936-231.936S205.824 154.624 205.824 282.624c-0.512 14.336 10.752 25.088 24.576 25.088z m564.736 234.496c-11.264 0-21.504 2.048-31.232 6.144 0-44.544-40.448-81.92-88.064-81.92-14.848 0-28.16 3.584-39.936 10.24-13.824-28.16-44.544-48.128-78.848-48.128-12.288 0-24.576 2.56-35.328 7.68V284.16c0-45.568-37.888-81.92-84.48-81.92s-84.48 36.864-84.48 81.92v348.672l-69.12-112.64c-18.432-28.16-58.368-36.864-91.136-19.968-26.624 14.336-46.592 47.104-30.208 88.064 3.072 8.192 76.8 205.312 171.52 311.296 0 0 28.16 24.576 43.008 58.88 4.096 9.728 13.312 15.36 22.528 15.36 3.072 0 6.656-0.512 9.728-2.048 12.288-5.12 18.432-19.968 12.8-32.256-19.456-44.544-53.76-74.752-53.76-74.752C281.6 768 209.408 573.44 208.384 570.88c-5.12-12.8-2.56-20.992 7.168-26.112 9.216-4.608 21.504-4.608 26.112 2.56l113.152 184.32c4.096 8.704 12.8 14.336 22.528 14.336 13.824 0 25.088-10.752 25.088-25.088V284.16c0-17.92 15.36-32.256 34.816-32.256s34.816 14.336 34.816 32.256v284.16c0 13.824 10.24 25.088 24.576 25.088 13.824 0 25.088-11.264 25.088-25.088v-57.344c0-17.92 15.36-32.768 34.816-32.768 19.968 0 37.376 15.36 37.376 32.768v95.232c0 7.168 3.072 13.312 7.68 17.92 4.608 4.608 10.752 7.168 17.92 7.168 13.824 0 24.576-11.264 24.576-25.088V547.84c0-18.432 13.824-32.256 32.256-32.256 20.48 0 38.912 15.36 38.912 32.256v95.232c0 13.824 11.264 25.088 25.088 25.088s24.576-11.264 25.088-25.088v-18.944c0-18.944 12.8-32.256 30.72-32.256 18.432 0 22.528 18.944 22.528 31.744 0 1.024-11.776 99.84-50.688 173.056-30.72 58.368-45.056 112.128-51.2 146.944-2.56 13.312 6.656 26.112 19.968 28.672 1.536 0 3.072 0.512 4.608 0.512 11.776 0 22.016-8.192 24.064-20.48 5.632-31.232 18.432-79.36 46.08-132.608 43.52-81.92 55.808-186.88 56.32-193.536-0.512-50.688-29.696-83.968-72.704-83.968z"></path></path></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View 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 + "/file/upload", // 上传的图片服务器地址
headers: {
Authorization: "Bearer " + getToken(),
},
};
},
props: {
value: {
type: String,
default: "",
},
},
methods: {
handleUploadSuccess(res) {
this.$emit("input", res.data.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>

View File

@@ -160,7 +160,7 @@ export default {
}, },
closeAllTags(view) { closeAllTags(view) {
this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => { this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
if (this.affixTags.some(tag => tag.path === view.path)) { if (this.affixTags.some(tag => tag.path === this.$route.path)) {
return return
} }
this.toLastView(visitedViews, view) this.toLastView(visitedViews, view)

View File

@@ -57,7 +57,7 @@ const user = {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
getInfo(state.token).then(res => { getInfo(state.token).then(res => {
const user = res.user 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/image/profile.jpg") : user.avatar;
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', res.roles) commit('SET_ROLES', res.roles)
commit('SET_PERMISSIONS', res.permissions) commit('SET_PERMISSIONS', res.permissions)

View File

@@ -406,6 +406,21 @@ export const layoutComponents = [
layoutTree: true, layoutTree: true,
children: [], children: [],
document: 'https://element.eleme.cn/#/zh-CN/component/layout' document: 'https://element.eleme.cn/#/zh-CN/component/layout'
},
{
layout: 'colFormItem',
label: '按钮',
changeTag: true,
labelWidth: null,
tag: 'el-button',
tagIcon: 'button',
span: 24,
default: '主要按钮',
type: 'primary',
icon: 'el-icon-search',
size: 'medium',
disabled: false,
document: 'https://element.eleme.cn/#/zh-CN/component/button'
} }
] ]

View File

@@ -107,6 +107,18 @@ const layouts = {
} }
const tags = { const tags = {
'el-button': el => {
const {
tag, disabled
} = attrBuilder(el)
const type = el.type ? `type="${el.type}"` : ''
const icon = el.icon ? `icon="${el.icon}"` : ''
const size = el.size ? `size="${el.size}"` : ''
let child = buildElButtonChild(el)
if (child) child = `\n${child}\n` // 换行
return `<${el.tag} ${type} ${icon} ${size} ${disabled}>${child}</${el.tag}>`
},
'el-input': el => { 'el-input': el => {
const { const {
disabled, vModel, clearable, placeholder, width disabled, vModel, clearable, placeholder, width
@@ -272,6 +284,15 @@ function attrBuilder(el) {
} }
} }
// el-buttin 子级
function buildElButtonChild(conf) {
const children = []
if (conf.default) {
children.push(conf.default)
}
return children.join('\n')
}
// el-input innerHTML // el-input innerHTML
function buildElInputChild(conf) { function buildElInputChild(conf) {
const children = [] const children = []

View File

@@ -26,6 +26,11 @@ function vModel(self, dataObject, defaultValue) {
} }
const componentChild = { const componentChild = {
'el-button': {
default(h, conf, key) {
return conf[key]
},
},
'el-input': { 'el-input': {
prepend(h, conf, key) { prepend(h, conf, key) {
return <template slot="prepend">{conf[key]}</template> return <template slot="prepend">{conf[key]}</template>

View File

@@ -59,8 +59,8 @@ export function addDateRange(params, dateRange) {
search.beginTime = ""; search.beginTime = "";
search.endTime = ""; search.endTime = "";
if (null != dateRange && '' != dateRange) { if (null != dateRange && '' != dateRange) {
search.beginTime = this.dateRange[0]; search.beginTime = dateRange[0];
search.endTime = this.dateRange[1]; search.endTime = dateRange[1];
} }
return search; return search;
} }

View File

@@ -1,98 +1,434 @@
<template> <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
>
&nbsp;&nbsp;&nbsp; 腾讯云服务器秒杀区
<el-link href="http://txy.ruoyi.vip" type="primary" target="_blank"
>>点我进入</el-link
><br />
<h4 class="text-danger">
云产品通用红包可叠加官网常规优惠使用(仅限新用户)
</h4>
</blockquote>
<panel-group @handleSetLineChartData="handleSetLineChartData" /> <hr />
<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-col>
</el-row> </el-row>
<el-row :gutter="20">
<el-col :sm="24" :lg="12" style="padding-left: 20px">
<h2>若依后台管理框架</h2>
<p>
一直想做一款后台管理系统看了很多优秀的开源项目但是发现没有合适自己的于是利用空闲休息时间开始自己写一套后台系统如此有了若依管理系统她可以用于所有的Web应用程序如网站管理后台网站会员中心CMSCRMOA等等当然您也可以对她进行深度定制以做出更强系统所有前端后台代码封装过后十分精简易上手出错概率低同时支持移动客户端访问系统会陆续更新一些实用功能
</p>
<p>
<b>当前版本:</b> <span>v{{ version }}</span>
</p>
<p>
<el-tag type="danger">&yen;免费开源</el-tag>
</p>
<p>
<el-button
type="primary"
size="mini"
icon="el-icon-cloudy"
plain
@click="goTarget('https://gitee.com/y_project/RuoYi-Cloud')"
>访问码云</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>SpringCloud</li>
<li>Nacos</li>
<li>Sentinel</li>
<li>MyBatis</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>满42799195</s>
<s>满170157040</s>
<a
href="https://jq.qq.com/?_wv=1027&k=MI9Ro7lk"
target="_blank"
>
130643120</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="v2.3.0 - 2020-11-20">
<ol>
<li>新增文件服务应用支持本地FastDFS</li>
<li>优化头像样式鼠标移入悬停遮罩</li>
<li>AjaxResult重写put方法以方便链式调用</li>
<li>代码生成支持上传控件</li>
<li>新增图片上传组件</li>
<li>支持用户头像更新</li>
<li>调整默认首页</li>
<li>角色权限验证hasRole匹配改为equals</li>
<li>修正数组权限为空判断</li>
<li>修正注释选中节点和半选节点获取</li>
<li>升级pagehelper到最新版1.3.0</li>
<li>升级fastjson到最新版1.2.74</li>
<li>修正定时任务执行一次权限标识</li>
<li>修复页签关闭所有固定标签路由不刷新问题</li>
<li>表单构建布局型组件新增按钮</li>
<li>调整日志路径到模块目录</li>
<li>修正菜单提示信息错误</li>
<li>其他细节优化</li>
</ol>
</el-collapse-item>
<el-collapse-item title="v2.2.0 - 2020-10-10">
<ol>
<li>移除 OAuth2 改为 Redis</li>
<li>升级SpringCloud到最新版本Hoxton.SR8</li>
<li>升级SpringCloud Alibaba到最新版本2.2.3</li>
<li>升级SpringBoot Admin到最新版本2.3.0</li>
<li>升级Fastjson到最新版1.2.73</li>
<li>新增在线用户会话管理</li>
<li>修改用户个人资料/密码同步缓存信息</li>
<li>修复前端通用导出方法参数传值请求方式问题</li>
<li>菜单新增是否缓存keep-alive</li>
<li>菜单&数据权限新增展开/折叠 全选/全不选 父子联动</li>
<li>Job与Gen模块增加Redis默认配置</li>
<li>新增表格右侧工具栏组件right-toolbar</li>
<li>代码生成支持同步数据库</li>
<li>代码生成支持富文本控件</li>
<li>代码生成树模板去掉多余双引号</li>
<li>代码生成添加select必填选项</li>
<li>代码生成页面时不忽略remark属性</li>
<li>修复代码生成下载路径错误</li>
<li>左侧菜单文字过长显示省略号</li>
<li>表格操作列间距调整</li>
<li>Excel注解支持自动统计数据总和</li>
<li>Excel注解支持设置BigDecimal精度&舍入规则</li>
<li>导入Excel整形值校验优化</li>
<li>导出Excel类型NUMERIC支持精度浮点类型</li>
<li>导出Excel调整targetAttr获取值方法防止get方法不规范</li>
<li>Token续期调整为后端刷新</li>
<li>Token设置默认有效期时长12小时</li>
<li>网关白名单放入nacos配置&支持模糊匹配</li>
<li>修复富文本工具栏样式不对齐问题</li>
<li>Editor组件优化支持自定义高度&图片冲突问题</li>
<li>
修复富文本空格和缩进保存后不生效问题&删除重复的placeholder
</li>
<li>限制系统内置参数不允许删除</li>
<li>修正调用目标字符串最大长度</li>
<li>修改自定义权限实现</li>
<li>优化递归菜单&部门子节点</li>
<li>修改sass为node-sass避免el-icon图标乱码</li>
<li>修复根节点为子部门时树状结构显示问题</li>
<li>全局异常状态汉化拦截处理</li>
<li>唯一限制条件只返回单条数据</li>
<li>其他细节优化</li>
</ol>
</el-collapse-item>
<el-collapse-item title="v2.1.0 - 2020-08-02">
<ol>
<li>表格工具栏右侧添加刷新&显隐查询栏</li>
<li>OAuth自动刷新续签Token</li>
<li>网关支持黑名单配置</li>
<li>权限配置自动注册</li>
<li>Feign配置自动注册</li>
<li>代码生成支持选择上级菜单</li>
<li>代码生成支持复选框</li>
<li>代码生成支持自定义路径</li>
<li>验证码类型支持数组计算字符验证</li>
<li>Excel支持sort导出排序</li>
<li>Excel支持分割字符串组内容</li>
<li>excel 导入数字不需要格式化 导入允许列和属性个数不一致</li>
<li>新增菜单默认主类目</li>
<li>升级vue-cli版本到4.4.4</li>
<li>修改 node-sass dart-sass</li>
<li>升级element-ui版本到2.13.2</li>
<li>删除babel提高编译速度</li>
<li>修复验证码异常时network面板的中文会出现乱码问题</li>
<li>修复 utils/index.js 中不包含 parseTime 函数的 bug</li>
<li>优化selectDictLabel方法数组迭代器换为some</li>
<li>修复客户端模式认证会出现错误</li>
<li>检查字符支持小数点&降级改成异常提醒</li>
<li>定时任务添加cron表达式验证</li>
<li>代码生成查询条件修正</li>
<li>修正角色管理导出权限权限字符</li>
<li>修正防止切换权限用户后登录出现404</li>
<li>终端设置安全码加密&更新缓存</li>
<li>修复头像上传成功二次打开无法改变裁剪框大小和位置问题</li>
<li>修复布局为small者mini用户表单显示错位问题</li>
<li>修复代码生成点击多次表修改数据不变化的问题</li>
<li>修复代码生成导入表结构出现异常页面不提醒问题</li>
<li>修复角色权限修改时已有权限未自动勾选异常</li>
<li>创建用户不允许选择系统管理员角色</li>
<li>添加全局异常处理网关异常&业务异常</li>
<li>修复终端查询Enter键搜索时是刷新页面而不是查询列表</li>
<li>删除job重复表单参数</li>
<li>代码生成浮点型改用BigDecimal</li>
<li>表单类型为Integer/Long设置整形默认值</li>
<li>修改用户管理复选框宽度防止部分浏览器出现省略号</li>
<li>
RedisCache中所有方法参数添加final并优化list取出效率添加其它常用redis方法
</li>
<li>修正定时任务日志权限字符</li>
<li>添加Jackson时区配置</li>
<li>代码生成相关问题修复</li>
<li>自定义oauth2返回异常信息</li>
<li>升级nacos到最新版1.3.0 全新内核构建</li>
<li>修正代码生成功能无法下载的问题</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="v2.0.0 - 2020-06-10">
<ol>
<li>使用Sentinel代替Hystrix</li>
<li>菜单新增终端管理配置</li>
<li>菜单新增Nacos&Sentinel控制台</li>
<li>代码生成适配Cloud</li>
<li>记录登录退出日志信息</li>
<li>网关验证码过滤器添加放行校验</li>
<li>个性化的定制自动加载类</li>
<li>定时任务调整label-width防止部署出现错位</li>
<li>调整表头固定列默认样式</li>
<li>代码生成模板调整字段为String并且必填则加空串条件</li>
<li>代码生成字典Integer/Long使用parseInt</li>
<li>修复退出登录重定向到登录页登录后参数丢失</li>
<li>修正岗位导出权限注解</li>
<li>修复首页搜索菜单外链无法点击跳转问题</li>
<li>修复菜单管理选择图标backspace删除时不过滤数据</li>
<li>用户管理部门分支节点不可检查&显示计数</li>
<li>数据范围过滤属性调整</li>
<li>字典管理添加缓存读取</li>
<li>参数管理支持缓存操作</li>
<li>升级fastjson到最新版1.2.70 修复高危安全漏洞</li>
<li>dev启动默认打开浏览器</li>
<li>使用vue-cli默认source-map</li>
<li>slidebar eslint报错优化</li>
<li>当tags-view滚动关闭右键菜单</li>
<li>支持一级菜单和主页同级在main区域显示</li>
<li>限制外链地址必须以http(s)😕/开头</li>
<li>tagview & sidebar 主题颜色与element ui(全局)同步</li>
<li>
修复dict_sort不可update为0的问题&查询返回增加dict_sort升序排序
</li>
<li>权限部分代码调整</li>
<li>其他细节优化</li>
</ol>
</el-collapse-item>
<el-collapse-item title="v1.0.0 - 2020-05-20">
<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> </div>
</template> </template>
<script> <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 { export default {
name: 'Index', name: "index",
components: {
PanelGroup,
LineChart,
RaddarChart,
PieChart,
BarChart
},
data() { data() {
return { return {
lineChartData: lineChartData.newVisitis // 版本号
} version: "2.3.0",
};
}, },
methods: { methods: {
handleSetLineChartData(type) { goTarget(href) {
this.lineChartData = lineChartData[type] window.open(href, "_blank");
} },
} },
} };
</script> </script>
<style lang="scss" scoped> <style scoped lang="scss">
.dashboard-editor-container { .home {
padding: 32px; blockquote {
background-color: rgb(240, 242, 245); padding: 10px 20px;
position: relative; margin: 0 0 20px;
font-size: 17.5px;
.chart-wrapper { border-left: 5px solid #eee;
background: #fff; }
padding: 16px 16px 0; hr {
margin-bottom: 32px; margin-top: 20px;
margin-bottom: 20px;
border: 0;
border-top: 1px solid #eee;
}
.col-item {
margin-bottom: 20px;
} }
}
@media (max-width:1024px) { ul {
.chart-wrapper { padding: 0;
padding: 8px; 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> </style>

View 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>

View File

@@ -48,7 +48,7 @@
</el-form> </el-form>
<!-- 底部 --> <!-- 底部 -->
<div class="el-login-footer"> <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>
</div> </div>
</template> </template>

View File

@@ -111,7 +111,7 @@
type="text" type="text"
icon="el-icon-caret-right" icon="el-icon-caret-right"
@click="handleRun(scope.row)" @click="handleRun(scope.row)"
v-hasPermi="['monitor:job:edit']" v-hasPermi="['monitor:job:changeStatus']"
>执行一次</el-button> >执行一次</el-button>
<el-button <el-button
size="mini" size="mini"
@@ -402,7 +402,7 @@ export default {
return runJob(row.jobId, row.jobGroup); return runJob(row.jobId, row.jobGroup);
}).then(() => { }).then(() => {
this.msgSuccess("执行成功"); this.msgSuccess("执行成功");
}).catch(function() {}); })
}, },
/** 任务详细信息 */ /** 任务详细信息 */
handleView(row) { handleView(row) {
@@ -437,19 +437,15 @@ export default {
if (valid) { if (valid) {
if (this.form.jobId != undefined) { if (this.form.jobId != undefined) {
updateJob(this.form).then(response => { updateJob(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
addJob(this.form).then(response => { addJob(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -467,7 +463,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {

View File

@@ -263,7 +263,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 清空按钮操作 */ /** 清空按钮操作 */
handleClean() { handleClean() {
@@ -276,7 +276,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("清空成功"); this.msgSuccess("清空成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {

View File

@@ -116,7 +116,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("强退成功"); this.msgSuccess("强退成功");
}).catch(function() {}); })
} }
} }
}; };

View File

@@ -304,19 +304,15 @@ export default {
if (valid) { if (valid) {
if (this.form.configId != undefined) { if (this.form.configId != undefined) {
updateConfig(this.form).then(response => { updateConfig(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
addConfig(this.form).then(response => { addConfig(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -334,7 +330,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {
@@ -345,11 +341,7 @@ export default {
/** 清理缓存按钮操作 */ /** 清理缓存按钮操作 */
handleClearCache() { handleClearCache() {
clearCache().then(response => { clearCache().then(response => {
if (response.code === 200) { this.msgSuccess("清理成功");
this.msgSuccess("清理成功");
} else {
this.msgError(response.msg);
}
}); });
} }
} }

View File

@@ -284,19 +284,15 @@ export default {
if (valid) { if (valid) {
if (this.form.deptId != undefined) { if (this.form.deptId != undefined) {
updateDept(this.form).then(response => { updateDept(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
addDept(this.form).then(response => { addDept(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -313,7 +309,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
} }
} }
}; };

View File

@@ -304,19 +304,15 @@ export default {
if (valid) { if (valid) {
if (this.form.dictCode != undefined) { if (this.form.dictCode != undefined) {
updateData(this.form).then(response => { updateData(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
addData(this.form).then(response => { addData(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -334,7 +330,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {

View File

@@ -308,19 +308,15 @@ export default {
if (valid) { if (valid) {
if (this.form.dictId != undefined) { if (this.form.dictId != undefined) {
updateType(this.form).then(response => { updateType(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
addType(this.form).then(response => { addType(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -338,7 +334,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {
@@ -349,11 +345,7 @@ export default {
/** 清理缓存按钮操作 */ /** 清理缓存按钮操作 */
handleClearCache() { handleClearCache() {
clearCache().then(response => { clearCache().then(response => {
if (response.code === 200) { this.msgSuccess("清理成功");
this.msgSuccess("清理成功");
} else {
this.msgError(response.msg);
}
}); });
} }
} }

View File

@@ -193,7 +193,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 清空按钮操作 */ /** 清空按钮操作 */
handleClean() { handleClean() {
@@ -206,7 +206,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("清空成功"); this.msgSuccess("清空成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {

View File

@@ -367,19 +367,15 @@ export default {
if (valid) { if (valid) {
if (this.form.menuId != undefined) { if (this.form.menuId != undefined) {
updateMenu(this.form).then(response => { updateMenu(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
addMenu(this.form).then(response => { addMenu(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -396,7 +392,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
} }
} }
}; };

View File

@@ -307,19 +307,15 @@ export default {
if (valid) { if (valid) {
if (this.form.noticeId != undefined) { if (this.form.noticeId != undefined) {
updateNotice(this.form).then(response => { updateNotice(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
addNotice(this.form).then(response => { addNotice(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -337,7 +333,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
} }
} }
}; };

View File

@@ -283,7 +283,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 清空按钮操作 */ /** 清空按钮操作 */
handleClean() { handleClean() {
@@ -296,7 +296,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("清空成功"); this.msgSuccess("清空成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {

View File

@@ -276,19 +276,15 @@ export default {
if (valid) { if (valid) {
if (this.form.postId != undefined) { if (this.form.postId != undefined) {
updatePost(this.form).then(response => { updatePost(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
addPost(this.form).then(response => { addPost(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -306,7 +302,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {

View File

@@ -368,18 +368,18 @@ export default {
// 所有菜单节点数据 // 所有菜单节点数据
getMenuAllCheckedKeys() { 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); checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
return checkedKeys; return checkedKeys;
}, },
// 所有部门节点数据 // 所有部门节点数据
getDeptAllCheckedKeys() { 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); checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
return checkedKeys; return checkedKeys;
}, },
@@ -537,20 +537,16 @@ export default {
if (this.form.roleId != undefined) { if (this.form.roleId != undefined) {
this.form.menuIds = this.getMenuAllCheckedKeys(); this.form.menuIds = this.getMenuAllCheckedKeys();
updateRole(this.form).then(response => { updateRole(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
this.form.menuIds = this.getMenuAllCheckedKeys(); this.form.menuIds = this.getMenuAllCheckedKeys();
addRole(this.form).then(response => { addRole(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -561,11 +557,9 @@ export default {
if (this.form.roleId != undefined) { if (this.form.roleId != undefined) {
this.form.deptIds = this.getDeptAllCheckedKeys(); this.form.deptIds = this.getDeptAllCheckedKeys();
dataScope(this.form).then(response => { dataScope(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.openDataScope = false;
this.openDataScope = false; this.getList();
this.getList();
}
}); });
} }
}, },
@@ -581,7 +575,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {

View File

@@ -582,9 +582,7 @@ export default {
cancelButtonText: "取消" cancelButtonText: "取消"
}).then(({ value }) => { }).then(({ value }) => {
resetUserPwd(row.userId, value).then(response => { resetUserPwd(row.userId, value).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功,新密码是:" + value);
this.msgSuccess("修改成功,新密码是:" + value);
}
}); });
}).catch(() => {}); }).catch(() => {});
}, },
@@ -594,19 +592,15 @@ export default {
if (valid) { if (valid) {
if (this.form.userId != undefined) { if (this.form.userId != undefined) {
updateUser(this.form).then(response => { updateUser(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} else { } else {
addUser(this.form).then(response => { addUser(this.form).then(response => {
if (response.code === 200) { this.msgSuccess("新增成功");
this.msgSuccess("新增成功"); this.open = false;
this.open = false; this.getList();
this.getList();
}
}); });
} }
} }
@@ -624,7 +618,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {

View File

@@ -57,9 +57,7 @@ export default {
if (valid) { if (valid) {
updateUserPwd(this.user.oldPassword, this.user.newPassword).then( updateUserPwd(this.user.oldPassword, this.user.newPassword).then(
response => { response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功");
}
} }
); );
} }

View File

@@ -1,6 +1,6 @@
<template> <template>
<div> <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-dialog :title="title" :visible.sync="open" width="800px" append-to-body @opened="modalOpened">
<el-row> <el-row>
<el-col :xs="24" :md="12" :style="{height: '350px'}"> <el-col :xs="24" :md="12" :style="{height: '350px'}">
@@ -125,12 +125,10 @@ export default {
let formData = new FormData(); let formData = new FormData();
formData.append("avatarfile", data); formData.append("avatarfile", data);
uploadAvatar(formData).then(response => { uploadAvatar(formData).then(response => {
if (response.code === 200) { this.open = false;
this.open = false; this.options.img = response.imgUrl;
this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl; store.commit('SET_AVATAR', this.options.img);
store.commit('SET_AVATAR', this.options.img); this.msgSuccess("修改成功");
this.msgSuccess("修改成功");
}
this.visible = false; this.visible = false;
}); });
}); });
@@ -141,4 +139,28 @@ export default {
} }
} }
}; };
</script> </script>
<style scoped lang="scss">
.user-info-head {
position: relative;
display: inline-block;
}
.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>

View File

@@ -62,9 +62,7 @@ export default {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
updateUserProfile(this.user).then(response => { updateUserProfile(this.user).then(response => {
if (response.code === 200) { this.msgSuccess("修改成功");
this.msgSuccess("修改成功");
}
}); });
} }
}); });

View File

@@ -90,6 +90,7 @@
<el-option label="单选框" value="radio" /> <el-option label="单选框" value="radio" />
<el-option label="复选框" value="checkbox" /> <el-option label="复选框" value="checkbox" />
<el-option label="日期控件" value="datetime" /> <el-option label="日期控件" value="datetime" />
<el-option label="上传控件" value="uploadImage" />
<el-option label="富文本控件" value="editor" /> <el-option label="富文本控件" value="editor" />
</el-select> </el-select>
</template> </template>

View File

@@ -270,7 +270,7 @@ export default {
return synchDb(tableName); return synchDb(tableName);
}).then(() => { }).then(() => {
this.msgSuccess("同步成功"); this.msgSuccess("同步成功");
}).catch(function() {}); })
}, },
/** 打开导入表弹窗 */ /** 打开导入表弹窗 */
openImportTable() { openImportTable() {
@@ -313,7 +313,7 @@ export default {
}).then(() => { }).then(() => {
this.getList(); this.getList();
this.msgSuccess("删除成功"); this.msgSuccess("删除成功");
}).catch(function() {}); })
} }
} }
}; };

View File

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

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-visual</artifactId> <artifactId>ruoyi-visual</artifactId>
<version>2.2.0</version> <version>2.3.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/ruoyi-visual-monitor" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@@ -1,215 +1,216 @@
DROP DATABASE IF EXISTS `ry-config`; DROP DATABASE IF EXISTS `ry-config`;
CREATE DATABASE `ry-config` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE DATABASE `ry-config` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
SET NAMES utf8mb4; SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; SET FOREIGN_KEY_CHECKS = 0;
USE `ry-config`; USE `ry-config`;
/******************************************/ /******************************************/
/* 表名称 = config_info */ /* 表名称 = config_info */
/******************************************/ /******************************************/
CREATE TABLE `config_info` ( CREATE TABLE `config_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id', `data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) DEFAULT NULL, `group_id` varchar(255) DEFAULT NULL,
`content` longtext NOT NULL COMMENT 'content', `content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5', `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user', `src_user` text COMMENT 'source user',
`src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip', `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) DEFAULT NULL, `app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`c_desc` varchar(256) DEFAULT NULL, `c_desc` varchar(256) DEFAULT NULL,
`c_use` varchar(64) DEFAULT NULL, `c_use` varchar(64) DEFAULT NULL,
`effect` varchar(64) DEFAULT NULL, `effect` varchar(64) DEFAULT NULL,
`type` varchar(64) DEFAULT NULL, `type` varchar(64) DEFAULT NULL,
`c_schema` text, `c_schema` text,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`) UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
insert into config_info(id, data_id, group_id, content, md5, gmt_create, gmt_modified, src_user, src_ip, app_name, tenant_id, c_desc, c_use, effect, type, c_schema) values insert into config_info(id, data_id, group_id, content, md5, gmt_create, gmt_modified, src_user, src_ip, app_name, tenant_id, c_desc, c_use, effect, type, c_schema) values
(1,'application-dev.yml','DEFAULT_GROUP','spring:\n main:\n allow-bean-definition-overriding: true\n\n#请求处理的超时时间\nribbon:\n ReadTimeout: 10000\n ConnectTimeout: 10000\n\n# feign 配置\nfeign:\n sentinel:\n enabled: true\n okhttp:\n enabled: true\n httpclient:\n enabled: false\n client:\n config:\n default:\n connectTimeout: 10000\n readTimeout: 10000\n compression:\n request:\n enabled: true\n response:\n enabled: true\n\n# 暴露监控端点\nmanagement:\n endpoints:\n web:\n exposure:\n include: \'*\'\n','57470c6d167154919418fa150863b7fb','2019-11-29 16:31:20','2020-09-01 09:14:30',NULL,'0:0:0:0:0:0:0:1','','','通用配置','null','null','yaml','null'), (1,'application-dev.yml','DEFAULT_GROUP','spring:\n main:\n allow-bean-definition-overriding: true\n\n#请求处理的超时时间\nribbon:\n ReadTimeout: 10000\n ConnectTimeout: 10000\n\n# feign 配置\nfeign:\n sentinel:\n enabled: true\n okhttp:\n enabled: true\n httpclient:\n enabled: false\n client:\n config:\n default:\n connectTimeout: 10000\n readTimeout: 10000\n compression:\n request:\n enabled: true\n response:\n enabled: true\n\n# 暴露监控端点\nmanagement:\n endpoints:\n web:\n exposure:\n include: \'*\'\n','57470c6d167154919418fa150863b7fb','2019-11-29 16:31:20','2020-09-01 09:14:30',NULL,'0:0:0:0:0:0:0:1','','','通用配置','null','null','yaml','null'),
(2,'ruoyi-gateway-dev.yml','DEFAULT_GROUP','spring:\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n cloud:\r\n gateway:\r\n discovery:\r\n locator:\r\n lowerCaseServiceId: true\r\n enabled: true\r\n routes:\r\n # 认证中心\r\n - id: ruoyi-auth\r\n uri: lb://ruoyi-auth\r\n predicates:\r\n - Path=/auth/**\r\n filters:\r\n # 验证码处理\r\n - CacheRequestFilter\r\n - ValidateCodeFilter\r\n - StripPrefix=1\r\n # 代码生成\r\n - id: ruoyi-gen\r\n uri: lb://ruoyi-gen\r\n predicates:\r\n - Path=/code/**\r\n filters:\r\n - StripPrefix=1\r\n # 定时任务\r\n - id: ruoyi-job\r\n uri: lb://ruoyi-job\r\n predicates:\r\n - Path=/schedule/**\r\n filters:\r\n - StripPrefix=1\r\n # 系统模块\r\n - id: ruoyi-system\r\n uri: lb://ruoyi-system\r\n predicates:\r\n - Path=/system/**\r\n filters:\r\n - StripPrefix=1\r\n\r\n# 不校验白名单\r\nignore:\r\n whites:\r\n - /auth/logout\r\n - /auth/login\r\n - /*/v2/api-docs\r\n - /csrf\r\n','679b21a74f71cb607944b7d9d03cffde','2020-05-14 14:17:55','2020-09-15 17:01:01',NULL,'0:0:0:0:0:0:0:1','','','网关模块','null','null','yaml','null'), (2,'ruoyi-gateway-dev.yml','DEFAULT_GROUP','spring:\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n cloud:\r\n gateway:\r\n discovery:\r\n locator:\r\n lowerCaseServiceId: true\r\n enabled: true\r\n routes:\r\n # 认证中心\r\n - id: ruoyi-auth\r\n uri: lb://ruoyi-auth\r\n predicates:\r\n - Path=/auth/**\r\n filters:\r\n # 验证码处理\r\n - CacheRequestFilter\r\n - ValidateCodeFilter\r\n - StripPrefix=1\r\n # 代码生成\r\n - id: ruoyi-gen\r\n uri: lb://ruoyi-gen\r\n predicates:\r\n - Path=/code/**\r\n filters:\r\n - StripPrefix=1\r\n # 定时任务\r\n - id: ruoyi-job\r\n uri: lb://ruoyi-job\r\n predicates:\r\n - Path=/schedule/**\r\n filters:\r\n - StripPrefix=1\r\n # 系统模块\r\n - id: ruoyi-system\r\n uri: lb://ruoyi-system\r\n predicates:\r\n - Path=/system/**\r\n filters:\r\n - StripPrefix=1\r\n # 文件服务\r\n - id: ruoyi-file\r\n uri: lb://ruoyi-file\r\n predicates:\r\n - Path=/file/**\r\n filters:\r\n - StripPrefix=1\r\n\r\n# 不校验白名单\r\nignore:\r\n whites:\r\n - /auth/logout\r\n - /auth/login\r\n - /*/v2/api-docs\r\n - /csrf\r\n','ef4a58daf989827334b3aac1c9d68392','2020-05-14 14:17:55','2020-11-18 17:53:23',NULL,'0:0:0:0:0:0:0:1','','','网关模块','null','null','yaml','null'),
(3,'ruoyi-auth-dev.yml','DEFAULT_GROUP','spring: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n','868c15010a7a15c027d4c90a48aabb3e','2020-05-14 13:20:49','2020-06-09 16:30:50',NULL,'0:0:0:0:0:0:0:1','','','认证中心','null','null','yaml','null'), (3,'ruoyi-auth-dev.yml','DEFAULT_GROUP','spring: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n','868c15010a7a15c027d4c90a48aabb3e','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','认证中心','null','null','yaml','null'),
(4,'ruoyi-monitor-dev.yml','DEFAULT_GROUP','# Spring\r\nspring: \r\n security:\r\n user:\r\n name: ruoyi\r\n password: 123456\r\n boot:\r\n admin:\r\n ui:\r\n title: 若依服务状态监控\r\n','8e49d78998a7780d780305aeefe4fb1b','2020-05-19 15:14:01','2020-05-19 18:50:44',NULL,'0:0:0:0:0:0:0:1','','','监控中心','null','null','yaml','null'), (4,'ruoyi-monitor-dev.yml','DEFAULT_GROUP','# Spring\r\nspring: \r\n security:\r\n user:\r\n name: ruoyi\r\n password: 123456\r\n boot:\r\n admin:\r\n ui:\r\n title: 若依服务状态监控\r\n','8e49d78998a7780d780305aeefe4fb1b','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','监控中心','null','null','yaml','null'),
(5,'ruoyi-system-dev.yml','DEFAULT_GROUP','# Spring\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# Mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.system\r\n # 配置mapper的扫描找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger 配置\r\nswagger:\r\n title: 系统模块接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n authorization:\r\n name: RuoYi OAuth\r\n auth-regex: ^.*$\r\n authorization-scope-list:\r\n - scope: server\r\n description: 客户端授权范围\r\n token-url-list:\r\n - http://localhost:8080/auth/oauth/token\r\n','06f95c879d284ec8031cc44805e62b50','2020-05-14 13:37:04','2020-07-02 20:03:46',NULL,'0:0:0:0:0:0:0:1','','','系统模块','null','null','yaml','null'), (5,'ruoyi-system-dev.yml','DEFAULT_GROUP','# Spring\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# Mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.system\r\n # 配置mapper的扫描找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger 配置\r\nswagger:\r\n title: 系统模块接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n authorization:\r\n name: RuoYi OAuth\r\n auth-regex: ^.*$\r\n authorization-scope-list:\r\n - scope: server\r\n description: 客户端授权范围\r\n token-url-list:\r\n - http://localhost:8080/auth/oauth/token\r\n','06f95c879d284ec8031cc44805e62b50','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','系统模块','null','null','yaml','null'),
(6,'ruoyi-gen-dev.yml','DEFAULT_GROUP','# Spring\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource: \r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# Mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.gen.domain\r\n # 配置mapper的扫描找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger 配置\r\nswagger:\r\n title: 代码生成接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n authorization:\r\n name: RuoYi OAuth\r\n auth-regex: ^.*$\r\n authorization-scope-list:\r\n - scope: server\r\n description: 客户端授权范围\r\n token-url-list:\r\n - http://localhost:8080/auth/oauth/token\r\n\r\n# 代码生成\r\ngen: \r\n # 作者\r\n author: ruoyi\r\n # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool\r\n packageName: com.ruoyi.system\r\n # 自动去除表前缀默认是false\r\n autoRemovePre: false\r\n # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)\r\n tablePrefix: sys_\r\n','02b9be6ad01ca44c992c41a020ec81aa','2020-05-14 13:54:50','2020-09-24 14:56:08',NULL,'0:0:0:0:0:0:0:1','','','代码生成','null','null','yaml','null'), (6,'ruoyi-gen-dev.yml','DEFAULT_GROUP','# Spring\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource: \r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# Mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.gen.domain\r\n # 配置mapper的扫描找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger 配置\r\nswagger:\r\n title: 代码生成接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n authorization:\r\n name: RuoYi OAuth\r\n auth-regex: ^.*$\r\n authorization-scope-list:\r\n - scope: server\r\n description: 客户端授权范围\r\n token-url-list:\r\n - http://localhost:8080/auth/oauth/token\r\n\r\n# 代码生成\r\ngen: \r\n # 作者\r\n author: ruoyi\r\n # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool\r\n packageName: com.ruoyi.system\r\n # 自动去除表前缀默认是false\r\n autoRemovePre: false\r\n # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)\r\n tablePrefix: sys_\r\n','02b9be6ad01ca44c992c41a020ec81aa','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','代码生成','null','null','yaml','null'),
(7,'ruoyi-job-dev.yml','DEFAULT_GROUP','# Spring\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# Mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.job.domain\r\n # 配置mapper的扫描找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger 配置\r\nswagger:\r\n title: 定时任务接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n authorization:\r\n name: RuoYi OAuth\r\n auth-regex: ^.*$\r\n authorization-scope-list:\r\n - scope: server\r\n description: 客户端授权范围\r\n token-url-list:\r\n - http://localhost:8080/auth/oauth/token\r\n','5033cbfb2c38780ac23f74954588ec4f','2020-05-14 13:58:46','2020-09-24 14:56:18',NULL,'0:0:0:0:0:0:0:1','','','定时任务','null','null','yaml','null'), (7,'ruoyi-job-dev.yml','DEFAULT_GROUP','# Spring\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# Mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.job.domain\r\n # 配置mapper的扫描找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger 配置\r\nswagger:\r\n title: 定时任务接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n authorization:\r\n name: RuoYi OAuth\r\n auth-regex: ^.*$\r\n authorization-scope-list:\r\n - scope: server\r\n description: 客户端授权范围\r\n token-url-list:\r\n - http://localhost:8080/auth/oauth/token\r\n','5033cbfb2c38780ac23f74954588ec4f','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','定时任务','null','null','yaml','null'),
(8,'sentinel-ruoyi-gateway','DEFAULT_GROUP','[\r\n {\r\n \"resource\": \"ruoyi-auth\",\r\n \"count\": 500,\r\n \"grade\": 1,\r\n \"limitApp\": \"default\",\r\n \"strategy\": 0,\r\n \"controlBehavior\": 0\r\n },\r\n {\r\n \"resource\": \"ruoyi-system\",\r\n \"count\": 1000,\r\n \"grade\": 1,\r\n \"limitApp\": \"default\",\r\n \"strategy\": 0,\r\n \"controlBehavior\": 0\r\n },\r\n {\r\n \"resource\": \"ruoyi-gen\",\r\n \"count\": 200,\r\n \"grade\": 1,\r\n \"limitApp\": \"default\",\r\n \"strategy\": 0,\r\n \"controlBehavior\": 0\r\n },\r\n {\r\n \"resource\": \"ruoyi-job\",\r\n \"count\": 300,\r\n \"grade\": 1,\r\n \"limitApp\": \"default\",\r\n \"strategy\": 0,\r\n \"controlBehavior\": 0\r\n }\r\n]','9f3a3069261598f74220bc47958ec252','2020-06-09 12:14:01','2020-06-10 11:44:19',NULL,'0:0:0:0:0:0:0:1','','','null','null','null','json','null'); (8,'ruoyi-file-dev.yml','DEFAULT_GROUP','## 本地文件上传 \r\nfile:\r\n domain: http://127.0.0.1:9300\r\n path: D:/ruoyi/uploadPath\r\n prefix: /statics\r\n\r\n# FastDFS配置\r\nfdfs:\r\n domain: http://127.0.0.1\r\n soTimeout: 3000\r\n connectTimeout: 2000\r\n trackerList: 127.0.0.1:22122','683f4f682d8d7a6df803b0f6823e6db5','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','文件服务','null','null','yaml','null'),
(9,'sentinel-ruoyi-gateway','DEFAULT_GROUP','[\r\n {\r\n \"resource\": \"ruoyi-auth\",\r\n \"count\": 500,\r\n \"grade\": 1,\r\n \"limitApp\": \"default\",\r\n \"strategy\": 0,\r\n \"controlBehavior\": 0\r\n },\r\n {\r\n \"resource\": \"ruoyi-system\",\r\n \"count\": 1000,\r\n \"grade\": 1,\r\n \"limitApp\": \"default\",\r\n \"strategy\": 0,\r\n \"controlBehavior\": 0\r\n },\r\n {\r\n \"resource\": \"ruoyi-gen\",\r\n \"count\": 200,\r\n \"grade\": 1,\r\n \"limitApp\": \"default\",\r\n \"strategy\": 0,\r\n \"controlBehavior\": 0\r\n },\r\n {\r\n \"resource\": \"ruoyi-job\",\r\n \"count\": 300,\r\n \"grade\": 1,\r\n \"limitApp\": \"default\",\r\n \"strategy\": 0,\r\n \"controlBehavior\": 0\r\n }\r\n]','9f3a3069261598f74220bc47958ec252','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','限流策略','null','null','json','null');
/******************************************/
/* 表名称 = config_info_aggr */ /******************************************/
/******************************************/ /* 表名称 = config_info_aggr */
CREATE TABLE `config_info_aggr` ( /******************************************/
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', CREATE TABLE `config_info_aggr` (
`data_id` varchar(255) NOT NULL COMMENT 'data_id', `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`group_id` varchar(255) NOT NULL COMMENT 'group_id', `data_id` varchar(255) NOT NULL COMMENT 'data_id',
`datum_id` varchar(255) NOT NULL COMMENT 'datum_id', `group_id` varchar(255) NOT NULL COMMENT 'group_id',
`content` longtext NOT NULL COMMENT '内容', `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
`gmt_modified` datetime NOT NULL COMMENT '修改时间', `content` longtext NOT NULL COMMENT '内容',
`app_name` varchar(128) DEFAULT NULL, `gmt_modified` datetime NOT NULL COMMENT '修改时间',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', `app_name` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`), `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`) PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段'; UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
/******************************************/
/* 表名称 = config_info_beta */ /******************************************/
/******************************************/ /* 表名称 = config_info_beta */
CREATE TABLE `config_info_beta` ( /******************************************/
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', CREATE TABLE `config_info_beta` (
`data_id` varchar(255) NOT NULL COMMENT 'data_id', `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id', `data_id` varchar(255) NOT NULL COMMENT 'data_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', `group_id` varchar(128) NOT NULL COMMENT 'group_id',
`content` longtext NOT NULL COMMENT 'content', `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps', `content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5', `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`src_user` text COMMENT 'source user', `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip', `src_user` text COMMENT 'source user',
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
PRIMARY KEY (`id`), `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`) PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta'; UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
/******************************************/
/* 表名称 = config_info_tag */ /******************************************/
/******************************************/ /* 表名称 = config_info_tag */
CREATE TABLE `config_info_tag` ( /******************************************/
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', CREATE TABLE `config_info_tag` (
`data_id` varchar(255) NOT NULL COMMENT 'data_id', `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`group_id` varchar(128) NOT NULL COMMENT 'group_id', `data_id` varchar(255) NOT NULL COMMENT 'data_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', `group_id` varchar(128) NOT NULL COMMENT 'group_id',
`tag_id` varchar(128) NOT NULL COMMENT 'tag_id', `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
`content` longtext NOT NULL COMMENT 'content', `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5', `content` longtext NOT NULL COMMENT 'content',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`src_user` text COMMENT 'source user', `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip', `src_user` text COMMENT 'source user',
PRIMARY KEY (`id`), `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`) PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag'; UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
/******************************************/
/* 表名称 = config_tags_relation */ /******************************************/
/******************************************/ /* 表名称 = config_tags_relation */
CREATE TABLE `config_tags_relation` ( /******************************************/
`id` bigint(20) NOT NULL COMMENT 'id', CREATE TABLE `config_tags_relation` (
`tag_name` varchar(128) NOT NULL COMMENT 'tag_name', `id` bigint(20) NOT NULL COMMENT 'id',
`tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type', `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
`data_id` varchar(255) NOT NULL COMMENT 'data_id', `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
`group_id` varchar(128) NOT NULL COMMENT 'group_id', `data_id` varchar(255) NOT NULL COMMENT 'data_id',
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', `group_id` varchar(128) NOT NULL COMMENT 'group_id',
`nid` bigint(20) NOT NULL AUTO_INCREMENT, `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
PRIMARY KEY (`nid`), `nid` bigint(20) NOT NULL AUTO_INCREMENT,
UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`), PRIMARY KEY (`nid`),
KEY `idx_tenant_id` (`tenant_id`) UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation'; KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
/******************************************/
/* 表名称 = group_capacity */ /******************************************/
/******************************************/ /* 表名称 = group_capacity */
CREATE TABLE `group_capacity` ( /******************************************/
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID', CREATE TABLE `group_capacity` (
`group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID空字符表示整个集群', `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额0表示使用默认值', `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID空字符表示整个集群',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量', `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额0表示使用默认值',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限单位为字节0表示使用默认值', `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,0表示使用默认值', `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节0表示使用默认值',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节0表示使用默认值', `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,0表示使用默认值',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量', `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限单位为字节0表示使用默认值',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`), `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
UNIQUE KEY `uk_group_id` (`group_id`) PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表'; UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
/******************************************/
/* 表名称 = his_config_info */ /******************************************/
/******************************************/ /* 表名称 = his_config_info */
CREATE TABLE `his_config_info` ( /******************************************/
`id` bigint(64) unsigned NOT NULL, CREATE TABLE `his_config_info` (
`nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `id` bigint(64) unsigned NOT NULL,
`data_id` varchar(255) NOT NULL, `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`group_id` varchar(128) NOT NULL, `data_id` varchar(255) NOT NULL,
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', `group_id` varchar(128) NOT NULL,
`content` longtext NOT NULL, `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
`md5` varchar(32) DEFAULT NULL, `content` longtext NOT NULL,
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `md5` varchar(32) DEFAULT NULL,
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`src_user` text, `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`src_ip` varchar(20) DEFAULT NULL, `src_user` text,
`op_type` char(10) DEFAULT NULL, `src_ip` varchar(20) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', `op_type` char(10) DEFAULT NULL,
PRIMARY KEY (`nid`), `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
KEY `idx_gmt_create` (`gmt_create`), PRIMARY KEY (`nid`),
KEY `idx_gmt_modified` (`gmt_modified`), KEY `idx_gmt_create` (`gmt_create`),
KEY `idx_did` (`data_id`) KEY `idx_gmt_modified` (`gmt_modified`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造'; KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
/******************************************/
/* 数据库全名 = nacos_config */ /******************************************/
/* 表名称 = tenant_capacity */ /* 数据库全名 = nacos_config */
/******************************************/ /* 表名称 = tenant_capacity */
CREATE TABLE `tenant_capacity` ( /******************************************/
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID', CREATE TABLE `tenant_capacity` (
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID', `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额0表示使用默认值', `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量', `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额0表示使用默认值',
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限单位为字节0表示使用默认值', `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数', `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限单位为字节0表示使用默认值',
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限单位为字节0表示使用默认值', `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量', `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限单位为字节0表示使用默认值',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`), `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
UNIQUE KEY `uk_tenant_id` (`tenant_id`) PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表'; UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
CREATE TABLE `tenant_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', CREATE TABLE `tenant_info` (
`kp` varchar(128) NOT NULL COMMENT 'kp', `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`tenant_id` varchar(128) default '' COMMENT 'tenant_id', `kp` varchar(128) NOT NULL COMMENT 'kp',
`tenant_name` varchar(128) default '' COMMENT 'tenant_name', `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
`tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc', `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
`create_source` varchar(32) DEFAULT NULL COMMENT 'create_source', `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
`gmt_create` bigint(20) NOT NULL COMMENT '创建时间', `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
`gmt_modified` bigint(20) NOT NULL COMMENT '修改时间', `gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`), `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`), PRIMARY KEY (`id`),
KEY `idx_tenant_id` (`tenant_id`) UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info'; KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
CREATE TABLE `users` (
`username` varchar(50) NOT NULL PRIMARY KEY, CREATE TABLE `users` (
`password` varchar(500) NOT NULL, `username` varchar(50) NOT NULL PRIMARY KEY,
`enabled` boolean NOT NULL `password` varchar(500) NOT NULL,
); `enabled` boolean NOT NULL
);
CREATE TABLE `roles` (
`username` varchar(50) NOT NULL, CREATE TABLE `roles` (
`role` varchar(50) NOT NULL, `username` varchar(50) NOT NULL,
UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE `role` varchar(50) NOT NULL,
); UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
);
CREATE TABLE `permissions` (
`role` varchar(50) NOT NULL, CREATE TABLE `permissions` (
`resource` varchar(512) NOT NULL, `role` varchar(50) NOT NULL,
`action` varchar(8) NOT NULL, `resource` varchar(512) NOT NULL,
UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE `action` varchar(8) NOT NULL,
); UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');