add 增加ruoyi-resource资源模块 移除ruoyi-file模块 调整项目结构
parent
5870045c35
commit
69e699946f
|
|
@ -279,7 +279,7 @@ knife4j:
|
|||
# seata配置
|
||||
seata:
|
||||
# 默认关闭,如需启用spring.datasource.dynami.seata需要同时开启
|
||||
enabled: false
|
||||
enabled: true
|
||||
# Seata 应用编号,默认为 ${spring.application.name}
|
||||
application-id: ${spring.application.name}
|
||||
# Seata 事务组编号,用于 TC 集群名
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ spring:
|
|||
# 性能分析插件(有性能损耗 不建议生产环境使用)
|
||||
p6spy: true
|
||||
# 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭
|
||||
seata: false
|
||||
seata: true
|
||||
druid:
|
||||
initial-size: 5
|
||||
min-idle: 5
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
# dubbo 订阅配置
|
||||
dubbo:
|
||||
cloud:
|
||||
# 需要远程调用的服务 多个用逗号分割
|
||||
subscribed-services: ruoyi-system
|
||||
|
||||
# 本地文件上传
|
||||
file:
|
||||
domain: http://127.0.0.1:9300
|
||||
path: D:/ruoyi/uploadPath
|
||||
prefix: /statics
|
||||
|
||||
# FastDFS配置
|
||||
fdfs:
|
||||
domain: http://8.129.231.12
|
||||
soTimeout: 3000
|
||||
connectTimeout: 2000
|
||||
trackerList: 8.129.231.12:22122
|
||||
|
||||
# Minio配置
|
||||
minio:
|
||||
url: http://8.129.231.12:9000
|
||||
accessKey: minioadmin
|
||||
secretKey: minioadmin
|
||||
bucketName: test
|
||||
|
|
@ -53,13 +53,6 @@ spring:
|
|||
- Path=/code/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
# 定时任务
|
||||
- id: ruoyi-job
|
||||
uri: lb://ruoyi-job
|
||||
predicates:
|
||||
- Path=/schedule/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
# 系统模块
|
||||
- id: ruoyi-system
|
||||
uri: lb://ruoyi-system
|
||||
|
|
@ -67,11 +60,11 @@ spring:
|
|||
- Path=/system/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
# 文件服务
|
||||
- id: ruoyi-file
|
||||
uri: lb://ruoyi-file
|
||||
# 资源服务
|
||||
- id: ruoyi-resource
|
||||
uri: lb://ruoyi-resource
|
||||
predicates:
|
||||
- Path=/file/**
|
||||
- Path=/resource/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
# dubbo 订阅配置
|
||||
dubbo:
|
||||
cloud:
|
||||
# 需要远程调用的服务 多个用逗号分割
|
||||
subscribed-services: ruoyi-system
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
dynamic:
|
||||
# 设置默认的数据源或者数据源组,默认值即为 master
|
||||
primary: master
|
||||
datasource:
|
||||
# 主库数据源
|
||||
master:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: ${datasource.system-master.url}
|
||||
username: ${datasource.system-master.username}
|
||||
password: ${datasource.system-master.password}
|
||||
# 从库数据源
|
||||
# slave:
|
||||
# driver-class-name:
|
||||
# url:
|
||||
# username:
|
||||
# password:
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
dubbo:
|
||||
cloud:
|
||||
# 需要远程调用的服务 多个用逗号分割
|
||||
subscribed-services: ruoyi-file
|
||||
subscribed-services: ruoyi-resource
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
service.vgroupMapping.ruoyi-auth-group=default
|
||||
service.vgroupMapping.ruoyi-system-group=default
|
||||
service.vgroupMapping.ruoyi-file-group=default
|
||||
service.vgroupMapping.ruoyi-resource-group=default
|
||||
service.vgroupMapping.ruoyi-gen-group=default
|
||||
service.enableDegrade=false
|
||||
service.disableGlobalTransaction=false
|
||||
|
|
|
|||
40
pom.xml
40
pom.xml
|
|
@ -23,16 +23,12 @@
|
|||
<alibaba.nacos.version>2.0.4</alibaba.nacos.version>
|
||||
<spring-boot-admin.version>2.6.2</spring-boot-admin.version>
|
||||
<spring-boot.mybatis>2.2.0</spring-boot.mybatis>
|
||||
<swagger.core.version>1.6.2</swagger.core.version>
|
||||
<tobato.version>1.27.2</tobato.version>
|
||||
<swagger.core.version>1.5.22</swagger.core.version>
|
||||
<mybatis-plus.version>3.5.1</mybatis-plus.version>
|
||||
<p6spy.version>3.9.1</p6spy.version>
|
||||
<druid.version>1.2.8</druid.version>
|
||||
<dynamic-ds.version>3.5.0</dynamic-ds.version>
|
||||
<commons.io.version>2.11.0</commons.io.version>
|
||||
<commons.fileupload.version>1.4</commons.fileupload.version>
|
||||
<velocity.version>2.3</velocity.version>
|
||||
<minio.version>8.2.2</minio.version>
|
||||
<poi.version>4.1.2</poi.version>
|
||||
<easyexcel.version>3.0.5</easyexcel.version>
|
||||
<cglib.version>3.3.0</cglib.version>
|
||||
|
|
@ -54,6 +50,7 @@
|
|||
<aliyun.oss.version>3.14.0</aliyun.oss.version>
|
||||
<qcloud.cos.version>5.6.68</qcloud.cos.version>
|
||||
<minio.version>8.3.5</minio.version>
|
||||
<okhttp.version>4.9.2</okhttp.version>
|
||||
|
||||
<!-- docker 配置 -->
|
||||
<docker.registry.url>localhost</docker.registry.url>
|
||||
|
|
@ -178,11 +175,10 @@
|
|||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- FastDFS 分布式文件系统 -->
|
||||
<dependency>
|
||||
<groupId>com.github.tobato</groupId>
|
||||
<artifactId>fastdfs-client</artifactId>
|
||||
<version>${tobato.version}</version>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
<version>${satoken.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Mybatis 依赖配置 -->
|
||||
|
|
@ -193,9 +189,9 @@
|
|||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
<version>${swagger.core.version}</version>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-micro-spring-boot-starter</artifactId>
|
||||
<version>${knife4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Swagger 依赖配置 -->
|
||||
|
|
@ -223,13 +219,6 @@
|
|||
<version>${p6spy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- io常用工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.io.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- excel工具 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
|
|
@ -259,13 +248,6 @@
|
|||
<version>${cglib.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 文件上传工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>${commons.fileupload.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 代码生成使用模板 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
|
|
@ -301,9 +283,9 @@
|
|||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-micro-spring-boot-starter</artifactId>
|
||||
<version>${knife4j.version}</version>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<modules>
|
||||
<module>ruoyi-api-bom</module>
|
||||
<module>ruoyi-api-system</module>
|
||||
<module>ruoyi-api-file</module>
|
||||
<module>ruoyi-api-resource</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>ruoyi-api</artifactId>
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@
|
|||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 文件服务接口 -->
|
||||
<!-- 资源服务接口 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-api-file</artifactId>
|
||||
<artifactId>ruoyi-api-resource</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@
|
|||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-api-file</artifactId>
|
||||
<artifactId>ruoyi-api-resource</artifactId>
|
||||
|
||||
<description>
|
||||
ruoyi-api-file文件服务接口模块
|
||||
ruoyi-api-resource 资源服务接口模块
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.ruoyi.file.api;
|
||||
package com.ruoyi.resource.api;
|
||||
|
||||
import com.ruoyi.file.api.domain.SysFile;
|
||||
import com.ruoyi.resource.api.domain.SysFile;
|
||||
|
||||
/**
|
||||
* 文件服务
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.ruoyi.file.api.domain;
|
||||
package com.ruoyi.resource.api.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
<module>ruoyi-common-swagger</module>
|
||||
<module>ruoyi-common-security</module>
|
||||
<module>ruoyi-common-satoken</module>
|
||||
<module>ruoyi-common-datasource</module>
|
||||
<module>ruoyi-common-web</module>
|
||||
<module>ruoyi-common-mybatis</module>
|
||||
<module>ruoyi-common-job</module>
|
||||
|
|
|
|||
|
|
@ -42,13 +42,6 @@
|
|||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 多数据源 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-datasource</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 日志记录 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
|
|
|
|||
|
|
@ -66,18 +66,6 @@
|
|||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Commons Io -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Commons Fileupload -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib</artifactId>
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
package com.ruoyi.common.core.exception.file;
|
||||
|
||||
import org.apache.commons.fileupload.FileUploadException;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 文件上传 误异常类
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
package com.ruoyi.common.core.utils.file;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 文件类型工具类
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件类型
|
||||
*
|
||||
* @param photoByte 文件字节码
|
||||
* @return 后缀(不含".")
|
||||
*/
|
||||
public static String getFileExtendName(byte[] photoByte) {
|
||||
String strFileExtendName = "JPG";
|
||||
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
|
||||
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) {
|
||||
strFileExtendName = "GIF";
|
||||
} else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) {
|
||||
strFileExtendName = "JPG";
|
||||
} else if ((photoByte[0] == 66) && (photoByte[1] == 77)) {
|
||||
strFileExtendName = "BMP";
|
||||
} else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) {
|
||||
strFileExtendName = "PNG";
|
||||
}
|
||||
return strFileExtendName;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
package com.ruoyi.common.core.utils.file;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 图片处理工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class ImageUtils {
|
||||
private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
|
||||
|
||||
public static byte[] getImage(String imagePath) {
|
||||
InputStream is = getFile(imagePath);
|
||||
try {
|
||||
return IOUtils.toByteArray(is);
|
||||
} catch (Exception e) {
|
||||
log.error("图片加载异常 {}", e);
|
||||
return null;
|
||||
} finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream getFile(String imagePath) {
|
||||
try {
|
||||
byte[] result = readFile(imagePath);
|
||||
result = Arrays.copyOf(result, result.length);
|
||||
return new ByteArrayInputStream(result);
|
||||
} catch (Exception e) {
|
||||
log.error("获取图片异常 {}", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取文件为字节数据
|
||||
*
|
||||
* @param key 地址
|
||||
* @return 字节数据
|
||||
*/
|
||||
public static byte[] readFile(String url) {
|
||||
InputStream in = null;
|
||||
ByteArrayOutputStream baos = null;
|
||||
try {
|
||||
// 网络地址
|
||||
URL urlObj = new URL(url);
|
||||
URLConnection urlConnection = urlObj.openConnection();
|
||||
urlConnection.setConnectTimeout(30 * 1000);
|
||||
urlConnection.setReadTimeout(60 * 1000);
|
||||
urlConnection.setDoInput(true);
|
||||
in = urlConnection.getInputStream();
|
||||
return IOUtils.toByteArray(in);
|
||||
} catch (Exception e) {
|
||||
log.error("访问文件异常 {}", e);
|
||||
return null;
|
||||
} finally {
|
||||
IOUtils.closeQuietly(in);
|
||||
IOUtils.closeQuietly(baos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
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 "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.ruoyi.common.core.validate;
|
||||
|
||||
/**
|
||||
* 校验分组 add
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface AddGroup {
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.ruoyi.common.core.validate;
|
||||
|
||||
/**
|
||||
* 校验分组 edit
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface EditGroup {
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.ruoyi.common.core.validate;
|
||||
|
||||
/**
|
||||
* 校验分组 query
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface QueryGroup {
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
<?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-common</artifactId>
|
||||
<version>0.5.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-common-datasource</artifactId>
|
||||
|
||||
<description>
|
||||
ruoyi-common-datasource多数据源
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Druid -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Dynamic DataSource -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>${dynamic-ds.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package com.ruoyi.common.datasource.annotation;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 主库数据源
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@DS("master")
|
||||
public @interface Master {
|
||||
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package com.ruoyi.common.datasource.annotation;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 从库数据源
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@DS("slave")
|
||||
public @interface Slave {
|
||||
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
org.springframework.boot.env.EnvironmentPostProcessor=
|
||||
|
|
@ -38,5 +38,19 @@
|
|||
<groupId>p6spy</groupId>
|
||||
<artifactId>p6spy</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Druid -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Dynamic DataSource -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>${dynamic-ds.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
package com.ruoyi.common.mybatis.config;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
|
||||
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.ruoyi.common.mybatis.handler.CreateAndUpdateMetaObjectHandler;
|
||||
import com.ruoyi.common.mybatis.interceptor.PlusDataPermissionInterceptor;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
|
@ -64,10 +66,10 @@ public class MybatisPlusConfiguration {
|
|||
/**
|
||||
* 元对象字段填充控制器
|
||||
*/
|
||||
// @Bean
|
||||
// public MetaObjectHandler metaObjectHandler() {
|
||||
// return new CreateAndUpdateMetaObjectHandler();
|
||||
// }
|
||||
@Bean
|
||||
public MetaObjectHandler metaObjectHandler() {
|
||||
return new CreateAndUpdateMetaObjectHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用网卡信息绑定雪花生成器
|
||||
|
|
|
|||
|
|
@ -1 +1,5 @@
|
|||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.ruoyi.common.oss.service.impl.AliyunOssStrategy,\
|
||||
com.ruoyi.common.oss.service.impl.MinioOssStrategy,\
|
||||
com.ruoyi.common.oss.service.impl.QcloudOssStrategy,\
|
||||
com.ruoyi.common.oss.service.impl.QiniuOssStrategy
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
<version>${satoken.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 整合 jwt -->
|
||||
|
|
|
|||
|
|
@ -36,8 +36,9 @@
|
|||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package com.ruoyi.common.swagger.config;
|
||||
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||
import com.ruoyi.common.swagger.config.properties.SwaggerProperties;
|
||||
import io.swagger.models.auth.In;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
|
@ -31,6 +34,9 @@ import java.util.function.Predicate;
|
|||
@ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true)
|
||||
public class SwaggerAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private SaTokenConfig saTokenConfig;
|
||||
|
||||
/**
|
||||
* 默认的排除路径,排除Spring Boot默认的错误处理路径和端点
|
||||
*/
|
||||
|
|
@ -57,6 +63,7 @@ public class SwaggerAutoConfiguration {
|
|||
swaggerProperties.getExcludePath().forEach(path -> excludePath.add(PathSelectors.ant(path)));
|
||||
|
||||
ApiSelectorBuilder builder = new Docket(DocumentationType.OAS_30)
|
||||
.enable(swaggerProperties.getEnabled())
|
||||
.host(swaggerProperties.getHost())
|
||||
.apiInfo(apiInfo(swaggerProperties))
|
||||
.select()
|
||||
|
|
@ -76,7 +83,8 @@ public class SwaggerAutoConfiguration {
|
|||
*/
|
||||
private List<SecurityScheme> securitySchemes() {
|
||||
List<SecurityScheme> apiKeyList = new ArrayList<>();
|
||||
apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
|
||||
String header = saTokenConfig.getTokenName();
|
||||
apiKeyList.add(new ApiKey(header, header, In.HEADER.toValue()));
|
||||
return apiKeyList;
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +109,7 @@ public class SwaggerAutoConfiguration {
|
|||
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
||||
authorizationScopes[0] = authorizationScope;
|
||||
List<SecurityReference> securityReferences = new ArrayList<>();
|
||||
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
|
||||
securityReferences.add(new SecurityReference(saTokenConfig.getTokenName(), authorizationScopes));
|
||||
return securityReferences;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<modules>
|
||||
<module>ruoyi-system</module>
|
||||
<module>ruoyi-gen</module>
|
||||
<module>ruoyi-file</module>
|
||||
<module>ruoyi-resource</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>ruoyi-modules</artifactId>
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
package com.ruoyi.file.config;
|
||||
|
||||
import io.minio.MinioClient;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Minio 配置信息
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "minio")
|
||||
public class MinioConfig {
|
||||
|
||||
/**
|
||||
* 服务地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String accessKey;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 存储桶名称
|
||||
*/
|
||||
private String bucketName;
|
||||
|
||||
@Bean
|
||||
public MinioClient getMinioClient() {
|
||||
return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
package com.ruoyi.file.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 通用映射配置
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启跨域
|
||||
*/
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
// 设置允许跨域的路由
|
||||
registry.addMapping(localFilePrefix + "/**")
|
||||
// 设置允许跨域请求的域名
|
||||
.allowedOrigins("*")
|
||||
// 设置允许的方法
|
||||
.allowedMethods("GET");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
package com.ruoyi.file.controller;
|
||||
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.utils.file.FileUtils;
|
||||
import com.ruoyi.file.api.domain.SysFile;
|
||||
import com.ruoyi.file.service.ISysFileService;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 文件请求处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api(tags = "文件处理")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
public class SysFileController {
|
||||
|
||||
private final ISysFileService sysFileService;
|
||||
|
||||
/**
|
||||
* 文件上传请求
|
||||
*/
|
||||
@PostMapping("upload")
|
||||
public R<SysFile> upload(MultipartFile file) {
|
||||
try {
|
||||
// 上传并返回访问地址
|
||||
String url = sysFileService.uploadFile(file);
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
package com.ruoyi.file.dubbo;
|
||||
|
||||
import com.ruoyi.common.core.exception.ServiceException;
|
||||
import com.ruoyi.common.core.utils.file.FileUtils;
|
||||
import com.ruoyi.file.api.RemoteFileService;
|
||||
import com.ruoyi.file.api.domain.SysFile;
|
||||
import com.ruoyi.file.service.ISysFileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* 文件请求处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@DubboService
|
||||
public class RemoteFileServiceImpl implements RemoteFileService {
|
||||
|
||||
@Autowired
|
||||
private ISysFileService sysFileService;
|
||||
|
||||
/**
|
||||
* 文件上传请求
|
||||
*/
|
||||
@Override
|
||||
public SysFile upload(String name, String originalFilename, String contentType, byte[] file) {
|
||||
// todo 临时用于测试 seata
|
||||
// throw new ServiceException("上传文件失败");
|
||||
|
||||
MultipartFile multipartFile = getMultipartFile(name, originalFilename, contentType, file);
|
||||
try {
|
||||
// 上传并返回访问地址
|
||||
String url = sysFileService.uploadFile(multipartFile);
|
||||
SysFile sysFile = new SysFile();
|
||||
sysFile.setName(FileUtils.getName(url));
|
||||
sysFile.setUrl(url);
|
||||
return sysFile;
|
||||
} catch (Exception e) {
|
||||
log.error("上传文件失败", e);
|
||||
throw new ServiceException("上传文件失败");
|
||||
}
|
||||
}
|
||||
|
||||
private MultipartFile getMultipartFile(String name, String originalFilename, String contentType, byte[] file) {
|
||||
return new MultipartFile() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return getSize() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return file.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() throws IOException {
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(File dest) throws IOException, IllegalStateException {
|
||||
OutputStream outputStream = null;
|
||||
try {
|
||||
outputStream = new FileOutputStream(dest);
|
||||
outputStream.write(file);
|
||||
} finally {
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
package com.ruoyi.file.service;
|
||||
|
||||
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
|
||||
import com.github.tobato.fastdfs.service.FastFileStorageClient;
|
||||
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;
|
||||
|
||||
/**
|
||||
* FastDFS 文件存储
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
public class FastDfsSysFileServiceImpl implements ISysFileService {
|
||||
/**
|
||||
* 域名或本机访问地址
|
||||
*/
|
||||
@Value("${fdfs.domain}")
|
||||
public String domain;
|
||||
|
||||
@Autowired
|
||||
private FastFileStorageClient storageClient;
|
||||
|
||||
/**
|
||||
* FastDfs文件上传接口
|
||||
*
|
||||
* @param file 上传的文件
|
||||
* @return 访问地址
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public String uploadFile(MultipartFile file) throws Exception {
|
||||
StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
|
||||
FilenameUtils.getExtension(file.getOriginalFilename()), null);
|
||||
return domain + "/" + storePath.getFullPath();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
package com.ruoyi.file.service;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 文件上传接口
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ISysFileService {
|
||||
/**
|
||||
* 文件上传接口
|
||||
*
|
||||
* @param file 上传的文件
|
||||
* @return 访问地址
|
||||
* @throws Exception
|
||||
*/
|
||||
String uploadFile(MultipartFile file) throws Exception;
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
package com.ruoyi.file.service;
|
||||
|
||||
import com.ruoyi.file.utils.FileUploadUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 本地文件存储
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Primary
|
||||
@Service
|
||||
public class LocalSysFileServiceImpl implements ISysFileService {
|
||||
/**
|
||||
* 资源映射路径 前缀
|
||||
*/
|
||||
@Value("${file.prefix}")
|
||||
public String localFilePrefix;
|
||||
|
||||
/**
|
||||
* 域名或本机访问地址
|
||||
*/
|
||||
@Value("${file.domain}")
|
||||
public String domain;
|
||||
|
||||
/**
|
||||
* 上传文件存储在本地的根路径
|
||||
*/
|
||||
@Value("${file.path}")
|
||||
private String localFilePath;
|
||||
|
||||
/**
|
||||
* 本地文件上传接口
|
||||
*
|
||||
* @param file 上传的文件
|
||||
* @return 访问地址
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public String uploadFile(MultipartFile file) throws Exception {
|
||||
String name = FileUploadUtils.upload(localFilePath, file);
|
||||
String url = domain + localFilePrefix + name;
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
package com.ruoyi.file.service;
|
||||
|
||||
import com.ruoyi.file.config.MinioConfig;
|
||||
import com.ruoyi.file.utils.FileUploadUtils;
|
||||
import io.minio.MinioClient;
|
||||
import io.minio.PutObjectArgs;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* Minio 文件存储
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
public class MinioSysFileServiceImpl implements ISysFileService {
|
||||
@Autowired
|
||||
private MinioConfig minioConfig;
|
||||
|
||||
@Autowired
|
||||
private MinioClient client;
|
||||
|
||||
/**
|
||||
* 本地文件上传接口
|
||||
*
|
||||
* @param file 上传的文件
|
||||
* @return 访问地址
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public String uploadFile(MultipartFile file) throws Exception {
|
||||
String fileName = FileUploadUtils.extractFilename(file);
|
||||
PutObjectArgs args = PutObjectArgs.builder()
|
||||
.bucket(minioConfig.getBucketName())
|
||||
.object(fileName)
|
||||
.stream(file.getInputStream(), file.getSize(), -1)
|
||||
.contentType(file.getContentType())
|
||||
.build();
|
||||
client.putObject(args);
|
||||
return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
package com.ruoyi.file.utils;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
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.StringUtils;
|
||||
import com.ruoyi.common.core.utils.file.MimeTypeUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 文件上传工具类
|
||||
*
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* 根据文件路径上传
|
||||
*
|
||||
* @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 allowedExtension 上传文件类型
|
||||
* @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() + "/" + IdUtil.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.isAbsolute() ? desc : desc.getAbsoluteFile();
|
||||
}
|
||||
|
||||
private static final String getPathFileName(String fileName) throws IOException {
|
||||
String pathFileName = "/" + fileName;
|
||||
return pathFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件大小校验
|
||||
*
|
||||
* @param file 上传的文件
|
||||
* @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 true/false
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
Spring Boot Version: ${spring-boot.version}
|
||||
Spring Application Name: ${spring.application.name}
|
||||
_ __ _ _
|
||||
(_) / _|(_)| |
|
||||
_ __ _ _ ___ _ _ _ ______ | |_ _ | | ___
|
||||
| '__|| | | | / _ \ | | | || ||______|| _|| || | / _ \
|
||||
| | | |_| || (_) || |_| || | | | | || || __/
|
||||
|_| \__,_| \___/ \__, ||_| |_| |_||_| \___|
|
||||
__/ |
|
||||
|___/
|
||||
|
|
@ -81,12 +81,6 @@
|
|||
<artifactId>ruoyi-common-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RuoYi Common DataSource -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-datasource</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-dubbo</artifactId>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.ruoyi.common.core.constant.GenConstants;
|
|||
import com.ruoyi.common.core.exception.ServiceException;
|
||||
import com.ruoyi.common.core.utils.JsonUtils;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.core.utils.file.FileUtils;
|
||||
import com.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.satoken.utils.LoginHelper;
|
||||
|
|
@ -22,8 +23,6 @@ import com.ruoyi.gen.util.VelocityInitializer;
|
|||
import com.ruoyi.gen.util.VelocityUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.Velocity;
|
||||
|
|
@ -261,8 +260,8 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||
tpl.merge(context, sw);
|
||||
try {
|
||||
String path = getGenPath(table, template);
|
||||
FileUtils.writeStringToFile(new File(path), sw.toString(), StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
FileUtils.writeUtf8String(sw.toString(), path);
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("渲染模板失败,表名:" + table.getTableName());
|
||||
}
|
||||
}
|
||||
|
|
@ -355,8 +354,8 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||
try {
|
||||
// 添加到zip
|
||||
zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
|
||||
IOUtils.write(sw.toString(), zip, Constants.UTF8);
|
||||
IOUtils.closeQuietly(sw);
|
||||
IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString());
|
||||
IoUtil.close(sw);
|
||||
zip.flush();
|
||||
zip.closeEntry();
|
||||
} catch (IOException e) {
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@
|
|||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-file</artifactId>
|
||||
<artifactId>ruoyi-resource</artifactId>
|
||||
|
||||
<description>
|
||||
ruoyi-file文件服务
|
||||
ruoyi-resource资源服务
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
|
@ -35,30 +35,18 @@
|
|||
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Mysql Connector -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot Actuator -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- FastDFS -->
|
||||
<dependency>
|
||||
<groupId>com.github.tobato</groupId>
|
||||
<artifactId>fastdfs-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Minio -->
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>${minio.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-api-file</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RuoYi Common Swagger -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
|
|
@ -80,6 +68,32 @@
|
|||
<artifactId>ruoyi-common-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-log</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-oss</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RuoYi Api System -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-api-system</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-api-resource</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.ruoyi.file;
|
||||
package com.ruoyi.resource;
|
||||
|
||||
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
|
|
@ -6,15 +6,15 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
|
||||
/**
|
||||
* 文件服务
|
||||
* 资源服务
|
||||
*
|
||||
* @author ruoyi
|
||||
* @author Lion Li
|
||||
*/
|
||||
@EnableDubbo
|
||||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
|
||||
public class RuoYiFileApplication {
|
||||
public class RuoYiResourceApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(RuoYiFileApplication.class, args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ 文件服务模块启动成功 ლ(´ڡ`ლ)゙ ");
|
||||
SpringApplication.run(RuoYiResourceApplication.class, args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ 资源服务模块启动成功 ლ(´ڡ`ლ)゙ ");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package com.ruoyi.resource.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.validate.AddGroup;
|
||||
import com.ruoyi.common.core.validate.EditGroup;
|
||||
import com.ruoyi.common.core.validate.QueryGroup;
|
||||
import com.ruoyi.common.core.web.controller.BaseController;
|
||||
import com.ruoyi.common.log.annotation.Log;
|
||||
import com.ruoyi.common.log.enums.BusinessType;
|
||||
import com.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import com.ruoyi.resource.domain.bo.SysOssConfigBo;
|
||||
import com.ruoyi.resource.domain.vo.SysOssConfigVo;
|
||||
import com.ruoyi.resource.service.ISysOssConfigService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 对象存储配置Controller
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
@Validated
|
||||
@Api(value = "对象存储配置控制器", tags = {"对象存储配置管理"})
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/oss/config")
|
||||
public class SysOssConfigController extends BaseController {
|
||||
|
||||
private final ISysOssConfigService iSysOssConfigService;
|
||||
|
||||
/**
|
||||
* 查询对象存储配置列表
|
||||
*/
|
||||
@ApiOperation("查询对象存储配置列表")
|
||||
@SaCheckPermission("system:oss:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo, PageQuery pageQuery) {
|
||||
return iSysOssConfigService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象存储配置详细信息
|
||||
*/
|
||||
@ApiOperation("获取对象存储配置详细信息")
|
||||
@SaCheckPermission("system:oss:query")
|
||||
@GetMapping("/{ossConfigId}")
|
||||
public R<SysOssConfigVo> getInfo(@ApiParam("OSS配置ID")
|
||||
@NotNull(message = "主键不能为空")
|
||||
@PathVariable("ossConfigId") Integer ossConfigId) {
|
||||
return R.ok(iSysOssConfigService.queryById(ossConfigId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增对象存储配置
|
||||
*/
|
||||
@ApiOperation("新增对象存储配置")
|
||||
@SaCheckPermission("system:oss:add")
|
||||
@Log(title = "对象存储配置", businessType = BusinessType.INSERT)
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
|
||||
return toAjax(iSysOssConfigService.insertByBo(bo) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改对象存储配置
|
||||
*/
|
||||
@ApiOperation("修改对象存储配置")
|
||||
@SaCheckPermission("system:oss:edit")
|
||||
@Log(title = "对象存储配置", businessType = BusinessType.UPDATE)
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
|
||||
return toAjax(iSysOssConfigService.updateByBo(bo) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除对象存储配置
|
||||
*/
|
||||
@ApiOperation("删除对象存储配置")
|
||||
@SaCheckPermission("system:oss:remove")
|
||||
@Log(title = "对象存储配置", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ossConfigIds}")
|
||||
public R<Void> remove(@ApiParam("OSS配置ID串")
|
||||
@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ossConfigIds) {
|
||||
return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态修改
|
||||
*/
|
||||
@ApiOperation("状态修改")
|
||||
@SaCheckPermission("system:oss:edit")
|
||||
@Log(title = "对象存储状态修改", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/changeStatus")
|
||||
public R<Void> changeStatus(@RequestBody SysOssConfigBo bo) {
|
||||
return toAjax(iSysOssConfigService.updateOssConfigStatus(bo));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package com.ruoyi.resource.controller;
|
||||
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.http.HttpException;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.exception.ServiceException;
|
||||
import com.ruoyi.common.core.utils.file.FileUtils;
|
||||
import com.ruoyi.common.core.validate.QueryGroup;
|
||||
import com.ruoyi.common.core.web.controller.BaseController;
|
||||
import com.ruoyi.common.log.annotation.Log;
|
||||
import com.ruoyi.common.log.enums.BusinessType;
|
||||
import com.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import com.ruoyi.resource.domain.SysOss;
|
||||
import com.ruoyi.resource.domain.bo.SysOssBo;
|
||||
import com.ruoyi.resource.domain.vo.SysOssVo;
|
||||
import com.ruoyi.resource.service.ISysOssService;
|
||||
import io.swagger.annotations.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 文件上传 控制层
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Validated
|
||||
@Api(value = "对象存储控制器", tags = {"对象存储管理"})
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/oss")
|
||||
public class SysOssController extends BaseController {
|
||||
|
||||
private final ISysOssService iSysOssService;
|
||||
|
||||
/**
|
||||
* 查询OSS对象存储列表
|
||||
*/
|
||||
@ApiOperation("查询OSS对象存储列表")
|
||||
@SaCheckPermission("system:oss:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo, PageQuery pageQuery) {
|
||||
return iSysOssService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传OSS对象存储
|
||||
*/
|
||||
@ApiOperation("上传OSS对象存储")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "file", value = "文件", dataTypeClass = File.class, required = true),
|
||||
})
|
||||
@SaCheckPermission("system:oss:upload")
|
||||
@Log(title = "OSS对象存储", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/upload")
|
||||
public R<Map<String, String>> upload(@RequestPart("file") MultipartFile file) {
|
||||
if (ObjectUtil.isNull(file)) {
|
||||
throw new ServiceException("上传文件不能为空");
|
||||
}
|
||||
SysOss oss = iSysOssService.upload(file);
|
||||
Map<String, String> map = new HashMap<>(2);
|
||||
map.put("url", oss.getUrl());
|
||||
map.put("fileName", oss.getFileName());
|
||||
return R.ok(map);
|
||||
}
|
||||
|
||||
@ApiOperation("下载OSS对象存储")
|
||||
@SaCheckPermission("system:oss:download")
|
||||
@GetMapping("/download/{ossId}")
|
||||
public void download(@ApiParam("OSS对象ID") @PathVariable Long ossId, HttpServletResponse response) throws IOException {
|
||||
SysOss sysOss = iSysOssService.getById(ossId);
|
||||
if (ObjectUtil.isNull(sysOss)) {
|
||||
throw new ServiceException("文件数据不存在!");
|
||||
}
|
||||
response.reset();
|
||||
FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
|
||||
long data;
|
||||
try {
|
||||
data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false);
|
||||
} catch (HttpException e) {
|
||||
if (e.getMessage().contains("403")) {
|
||||
throw new ServiceException("无读取权限, 请在对应的OSS开启'公有读'权限!");
|
||||
} else {
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
response.setContentLength(Convert.toInt(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除OSS对象存储
|
||||
*/
|
||||
@ApiOperation("删除OSS对象存储")
|
||||
@SaCheckPermission("system:oss:remove")
|
||||
@Log(title = "OSS对象存储", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ossIds}")
|
||||
public R<Void> remove(@ApiParam("OSS对象ID串")
|
||||
@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ossIds) {
|
||||
return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true) ? 1 : 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package com.ruoyi.resource.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.core.web.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* OSS对象存储对象
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("sys_oss")
|
||||
public class SysOss extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 对象存储主键
|
||||
*/
|
||||
@TableId(value = "oss_id", type = IdType.AUTO)
|
||||
private Long ossId;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 原名
|
||||
*/
|
||||
private String originalName;
|
||||
|
||||
/**
|
||||
* 文件后缀名
|
||||
*/
|
||||
private String fileSuffix;
|
||||
|
||||
/**
|
||||
* URL地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 服务商
|
||||
*/
|
||||
private String service;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package com.ruoyi.resource.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.core.web.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 对象存储配置对象 sys_oss_config
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("sys_oss_config")
|
||||
public class SysOssConfig extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主建
|
||||
*/
|
||||
@TableId(value = "oss_config_id")
|
||||
private Long ossConfigId;
|
||||
|
||||
/**
|
||||
* 配置key
|
||||
*/
|
||||
private String configKey;
|
||||
|
||||
/**
|
||||
* accessKey
|
||||
*/
|
||||
private String accessKey;
|
||||
|
||||
/**
|
||||
* 秘钥
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 桶名称
|
||||
*/
|
||||
private String bucketName;
|
||||
|
||||
/**
|
||||
* 前缀
|
||||
*/
|
||||
private String prefix;
|
||||
|
||||
/**
|
||||
* 访问站点
|
||||
*/
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* 是否https(0否 1是)
|
||||
*/
|
||||
private String isHttps;
|
||||
|
||||
/**
|
||||
* 域
|
||||
*/
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
private String ext1;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.ruoyi.resource.domain.bo;
|
||||
|
||||
import com.ruoyi.common.core.web.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* OSS对象存储分页查询对象 sys_oss
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("OSS对象存储分页查询对象")
|
||||
public class SysOssBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
@ApiModelProperty("文件名")
|
||||
private String fileName;
|
||||
/**
|
||||
* 原名
|
||||
*/
|
||||
@ApiModelProperty("原名")
|
||||
private String originalName;
|
||||
/**
|
||||
* 文件后缀名
|
||||
*/
|
||||
@ApiModelProperty("文件后缀名")
|
||||
private String fileSuffix;
|
||||
/**
|
||||
* URL地址
|
||||
*/
|
||||
@ApiModelProperty("URL地址")
|
||||
private String url;
|
||||
/**
|
||||
* 服务商
|
||||
*/
|
||||
@ApiModelProperty("服务商")
|
||||
private String service;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
package com.ruoyi.resource.domain.bo;
|
||||
|
||||
import com.ruoyi.common.core.validate.AddGroup;
|
||||
import com.ruoyi.common.core.validate.EditGroup;
|
||||
import com.ruoyi.common.core.web.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 对象存储配置业务对象 sys_oss_config
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ApiModel("对象存储配置业务对象")
|
||||
public class SysOssConfigBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主建
|
||||
*/
|
||||
@ApiModelProperty(value = "主建", required = true)
|
||||
@NotNull(message = "主建不能为空", groups = {EditGroup.class})
|
||||
private Long ossConfigId;
|
||||
|
||||
/**
|
||||
* 配置key
|
||||
*/
|
||||
@ApiModelProperty(value = "configKey", required = true)
|
||||
@NotBlank(message = "configKey不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(min = 2, max = 100, message = "configKey长度必须介于2和20 之间")
|
||||
private String configKey;
|
||||
|
||||
/**
|
||||
* accessKey
|
||||
*/
|
||||
@ApiModelProperty(value = "accessKey", required = true)
|
||||
@NotBlank(message = "accessKey不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(min = 2, max = 100, message = "accessKey长度必须介于2和100 之间")
|
||||
private String accessKey;
|
||||
|
||||
/**
|
||||
* 秘钥
|
||||
*/
|
||||
@ApiModelProperty(value = "secretKey", required = true)
|
||||
@NotBlank(message = "secretKey不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(min = 2, max = 100, message = "secretKey长度必须介于2和100 之间")
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 桶名称
|
||||
*/
|
||||
@ApiModelProperty(value = "bucketName", required = true)
|
||||
@NotBlank(message = "bucketName不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(min = 2, max = 100, message = "bucketName长度必须介于2和100之间")
|
||||
private String bucketName;
|
||||
|
||||
/**
|
||||
* 前缀
|
||||
*/
|
||||
@ApiModelProperty(value = "前缀")
|
||||
private String prefix;
|
||||
|
||||
/**
|
||||
* 访问站点
|
||||
*/
|
||||
@ApiModelProperty(value = "endpoint", required = true)
|
||||
@NotBlank(message = "endpoint不能为空", groups = {AddGroup.class, EditGroup.class})
|
||||
@Size(min = 2, max = 100, message = "endpoint长度必须介于2和100之间")
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* 是否https(Y=是,N=否)
|
||||
*/
|
||||
@ApiModelProperty("是否https(Y=是,N=否)")
|
||||
private String isHttps;
|
||||
|
||||
/**
|
||||
* 状态(0=正常,1=停用)
|
||||
*/
|
||||
@ApiModelProperty("状态(0=正常,1=停用)")
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 域
|
||||
*/
|
||||
@ApiModelProperty(value = "region")
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
@ApiModelProperty(value = "扩展字段")
|
||||
private String ext1;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package com.ruoyi.resource.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
/**
|
||||
* 对象存储配置视图对象 sys_oss_config
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("对象存储配置视图对象")
|
||||
public class SysOssConfigVo {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主建
|
||||
*/
|
||||
@ApiModelProperty("主建")
|
||||
private Long ossConfigId;
|
||||
|
||||
/**
|
||||
* 配置key
|
||||
*/
|
||||
@ApiModelProperty("配置key")
|
||||
private String configKey;
|
||||
|
||||
/**
|
||||
* accessKey
|
||||
*/
|
||||
@ApiModelProperty("accessKey")
|
||||
private String accessKey;
|
||||
|
||||
/**
|
||||
* 秘钥
|
||||
*/
|
||||
@ApiModelProperty("secretKey")
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 桶名称
|
||||
*/
|
||||
@ApiModelProperty("桶名称")
|
||||
private String bucketName;
|
||||
|
||||
/**
|
||||
* 前缀
|
||||
*/
|
||||
@ApiModelProperty("前缀")
|
||||
private String prefix;
|
||||
|
||||
/**
|
||||
* 访问站点
|
||||
*/
|
||||
@ApiModelProperty("访问站点")
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* 是否https(Y=是,N=否)
|
||||
*/
|
||||
@ApiModelProperty("是否https(Y=是,N=否)")
|
||||
private String isHttps;
|
||||
|
||||
/**
|
||||
* 域
|
||||
*/
|
||||
@ApiModelProperty("域")
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* 状态(0=正常,1=停用)
|
||||
*/
|
||||
@ApiModelProperty("状态(0=正常,1=停用)")
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
@ApiModelProperty("扩展字段")
|
||||
private String ext1;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ApiModelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package com.ruoyi.resource.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* OSS对象存储视图对象 sys_oss
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("OSS对象存储视图对象")
|
||||
public class SysOssVo {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 对象存储主键
|
||||
*/
|
||||
@ApiModelProperty("对象存储主键")
|
||||
private Long ossId;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
@ApiModelProperty("文件名")
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 原名
|
||||
*/
|
||||
@ApiModelProperty("原名")
|
||||
private String originalName;
|
||||
|
||||
/**
|
||||
* 文件后缀名
|
||||
*/
|
||||
@ApiModelProperty("文件后缀名")
|
||||
private String fileSuffix;
|
||||
|
||||
/**
|
||||
* URL地址
|
||||
*/
|
||||
@ApiModelProperty("URL地址")
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ApiModelProperty("创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 上传人
|
||||
*/
|
||||
@ApiModelProperty("上传人")
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 服务商
|
||||
*/
|
||||
@ApiModelProperty("服务商")
|
||||
private String service;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package com.ruoyi.resource.dubbo;
|
||||
|
||||
import com.ruoyi.common.core.exception.ServiceException;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.oss.entity.UploadResult;
|
||||
import com.ruoyi.common.oss.factory.OssFactory;
|
||||
import com.ruoyi.common.oss.service.IOssStrategy;
|
||||
import com.ruoyi.resource.api.RemoteFileService;
|
||||
import com.ruoyi.resource.api.domain.SysFile;
|
||||
import com.ruoyi.resource.domain.SysOss;
|
||||
import com.ruoyi.resource.mapper.SysOssMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 文件请求处理
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@DubboService
|
||||
public class RemoteFileServiceImpl implements RemoteFileService {
|
||||
|
||||
@Autowired
|
||||
private SysOssMapper sysOssMapper;
|
||||
|
||||
/**
|
||||
* 文件上传请求
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public SysFile upload(String name, String originalFilename, String contentType, byte[] file) {
|
||||
try {
|
||||
String suffix = StringUtils.substring(originalFilename, originalFilename.lastIndexOf("."), originalFilename.length());
|
||||
IOssStrategy storage = OssFactory.instance();
|
||||
UploadResult uploadResult = storage.uploadSuffix(file, suffix, contentType);
|
||||
// 保存文件信息
|
||||
SysOss oss = new SysOss();
|
||||
oss.setUrl(uploadResult.getUrl());
|
||||
oss.setFileSuffix(suffix);
|
||||
oss.setFileName(uploadResult.getFilename());
|
||||
oss.setOriginalName(originalFilename);
|
||||
oss.setService(storage.getServiceType().getValue());
|
||||
sysOssMapper.insert(oss);
|
||||
SysFile sysFile = new SysFile();
|
||||
sysFile.setName(uploadResult.getFilename());
|
||||
sysFile.setUrl(uploadResult.getUrl());
|
||||
return sysFile;
|
||||
} catch (Exception e) {
|
||||
log.error("上传文件失败", e);
|
||||
throw new ServiceException("上传文件失败");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.ruoyi.resource.mapper;
|
||||
|
||||
|
||||
import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import com.ruoyi.resource.domain.SysOssConfig;
|
||||
import com.ruoyi.resource.domain.vo.SysOssConfigVo;
|
||||
|
||||
/**
|
||||
* 对象存储配置Mapper接口
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
public interface SysOssConfigMapper extends BaseMapperPlus<SysOssConfigMapper, SysOssConfig, SysOssConfigVo> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.ruoyi.resource.mapper;
|
||||
|
||||
import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import com.ruoyi.resource.domain.SysOss;
|
||||
import com.ruoyi.resource.domain.vo.SysOssVo;
|
||||
|
||||
/**
|
||||
* 文件上传 数据层
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface SysOssMapper extends BaseMapperPlus<SysOssMapper, SysOss, SysOssVo> {
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.ruoyi.resource.runner;
|
||||
|
||||
import com.ruoyi.resource.service.ISysOssConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 初始化 system 模块对应业务数据
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class ResourceApplicationRunner implements ApplicationRunner {
|
||||
|
||||
private final ISysOssConfigService ossConfigService;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
ossConfigService.init();
|
||||
log.info("初始化OSS配置成功");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package com.ruoyi.resource.service;
|
||||
|
||||
|
||||
import com.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import com.ruoyi.resource.domain.bo.SysOssConfigBo;
|
||||
import com.ruoyi.resource.domain.vo.SysOssConfigVo;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 对象存储配置Service接口
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
public interface ISysOssConfigService {
|
||||
|
||||
/**
|
||||
* 初始化OSS配置
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* 查询单个
|
||||
*/
|
||||
SysOssConfigVo queryById(Integer ossConfigId);
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo, PageQuery pageQuery);
|
||||
|
||||
|
||||
/**
|
||||
* 根据新增业务对象插入对象存储配置
|
||||
*
|
||||
* @param bo 对象存储配置新增业务对象
|
||||
* @return
|
||||
*/
|
||||
Boolean insertByBo(SysOssConfigBo bo);
|
||||
|
||||
/**
|
||||
* 根据编辑业务对象修改对象存储配置
|
||||
*
|
||||
* @param bo 对象存储配置编辑业务对象
|
||||
* @return
|
||||
*/
|
||||
Boolean updateByBo(SysOssConfigBo bo);
|
||||
|
||||
/**
|
||||
* 校验并删除数据
|
||||
*
|
||||
* @param ids 主键集合
|
||||
* @param isValid 是否校验,true-删除前校验,false-不校验
|
||||
* @return
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 启用停用状态
|
||||
*/
|
||||
int updateOssConfigStatus(SysOssConfigBo bo);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.ruoyi.resource.service;
|
||||
|
||||
import com.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import com.ruoyi.resource.domain.SysOss;
|
||||
import com.ruoyi.resource.domain.bo.SysOssBo;
|
||||
import com.ruoyi.resource.domain.vo.SysOssVo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 文件上传 服务层
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public interface ISysOssService {
|
||||
|
||||
TableDataInfo<SysOssVo> queryPageList(SysOssBo sysOss, PageQuery pageQuery);
|
||||
|
||||
SysOss getById(Long ossId);
|
||||
|
||||
SysOss upload(MultipartFile file);
|
||||
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
package com.ruoyi.resource.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.ruoyi.common.core.constant.UserConstants;
|
||||
import com.ruoyi.common.core.exception.ServiceException;
|
||||
import com.ruoyi.common.core.utils.JsonUtils;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.oss.constant.OssConstant;
|
||||
import com.ruoyi.common.oss.factory.OssFactory;
|
||||
import com.ruoyi.common.redis.utils.RedisUtils;
|
||||
import com.ruoyi.resource.domain.SysOssConfig;
|
||||
import com.ruoyi.resource.domain.bo.SysOssConfigBo;
|
||||
import com.ruoyi.resource.domain.vo.SysOssConfigVo;
|
||||
import com.ruoyi.resource.mapper.SysOssConfigMapper;
|
||||
import com.ruoyi.resource.service.ISysOssConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 对象存储配置Service业务层处理
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author 孤舟烟雨
|
||||
* @date 2021-08-13
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class SysOssConfigServiceImpl implements ISysOssConfigService {
|
||||
|
||||
private final SysOssConfigMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 项目启动时,初始化参数到缓存,加载配置类
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
List<SysOssConfig> list = baseMapper.selectList();
|
||||
// 加载OSS初始化配置
|
||||
for (SysOssConfig config : list) {
|
||||
String configKey = config.getConfigKey();
|
||||
if ("0".equals(config.getStatus())) {
|
||||
RedisUtils.setCacheObject(OssConstant.CACHE_CONFIG_KEY, configKey);
|
||||
}
|
||||
setConfigCache(true, config);
|
||||
}
|
||||
// 初始化OSS工厂
|
||||
OssFactory.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysOssConfigVo queryById(Integer ossConfigId) {
|
||||
return baseMapper.selectVoById(ossConfigId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<SysOssConfig> lqw = buildQueryWrapper(bo);
|
||||
Page<SysOssConfigVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
|
||||
private LambdaQueryWrapper<SysOssConfig> buildQueryWrapper(SysOssConfigBo bo) {
|
||||
LambdaQueryWrapper<SysOssConfig> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getConfigKey()), SysOssConfig::getConfigKey, bo.getConfigKey());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getBucketName()), SysOssConfig::getBucketName, bo.getBucketName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysOssConfig::getStatus, bo.getStatus());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean insertByBo(SysOssConfigBo bo) {
|
||||
SysOssConfig config = BeanUtil.toBean(bo, SysOssConfig.class);
|
||||
validEntityBeforeSave(config);
|
||||
return setConfigCache(baseMapper.insert(config) > 0, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updateByBo(SysOssConfigBo bo) {
|
||||
SysOssConfig config = BeanUtil.toBean(bo, SysOssConfig.class);
|
||||
validEntityBeforeSave(config);
|
||||
LambdaUpdateWrapper<SysOssConfig> luw = new LambdaUpdateWrapper<>();
|
||||
luw.set(StringUtils.isBlank(config.getPrefix()), SysOssConfig::getPrefix, "");
|
||||
luw.set(StringUtils.isBlank(config.getRegion()), SysOssConfig::getRegion, "");
|
||||
luw.set(StringUtils.isBlank(config.getExt1()), SysOssConfig::getExt1, "");
|
||||
luw.eq(SysOssConfig::getOssConfigId, config.getOssConfigId());
|
||||
return setConfigCache(baseMapper.update(config, luw) > 0, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(SysOssConfig entity) {
|
||||
if (StringUtils.isNotEmpty(entity.getConfigKey())
|
||||
&& UserConstants.NOT_UNIQUE.equals(checkConfigKeyUnique(entity))) {
|
||||
throw new ServiceException("操作配置'" + entity.getConfigKey() + "'失败, 配置key已存在!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
if (CollUtil.containsAny(ids, OssConstant.SYSTEM_DATA_IDS)) {
|
||||
throw new ServiceException("系统内置, 不可删除!");
|
||||
}
|
||||
}
|
||||
List<SysOssConfig> list = Lists.newArrayList();
|
||||
for (Long configId : ids) {
|
||||
SysOssConfig config = baseMapper.selectById(configId);
|
||||
list.add(config);
|
||||
}
|
||||
boolean flag = baseMapper.deleteBatchIds(ids) > 0;
|
||||
if (flag) {
|
||||
list.stream().forEach(sysOssConfig -> {
|
||||
RedisUtils.deleteObject(getCacheKey(sysOssConfig.getConfigKey()));
|
||||
});
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断configKey是否唯一
|
||||
*/
|
||||
private String checkConfigKeyUnique(SysOssConfig sysOssConfig) {
|
||||
long ossConfigId = ObjectUtil.isNull(sysOssConfig.getOssConfigId()) ? -1L : sysOssConfig.getOssConfigId();
|
||||
SysOssConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysOssConfig>()
|
||||
.select(SysOssConfig::getOssConfigId, SysOssConfig::getConfigKey)
|
||||
.eq(SysOssConfig::getConfigKey, sysOssConfig.getConfigKey()));
|
||||
if (ObjectUtil.isNotNull(info) && info.getOssConfigId() != ossConfigId) {
|
||||
return UserConstants.NOT_UNIQUE;
|
||||
}
|
||||
return UserConstants.UNIQUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用禁用状态
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int updateOssConfigStatus(SysOssConfigBo bo) {
|
||||
SysOssConfig sysOssConfig = BeanUtil.toBean(bo, SysOssConfig.class);
|
||||
int row = baseMapper.update(null, new LambdaUpdateWrapper<SysOssConfig>()
|
||||
.set(SysOssConfig::getStatus, "1"));
|
||||
row += baseMapper.updateById(sysOssConfig);
|
||||
if (row > 0) {
|
||||
RedisUtils.setCacheObject(OssConstant.CACHE_CONFIG_KEY, sysOssConfig.getConfigKey());
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置cache key
|
||||
*
|
||||
* @param configKey 参数键
|
||||
* @return 缓存键key
|
||||
*/
|
||||
private String getCacheKey(String configKey) {
|
||||
return OssConstant.SYS_OSS_KEY + configKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果操作成功 则更新缓存
|
||||
*
|
||||
* @param flag 操作状态
|
||||
* @param config 配置
|
||||
* @return 返回操作状态
|
||||
*/
|
||||
private boolean setConfigCache(boolean flag, SysOssConfig config) {
|
||||
if (flag) {
|
||||
RedisUtils.setCacheObject(
|
||||
getCacheKey(config.getConfigKey()),
|
||||
JsonUtils.toJsonString(config));
|
||||
RedisUtils.publish(OssConstant.CACHE_CONFIG_KEY, config.getConfigKey(), msg -> {
|
||||
log.info("发布刷新OSS配置 => " + msg);
|
||||
});
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package com.ruoyi.resource.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.core.exception.ServiceException;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.oss.entity.UploadResult;
|
||||
import com.ruoyi.common.oss.factory.OssFactory;
|
||||
import com.ruoyi.common.oss.service.IOssStrategy;
|
||||
import com.ruoyi.resource.domain.SysOss;
|
||||
import com.ruoyi.resource.domain.bo.SysOssBo;
|
||||
import com.ruoyi.resource.domain.vo.SysOssVo;
|
||||
import com.ruoyi.resource.mapper.SysOssMapper;
|
||||
import com.ruoyi.resource.service.ISysOssService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 文件上传 服务层实现
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class SysOssServiceImpl implements ISysOssService {
|
||||
|
||||
private final SysOssMapper baseMapper;
|
||||
|
||||
@Override
|
||||
public TableDataInfo<SysOssVo> queryPageList(SysOssBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<SysOss> lqw = buildQueryWrapper(bo);
|
||||
Page<SysOssVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<SysOss> buildQueryWrapper(SysOssBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<SysOss> lqw = Wrappers.lambdaQuery();
|
||||
lqw.like(StringUtils.isNotBlank(bo.getFileName()), SysOss::getFileName, bo.getFileName());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getOriginalName()), SysOss::getOriginalName, bo.getOriginalName());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getFileSuffix()), SysOss::getFileSuffix, bo.getFileSuffix());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getUrl()), SysOss::getUrl, bo.getUrl());
|
||||
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
|
||||
SysOss::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), SysOss::getCreateBy, bo.getCreateBy());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getService()), SysOss::getService, bo.getService());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysOss getById(Long ossId) {
|
||||
return baseMapper.selectById(ossId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysOss upload(MultipartFile file) {
|
||||
String originalfileName = file.getOriginalFilename();
|
||||
String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
|
||||
IOssStrategy storage = OssFactory.instance();
|
||||
UploadResult uploadResult;
|
||||
try {
|
||||
uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType());
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
// 保存文件信息
|
||||
SysOss oss = new SysOss();
|
||||
oss.setUrl(uploadResult.getUrl());
|
||||
oss.setFileSuffix(suffix);
|
||||
oss.setFileName(uploadResult.getFilename());
|
||||
oss.setOriginalName(originalfileName);
|
||||
oss.setService(storage.getServiceType().getValue());
|
||||
baseMapper.insert(oss);
|
||||
return oss;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
// 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
List<SysOss> list = baseMapper.selectBatchIds(ids);
|
||||
for (SysOss sysOss : list) {
|
||||
IOssStrategy storage = OssFactory.instance(sysOss.getService());
|
||||
storage.delete(sysOss.getUrl());
|
||||
}
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
Spring Boot Version: ${spring-boot.version}
|
||||
Spring Application Name: ${spring.application.name}
|
||||
_
|
||||
(_)
|
||||
_ __ _ _ ___ _ _ _ ______ _ __ ___ ___ ___ _ _ _ __ ___ ___
|
||||
| '__| | | |/ _ \| | | | |______| '__/ _ \/ __|/ _ \| | | | '__/ __/ _ \
|
||||
| | | |_| | (_) | |_| | | | | | __/\__ \ (_) | |_| | | | (_| __/
|
||||
|_| \__,_|\___/ \__, |_| |_| \___||___/\___/ \__,_|_| \___\___|
|
||||
__/ |
|
||||
|___/
|
||||
|
|
@ -9,7 +9,7 @@ spring:
|
|||
allow-circular-references: true
|
||||
application:
|
||||
# 应用名称
|
||||
name: ruoyi-file
|
||||
name: ruoyi-resource
|
||||
profiles:
|
||||
# 环境配置
|
||||
active: @profiles.active@
|
||||
|
|
@ -34,3 +34,5 @@ spring:
|
|||
shared-configs:
|
||||
- data-id: application.${spring.cloud.nacos.config.file-extension}
|
||||
refresh: true
|
||||
- data-id: datasource.${spring.cloud.nacos.config.file-extension}
|
||||
refresh: true
|
||||
|
|
@ -1,97 +1,97 @@
|
|||
<?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="console.log.pattern"
|
||||
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
||||
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${console.log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/console.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/console.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大 1天 -->
|
||||
<maxHistory>1</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
</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" />
|
||||
<appender-ref ref="file_console" />
|
||||
</root>
|
||||
</configuration>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" value="logs/ruoyi-resource" />
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="console.log.pattern"
|
||||
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
||||
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${console.log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/console.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/console.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大 1天 -->
|
||||
<maxHistory>1</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
</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" />
|
||||
<appender-ref ref="file_console" />
|
||||
</root>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
java包使用 `.` 分割 resource 目录使用 `/` 分割
|
||||
<br>
|
||||
此文件目的 防止文件夹粘连找不到 `xml` 文件
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.resource.mapper.SysOssConfigMapper">
|
||||
|
||||
<resultMap type="com.ruoyi.resource.domain.SysOssConfig" id="SysOssConfigResult">
|
||||
<result property="ossConfigId" column="oss_config_id"/>
|
||||
<result property="configKey" column="config_key"/>
|
||||
<result property="accessKey" column="access_key"/>
|
||||
<result property="secretKey" column="secret_key"/>
|
||||
<result property="bucketName" column="bucket_name"/>
|
||||
<result property="prefix" column="prefix"/>
|
||||
<result property="endpoint" column="endpoint"/>
|
||||
<result property="isHttps" column="is_https"/>
|
||||
<result property="region" column="region"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="ext1" column="ext1"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="remark" column="remark"/>
|
||||
</resultMap>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.resource.mapper.SysOssMapper">
|
||||
|
||||
<resultMap type="com.ruoyi.resource.domain.SysOss" id="SysOssResult">
|
||||
<result property="ossId" column="oss_id"/>
|
||||
<result property="fileName" column="file_name"/>
|
||||
<result property="fileSuffix" column="file_suffix"/>
|
||||
<result property="url" column="url"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="service" column="service"/>
|
||||
</resultMap>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# p6spy 性能分析插件配置文件
|
||||
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
|
||||
# 自定义日志打印
|
||||
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
|
||||
#日志输出到控制台
|
||||
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
|
||||
# 使用日志系统记录 sql
|
||||
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
|
||||
# 设置 p6spy driver 代理
|
||||
#deregisterdrivers=true
|
||||
# 取消JDBC URL前缀
|
||||
useprefix=true
|
||||
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
|
||||
excludecategories=info,debug,result,commit,resultset
|
||||
# 日期格式
|
||||
dateformat=yyyy-MM-dd HH:mm:ss
|
||||
# 实际驱动可多个
|
||||
#driverlist=org.h2.Driver
|
||||
# 是否开启慢SQL记录
|
||||
outagedetection=true
|
||||
# 慢SQL记录标准 2 秒
|
||||
outagedetectioninterval=2
|
||||
# 是否过滤 Log
|
||||
filter=true
|
||||
|
|
@ -47,12 +47,6 @@
|
|||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RuoYi Common DataSource -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-datasource</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RuoYi Common Log -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
|
|
@ -103,7 +97,7 @@
|
|||
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-api-file</artifactId>
|
||||
<artifactId>ruoyi-api-resource</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -99,6 +99,17 @@ public class SysConfigController extends BaseController {
|
|||
return toAjax(configService.updateConfig(config));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据参数键名修改参数配置
|
||||
*/
|
||||
@ApiOperation("根据参数键名修改参数配置")
|
||||
@SaCheckPermission("system:config:edit")
|
||||
@Log(title = "参数管理", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/updateByKey")
|
||||
public R<Void> updateByKey(@RequestBody SysConfig config) {
|
||||
return toAjax(configService.updateConfig(config));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除参数配置
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@ import com.ruoyi.common.log.annotation.Log;
|
|||
import com.ruoyi.common.log.enums.BusinessType;
|
||||
import com.ruoyi.common.satoken.utils.LoginHelper;
|
||||
import com.ruoyi.common.security.utils.SecurityUtils;
|
||||
import com.ruoyi.file.api.RemoteFileService;
|
||||
import com.ruoyi.file.api.domain.SysFile;
|
||||
import com.ruoyi.resource.api.RemoteFileService;
|
||||
import com.ruoyi.resource.api.domain.SysFile;
|
||||
import com.ruoyi.system.api.domain.SysUser;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
import io.seata.spring.annotation.GlobalTransactional;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
|
|
@ -111,17 +112,14 @@ public class SysProfileController extends BaseController {
|
|||
/**
|
||||
* 头像上传
|
||||
*/
|
||||
// @GlobalTransactional(rollbackFor = Exception.class)
|
||||
@GlobalTransactional(rollbackFor = Exception.class)
|
||||
@ApiOperation("头像上传")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "avatarfile", value = "用户头像", dataTypeClass = File.class, required = true),
|
||||
})
|
||||
@Log(title = "用户头像", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/avatar")
|
||||
public R<Map<String, Object>> avatar(@RequestParam("avatarfile") MultipartFile file) throws IOException {
|
||||
// todo 临时用于测试 seata
|
||||
// userService.insertUser(new SysUser().setUserName("test").setNickName("test"));
|
||||
|
||||
public R<Map<String, Object>> avatar(@RequestPart("avatarfile") MultipartFile file) throws IOException {
|
||||
if (!file.isEmpty()) {
|
||||
SysFile sysFile = remoteFileService.upload(file.getName(), file.getOriginalFilename(), file.getContentType(), file.getBytes());
|
||||
if (ObjectUtil.isNull(sysFile)) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package com.ruoyi.system.runner;
|
||||
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.system.service.ISysDictTypeService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 初始化 system 模块对应业务数据
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class SystemApplicationRunner implements ApplicationRunner {
|
||||
|
||||
private final ISysConfigService configService;
|
||||
private final ISysDictTypeService dictTypeService;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
configService.loadingConfigCache();
|
||||
log.info("加载参数缓存数据成功");
|
||||
dictTypeService.loadingDictCache();
|
||||
log.info("加载字典缓存数据成功");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -34,14 +34,6 @@ public class SysConfigServiceImpl implements ISysConfigService {
|
|||
|
||||
private final SysConfigMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 项目启动时,初始化参数到缓存
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
loadingConfigCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataInfo<SysConfig> selectPageConfigList(SysConfig config, PageQuery pageQuery) {
|
||||
Map<String, Object> params = config.getParams();
|
||||
|
|
@ -128,7 +120,13 @@ public class SysConfigServiceImpl implements ISysConfigService {
|
|||
*/
|
||||
@Override
|
||||
public int updateConfig(SysConfig config) {
|
||||
int row = baseMapper.updateById(config);
|
||||
int row = 0;
|
||||
if (config.getConfigId() != null) {
|
||||
row = baseMapper.updateById(config);
|
||||
} else {
|
||||
row = baseMapper.update(config, new LambdaQueryWrapper<SysConfig>()
|
||||
.eq(SysConfig::getConfigKey, config.getConfigKey()));
|
||||
}
|
||||
if (row > 0) {
|
||||
RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,14 +39,6 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService {
|
|||
private final SysDictTypeMapper baseMapper;
|
||||
private final SysDictDataMapper dictDataMapper;
|
||||
|
||||
/**
|
||||
* 项目启动时,初始化字典到缓存
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
loadingDictCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataInfo<SysDictType> selectPageDictTypeList(SysDictType dictType, PageQuery pageQuery) {
|
||||
Map<String, Object> params = dictType.getParams();
|
||||
|
|
|
|||
|
|
@ -1,60 +1,72 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 查询参数列表
|
||||
export function listConfig(query) {
|
||||
return request({
|
||||
url: '/system/config/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询参数详细
|
||||
export function getConfig(configId) {
|
||||
return request({
|
||||
url: '/system/config/' + configId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据参数键名查询参数值
|
||||
export function getConfigKey(configKey) {
|
||||
return request({
|
||||
url: '/system/config/configKey/' + configKey,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增参数配置
|
||||
export function addConfig(data) {
|
||||
return request({
|
||||
url: '/system/config',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改参数配置
|
||||
export function updateConfig(data) {
|
||||
return request({
|
||||
url: '/system/config',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除参数配置
|
||||
export function delConfig(configId) {
|
||||
return request({
|
||||
url: '/system/config/' + configId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 刷新参数缓存
|
||||
export function refreshCache() {
|
||||
return request({
|
||||
url: '/system/config/refreshCache',
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询参数列表
|
||||
export function listConfig(query) {
|
||||
return request({
|
||||
url: '/system/config/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询参数详细
|
||||
export function getConfig(configId) {
|
||||
return request({
|
||||
url: '/system/config/' + configId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 根据参数键名查询参数值
|
||||
export function getConfigKey(configKey) {
|
||||
return request({
|
||||
url: '/system/config/configKey/' + configKey,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增参数配置
|
||||
export function addConfig(data) {
|
||||
return request({
|
||||
url: '/system/config',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改参数配置
|
||||
export function updateConfig(data) {
|
||||
return request({
|
||||
url: '/system/config',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改参数配置
|
||||
export function updateConfigByKey(key, value) {
|
||||
return request({
|
||||
url: '/system/config/updateByKey',
|
||||
method: 'put',
|
||||
data: {
|
||||
configKey: key,
|
||||
configValue: value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 删除参数配置
|
||||
export function delConfig(configId) {
|
||||
return request({
|
||||
url: '/system/config/' + configId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 刷新参数缓存
|
||||
export function refreshCache() {
|
||||
return request({
|
||||
url: '/system/config/refreshCache',
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 查询OSS对象存储列表
|
||||
export function listOss(query) {
|
||||
return request({
|
||||
url: '/resource/oss/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 删除OSS对象存储
|
||||
export function delOss(ossId) {
|
||||
return request({
|
||||
url: '/resource/oss/' + ossId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 查询对象存储配置列表
|
||||
export function listOssConfig(query) {
|
||||
return request({
|
||||
url: '/resource/oss/config/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询对象存储配置详细
|
||||
export function getOssConfig(ossConfigId) {
|
||||
return request({
|
||||
url: '/resource/oss/config/' + ossConfigId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增对象存储配置
|
||||
export function addOssConfig(data) {
|
||||
return request({
|
||||
url: '/resource/oss/config',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改对象存储配置
|
||||
export function updateOssConfig(data) {
|
||||
return request({
|
||||
url: '/resource/oss/config',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除对象存储配置
|
||||
export function delOssConfig(ossConfigId) {
|
||||
return request({
|
||||
url: '/resource/oss/config/' + ossConfigId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 用户状态修改
|
||||
export function changeOssConfigStatus(ossConfigId, status, configKey) {
|
||||
const data = {
|
||||
ossConfigId,
|
||||
status,
|
||||
configKey
|
||||
}
|
||||
return request({
|
||||
url: '/resource/oss/config/changeStatus',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
@ -1,272 +1,272 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-upload
|
||||
:action="uploadUrl"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleUploadError"
|
||||
name="file"
|
||||
:show-file-list="false"
|
||||
:headers="headers"
|
||||
style="display: none"
|
||||
ref="upload"
|
||||
v-if="this.type == 'url'"
|
||||
>
|
||||
</el-upload>
|
||||
<div class="editor" ref="editor" :style="styles"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Quill from "quill";
|
||||
import "quill/dist/quill.core.css";
|
||||
import "quill/dist/quill.snow.css";
|
||||
import "quill/dist/quill.bubble.css";
|
||||
import { getToken } from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
name: "Editor",
|
||||
props: {
|
||||
/* 编辑器的内容 */
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
/* 高度 */
|
||||
height: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
/* 最小高度 */
|
||||
minHeight: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
/* 只读 */
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 上传文件大小限制(MB)
|
||||
fileSize: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
/* 类型(base64格式、url格式) */
|
||||
type: {
|
||||
type: String,
|
||||
default: "url",
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
uploadUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传的图片服务器地址
|
||||
headers: {
|
||||
Authorization: "Bearer " + getToken()
|
||||
},
|
||||
Quill: null,
|
||||
currentValue: "",
|
||||
options: {
|
||||
theme: "snow",
|
||||
bounds: document.body,
|
||||
debug: "warn",
|
||||
modules: {
|
||||
// 工具栏配置
|
||||
toolbar: [
|
||||
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
|
||||
["blockquote", "code-block"], // 引用 代码块
|
||||
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
|
||||
[{ indent: "-1" }, { indent: "+1" }], // 缩进
|
||||
[{ size: ["small", false, "large", "huge"] }], // 字体大小
|
||||
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
|
||||
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
|
||||
[{ align: [] }], // 对齐方式
|
||||
["clean"], // 清除文本格式
|
||||
["link", "image", "video"] // 链接、图片、视频
|
||||
],
|
||||
},
|
||||
placeholder: "请输入内容",
|
||||
readOnly: this.readOnly,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
styles() {
|
||||
let style = {};
|
||||
if (this.minHeight) {
|
||||
style.minHeight = `${this.minHeight}px`;
|
||||
}
|
||||
if (this.height) {
|
||||
style.height = `${this.height}px`;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
if (val !== this.currentValue) {
|
||||
this.currentValue = val === null ? "" : val;
|
||||
if (this.Quill) {
|
||||
this.Quill.pasteHTML(this.currentValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.Quill = null;
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
const editor = this.$refs.editor;
|
||||
this.Quill = new Quill(editor, this.options);
|
||||
// 如果设置了上传地址则自定义图片上传事件
|
||||
if (this.type == 'url') {
|
||||
let toolbar = this.Quill.getModule("toolbar");
|
||||
toolbar.addHandler("image", (value) => {
|
||||
this.uploadType = "image";
|
||||
if (value) {
|
||||
this.$refs.upload.$children[0].$refs.input.click();
|
||||
} else {
|
||||
this.quill.format("image", false);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.Quill.pasteHTML(this.currentValue);
|
||||
this.Quill.on("text-change", (delta, oldDelta, source) => {
|
||||
const html = this.$refs.editor.children[0].innerHTML;
|
||||
const text = this.Quill.getText();
|
||||
const quill = this.Quill;
|
||||
this.currentValue = html;
|
||||
this.$emit("input", html);
|
||||
this.$emit("on-change", { html, text, quill });
|
||||
});
|
||||
this.Quill.on("text-change", (delta, oldDelta, source) => {
|
||||
this.$emit("on-text-change", delta, oldDelta, source);
|
||||
});
|
||||
this.Quill.on("selection-change", (range, oldRange, source) => {
|
||||
this.$emit("on-selection-change", range, oldRange, source);
|
||||
});
|
||||
this.Quill.on("editor-change", (eventName, ...args) => {
|
||||
this.$emit("on-editor-change", eventName, ...args);
|
||||
});
|
||||
},
|
||||
// 上传前校检格式和大小
|
||||
handleBeforeUpload(file) {
|
||||
// 校检文件大小
|
||||
if (this.fileSize) {
|
||||
const isLt = file.size / 1024 / 1024 < this.fileSize;
|
||||
if (!isLt) {
|
||||
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
handleUploadSuccess(res, file) {
|
||||
// 获取富文本组件实例
|
||||
let quill = this.Quill;
|
||||
// 如果上传成功
|
||||
if (res.code == 200) {
|
||||
// 获取光标所在位置
|
||||
let length = quill.getSelection().index;
|
||||
// 插入图片 res.url为服务器返回的图片地址
|
||||
quill.insertEmbed(length, "image", res.data.url);
|
||||
// 调整光标到最后
|
||||
quill.setSelection(length + 1);
|
||||
} else {
|
||||
this.$message.error("图片插入失败");
|
||||
}
|
||||
},
|
||||
handleUploadError() {
|
||||
this.$message.error("图片插入失败");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.editor, .ql-toolbar {
|
||||
white-space: pre-wrap !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
.quill-img {
|
||||
display: none;
|
||||
}
|
||||
.ql-snow .ql-tooltip[data-mode="link"]::before {
|
||||
content: "请输入链接地址:";
|
||||
}
|
||||
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
||||
border-right: 0px;
|
||||
content: "保存";
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.ql-snow .ql-tooltip[data-mode="video"]::before {
|
||||
content: "请输入视频地址:";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
||||
content: "14px";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
|
||||
content: "10px";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
|
||||
content: "18px";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
|
||||
content: "32px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
||||
content: "文本";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
||||
content: "标题1";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
||||
content: "标题2";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
||||
content: "标题3";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
||||
content: "标题4";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
||||
content: "标题5";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
||||
content: "标题6";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
||||
content: "标准字体";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
|
||||
content: "衬线字体";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
|
||||
content: "等宽字体";
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div>
|
||||
<el-upload
|
||||
:action="uploadUrl"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleUploadError"
|
||||
name="file"
|
||||
:show-file-list="false"
|
||||
:headers="headers"
|
||||
style="display: none"
|
||||
ref="upload"
|
||||
v-if="this.type == 'url'"
|
||||
>
|
||||
</el-upload>
|
||||
<div class="editor" ref="editor" :style="styles"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Quill from "quill";
|
||||
import "quill/dist/quill.core.css";
|
||||
import "quill/dist/quill.snow.css";
|
||||
import "quill/dist/quill.bubble.css";
|
||||
import { getToken } from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
name: "Editor",
|
||||
props: {
|
||||
/* 编辑器的内容 */
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
/* 高度 */
|
||||
height: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
/* 最小高度 */
|
||||
minHeight: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
/* 只读 */
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 上传文件大小限制(MB)
|
||||
fileSize: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
/* 类型(base64格式、url格式) */
|
||||
type: {
|
||||
type: String,
|
||||
default: "url",
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
uploadUrl: process.env.VUE_APP_BASE_API + "/resource/oss/upload", // 上传的图片服务器地址
|
||||
headers: {
|
||||
Authorization: "Bearer " + getToken()
|
||||
},
|
||||
Quill: null,
|
||||
currentValue: "",
|
||||
options: {
|
||||
theme: "snow",
|
||||
bounds: document.body,
|
||||
debug: "warn",
|
||||
modules: {
|
||||
// 工具栏配置
|
||||
toolbar: [
|
||||
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
|
||||
["blockquote", "code-block"], // 引用 代码块
|
||||
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
|
||||
[{ indent: "-1" }, { indent: "+1" }], // 缩进
|
||||
[{ size: ["small", false, "large", "huge"] }], // 字体大小
|
||||
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
|
||||
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
|
||||
[{ align: [] }], // 对齐方式
|
||||
["clean"], // 清除文本格式
|
||||
["link", "image", "video"] // 链接、图片、视频
|
||||
],
|
||||
},
|
||||
placeholder: "请输入内容",
|
||||
readOnly: this.readOnly,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
styles() {
|
||||
let style = {};
|
||||
if (this.minHeight) {
|
||||
style.minHeight = `${this.minHeight}px`;
|
||||
}
|
||||
if (this.height) {
|
||||
style.height = `${this.height}px`;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
if (val !== this.currentValue) {
|
||||
this.currentValue = val === null ? "" : val;
|
||||
if (this.Quill) {
|
||||
this.Quill.pasteHTML(this.currentValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.Quill = null;
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
const editor = this.$refs.editor;
|
||||
this.Quill = new Quill(editor, this.options);
|
||||
// 如果设置了上传地址则自定义图片上传事件
|
||||
if (this.type == 'url') {
|
||||
let toolbar = this.Quill.getModule("toolbar");
|
||||
toolbar.addHandler("image", (value) => {
|
||||
this.uploadType = "image";
|
||||
if (value) {
|
||||
this.$refs.upload.$children[0].$refs.input.click();
|
||||
} else {
|
||||
this.quill.format("image", false);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.Quill.pasteHTML(this.currentValue);
|
||||
this.Quill.on("text-change", (delta, oldDelta, source) => {
|
||||
const html = this.$refs.editor.children[0].innerHTML;
|
||||
const text = this.Quill.getText();
|
||||
const quill = this.Quill;
|
||||
this.currentValue = html;
|
||||
this.$emit("input", html);
|
||||
this.$emit("on-change", { html, text, quill });
|
||||
});
|
||||
this.Quill.on("text-change", (delta, oldDelta, source) => {
|
||||
this.$emit("on-text-change", delta, oldDelta, source);
|
||||
});
|
||||
this.Quill.on("selection-change", (range, oldRange, source) => {
|
||||
this.$emit("on-selection-change", range, oldRange, source);
|
||||
});
|
||||
this.Quill.on("editor-change", (eventName, ...args) => {
|
||||
this.$emit("on-editor-change", eventName, ...args);
|
||||
});
|
||||
},
|
||||
// 上传前校检格式和大小
|
||||
handleBeforeUpload(file) {
|
||||
// 校检文件大小
|
||||
if (this.fileSize) {
|
||||
const isLt = file.size / 1024 / 1024 < this.fileSize;
|
||||
if (!isLt) {
|
||||
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
handleUploadSuccess(res, file) {
|
||||
// 获取富文本组件实例
|
||||
let quill = this.Quill;
|
||||
// 如果上传成功
|
||||
if (res.code == 200) {
|
||||
// 获取光标所在位置
|
||||
let length = quill.getSelection().index;
|
||||
// 插入图片 res.url为服务器返回的图片地址
|
||||
quill.insertEmbed(length, "image", res.data.url);
|
||||
// 调整光标到最后
|
||||
quill.setSelection(length + 1);
|
||||
} else {
|
||||
this.$message.error(res.msg);
|
||||
}
|
||||
},
|
||||
handleUploadError() {
|
||||
this.$message.error("图片插入失败");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.editor, .ql-toolbar {
|
||||
white-space: pre-wrap !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
.quill-img {
|
||||
display: none;
|
||||
}
|
||||
.ql-snow .ql-tooltip[data-mode="link"]::before {
|
||||
content: "请输入链接地址:";
|
||||
}
|
||||
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
||||
border-right: 0px;
|
||||
content: "保存";
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.ql-snow .ql-tooltip[data-mode="video"]::before {
|
||||
content: "请输入视频地址:";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
||||
content: "14px";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
|
||||
content: "10px";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
|
||||
content: "18px";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
|
||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
|
||||
content: "32px";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
||||
content: "文本";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
||||
content: "标题1";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
||||
content: "标题2";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
||||
content: "标题3";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
||||
content: "标题4";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
||||
content: "标题5";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
||||
content: "标题6";
|
||||
}
|
||||
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
||||
content: "标准字体";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
|
||||
content: "衬线字体";
|
||||
}
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
|
||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
|
||||
content: "等宽字体";
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,197 +1,197 @@
|
|||
<template>
|
||||
<div class="upload-file">
|
||||
<el-upload
|
||||
:action="uploadFileUrl"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:file-list="fileList"
|
||||
:limit="limit"
|
||||
:on-error="handleUploadError"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="handleUploadSuccess"
|
||||
:show-file-list="false"
|
||||
:headers="headers"
|
||||
class="upload-file-uploader"
|
||||
ref="upload"
|
||||
>
|
||||
<!-- 上传按钮 -->
|
||||
<el-button size="mini" type="primary">选取文件</el-button>
|
||||
<!-- 上传提示 -->
|
||||
<div class="el-upload__tip" slot="tip" v-if="showTip">
|
||||
请上传
|
||||
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
|
||||
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
|
||||
的文件
|
||||
</div>
|
||||
</el-upload>
|
||||
|
||||
<!-- 文件列表 -->
|
||||
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
|
||||
<li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
|
||||
<el-link :href="file.url" :underline="false" target="_blank">
|
||||
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
|
||||
</el-link>
|
||||
<div class="ele-upload-list__item-content-action">
|
||||
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
|
||||
</div>
|
||||
</li>
|
||||
</transition-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
name: "FileUpload",
|
||||
props: {
|
||||
// 值
|
||||
value: [String, Object, Array],
|
||||
// 数量限制
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
// 大小限制(MB)
|
||||
fileSize: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||
fileType: {
|
||||
type: Array,
|
||||
default: () => ["doc", "xls", "ppt", "txt", "pdf"],
|
||||
},
|
||||
// 是否显示提示
|
||||
isShowTip: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
uploadFileUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传的图片服务器地址
|
||||
headers: {
|
||||
Authorization: "Bearer " + getToken(),
|
||||
},
|
||||
fileList: [],
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
if (val) {
|
||||
let temp = 1;
|
||||
// 首先将值转为数组
|
||||
const list = Array.isArray(val) ? val : this.value.split(',');
|
||||
// 然后将数组转为对象数组
|
||||
this.fileList = list.map(item => {
|
||||
if (typeof item === "string") {
|
||||
item = { name: item, url: item };
|
||||
}
|
||||
item.uid = item.uid || new Date().getTime() + temp++;
|
||||
return item;
|
||||
});
|
||||
} else {
|
||||
this.fileList = [];
|
||||
return [];
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否显示提示
|
||||
showTip() {
|
||||
return this.isShowTip && (this.fileType || this.fileSize);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 上传前校检格式和大小
|
||||
handleBeforeUpload(file) {
|
||||
// 校检文件类型
|
||||
if (this.fileType) {
|
||||
let fileExtension = "";
|
||||
if (file.name.lastIndexOf(".") > -1) {
|
||||
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
|
||||
}
|
||||
const isTypeOk = this.fileType.some((type) => {
|
||||
if (file.type.indexOf(type) > -1) return true;
|
||||
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
|
||||
return false;
|
||||
});
|
||||
if (!isTypeOk) {
|
||||
this.$message.error(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 校检文件大小
|
||||
if (this.fileSize) {
|
||||
const isLt = file.size / 1024 / 1024 < this.fileSize;
|
||||
if (!isLt) {
|
||||
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// 文件个数超出
|
||||
handleExceed() {
|
||||
this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
|
||||
},
|
||||
// 上传失败
|
||||
handleUploadError(err) {
|
||||
this.$message.error("上传失败, 请重试");
|
||||
},
|
||||
// 上传成功回调
|
||||
handleUploadSuccess(res, file) {
|
||||
this.$message.success("上传成功");
|
||||
this.fileList.push({ name: res.data.url, url: res.data.url });
|
||||
this.$emit("input", this.listToString(this.fileList));
|
||||
},
|
||||
// 删除文件
|
||||
handleDelete(index) {
|
||||
this.fileList.splice(index, 1);
|
||||
this.$emit("input", this.listToString(this.fileList));
|
||||
},
|
||||
// 获取文件名称
|
||||
getFileName(name) {
|
||||
if (name.lastIndexOf("/") > -1) {
|
||||
return name.slice(name.lastIndexOf("/") + 1).toLowerCase();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
// 对象转成指定字符串分隔
|
||||
listToString(list, separator) {
|
||||
let strs = "";
|
||||
separator = separator || ",";
|
||||
for (let i in list) {
|
||||
strs += list[i].url + separator;
|
||||
}
|
||||
return strs != '' ? strs.substr(0, strs.length - 1) : '';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.upload-file-uploader {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.upload-file-list .el-upload-list__item {
|
||||
border: 1px solid #e4e7ed;
|
||||
line-height: 2;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.upload-file-list .ele-upload-list__item-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
}
|
||||
.ele-upload-list__item-content-action .el-link {
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="upload-file">
|
||||
<el-upload
|
||||
:action="uploadFileUrl"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:file-list="fileList"
|
||||
:limit="limit"
|
||||
:on-error="handleUploadError"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="handleUploadSuccess"
|
||||
:show-file-list="false"
|
||||
:headers="headers"
|
||||
class="upload-file-uploader"
|
||||
ref="upload"
|
||||
>
|
||||
<!-- 上传按钮 -->
|
||||
<el-button size="mini" type="primary">选取文件</el-button>
|
||||
<!-- 上传提示 -->
|
||||
<div class="el-upload__tip" slot="tip" v-if="showTip">
|
||||
请上传
|
||||
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
|
||||
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
|
||||
的文件
|
||||
</div>
|
||||
</el-upload>
|
||||
|
||||
<!-- 文件列表 -->
|
||||
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
|
||||
<li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
|
||||
<el-link :href="file.url" :underline="false" target="_blank">
|
||||
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
|
||||
</el-link>
|
||||
<div class="ele-upload-list__item-content-action">
|
||||
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
|
||||
</div>
|
||||
</li>
|
||||
</transition-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
name: "FileUpload",
|
||||
props: {
|
||||
// 值
|
||||
value: [String, Object, Array],
|
||||
// 数量限制
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
// 大小限制(MB)
|
||||
fileSize: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||
fileType: {
|
||||
type: Array,
|
||||
default: () => ["doc", "xls", "ppt", "txt", "pdf"],
|
||||
},
|
||||
// 是否显示提示
|
||||
isShowTip: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
uploadFileUrl: process.env.VUE_APP_BASE_API + "/resource/oss/upload", // 上传的图片服务器地址
|
||||
headers: {
|
||||
Authorization: "Bearer " + getToken(),
|
||||
},
|
||||
fileList: [],
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
if (val) {
|
||||
let temp = 1;
|
||||
// 首先将值转为数组
|
||||
const list = Array.isArray(val) ? val : this.value.split(',');
|
||||
// 然后将数组转为对象数组
|
||||
this.fileList = list.map(item => {
|
||||
if (typeof item === "string") {
|
||||
item = { name: item, url: item };
|
||||
}
|
||||
item.uid = item.uid || new Date().getTime() + temp++;
|
||||
return item;
|
||||
});
|
||||
} else {
|
||||
this.fileList = [];
|
||||
return [];
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否显示提示
|
||||
showTip() {
|
||||
return this.isShowTip && (this.fileType || this.fileSize);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 上传前校检格式和大小
|
||||
handleBeforeUpload(file) {
|
||||
// 校检文件类型
|
||||
if (this.fileType) {
|
||||
let fileExtension = "";
|
||||
if (file.name.lastIndexOf(".") > -1) {
|
||||
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
|
||||
}
|
||||
const isTypeOk = this.fileType.some((type) => {
|
||||
if (file.type.indexOf(type) > -1) return true;
|
||||
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
|
||||
return false;
|
||||
});
|
||||
if (!isTypeOk) {
|
||||
this.$message.error(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 校检文件大小
|
||||
if (this.fileSize) {
|
||||
const isLt = file.size / 1024 / 1024 < this.fileSize;
|
||||
if (!isLt) {
|
||||
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// 文件个数超出
|
||||
handleExceed() {
|
||||
this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
|
||||
},
|
||||
// 上传失败
|
||||
handleUploadError(err) {
|
||||
this.$message.error("上传失败, 请重试");
|
||||
},
|
||||
// 上传成功回调
|
||||
handleUploadSuccess(res, file) {
|
||||
this.$message.success("上传成功");
|
||||
this.fileList.push({ name: res.data.fileName, url: res.data.url });
|
||||
this.$emit("input", this.listToString(this.fileList));
|
||||
},
|
||||
// 删除文件
|
||||
handleDelete(index) {
|
||||
this.fileList.splice(index, 1);
|
||||
this.$emit("input", this.listToString(this.fileList));
|
||||
},
|
||||
// 获取文件名称
|
||||
getFileName(name) {
|
||||
if (name.lastIndexOf("/") > -1) {
|
||||
return name.slice(name.lastIndexOf("/") + 1).toLowerCase();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
// 对象转成指定字符串分隔
|
||||
listToString(list, separator) {
|
||||
let strs = "";
|
||||
separator = separator || ",";
|
||||
for (let i in list) {
|
||||
strs += list[i].url + separator;
|
||||
}
|
||||
return strs != "" ? strs.substr(0, strs.length - 1) : "";
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.upload-file-uploader {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.upload-file-list .el-upload-list__item {
|
||||
border: 1px solid #e4e7ed;
|
||||
line-height: 2;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.upload-file-list .ele-upload-list__item-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
}
|
||||
.ele-upload-list__item-content-action .el-link {
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,207 +1,207 @@
|
|||
<template>
|
||||
<div class="component-upload-image">
|
||||
<el-upload
|
||||
:action="uploadImgUrl"
|
||||
list-type="picture-card"
|
||||
:on-success="handleUploadSuccess"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:limit="limit"
|
||||
:on-error="handleUploadError"
|
||||
:on-exceed="handleExceed"
|
||||
name="file"
|
||||
:on-remove="handleRemove"
|
||||
:show-file-list="true"
|
||||
:headers="headers"
|
||||
:file-list="fileList"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:class="{hide: this.fileList.length >= this.limit}"
|
||||
>
|
||||
<i class="el-icon-plus"></i>
|
||||
</el-upload>
|
||||
|
||||
<!-- 上传提示 -->
|
||||
<div class="el-upload__tip" slot="tip" v-if="showTip">
|
||||
请上传
|
||||
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
|
||||
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
|
||||
的文件
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
:visible.sync="dialogVisible"
|
||||
title="预览"
|
||||
width="800"
|
||||
append-to-body
|
||||
>
|
||||
<img
|
||||
:src="dialogImageUrl"
|
||||
style="display: block; max-width: 100%; margin: 0 auto"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: [String, Object, Array],
|
||||
// 图片数量限制
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
// 大小限制(MB)
|
||||
fileSize: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||
fileType: {
|
||||
type: Array,
|
||||
default: () => ["png", "jpg", "jpeg"],
|
||||
},
|
||||
// 是否显示提示
|
||||
isShowTip: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogImageUrl: "",
|
||||
dialogVisible: false,
|
||||
hideUpload: false,
|
||||
uploadImgUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传的图片服务器地址
|
||||
headers: {
|
||||
Authorization: "Bearer " + getToken(),
|
||||
},
|
||||
fileList: []
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
if (val) {
|
||||
// 首先将值转为数组
|
||||
const list = Array.isArray(val) ? val : this.value.split(',');
|
||||
// 然后将数组转为对象数组
|
||||
this.fileList = list.map(item => {
|
||||
if (typeof item === "string") {
|
||||
item = { name: item, url: item };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
} else {
|
||||
this.fileList = [];
|
||||
return [];
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否显示提示
|
||||
showTip() {
|
||||
return this.isShowTip && (this.fileType || this.fileSize);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 删除图片
|
||||
handleRemove(file, fileList) {
|
||||
const findex = this.fileList.map(f => f.name).indexOf(file.name);
|
||||
if(findex > -1) {
|
||||
this.fileList.splice(findex, 1);
|
||||
this.$emit("input", this.listToString(this.fileList));
|
||||
}
|
||||
},
|
||||
// 上传成功回调
|
||||
handleUploadSuccess(res) {
|
||||
this.fileList.push({ name: res.data.url, url: res.data.url });
|
||||
this.$emit("input", this.listToString(this.fileList));
|
||||
this.loading.close();
|
||||
},
|
||||
// 上传前loading加载
|
||||
handleBeforeUpload(file) {
|
||||
let isImg = false;
|
||||
if (this.fileType.length) {
|
||||
let fileExtension = "";
|
||||
if (file.name.lastIndexOf(".") > -1) {
|
||||
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
|
||||
}
|
||||
isImg = this.fileType.some(type => {
|
||||
if (file.type.indexOf(type) > -1) return true;
|
||||
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
isImg = file.type.indexOf("image") > -1;
|
||||
}
|
||||
|
||||
if (!isImg) {
|
||||
this.$message.error(
|
||||
`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (this.fileSize) {
|
||||
const isLt = file.size / 1024 / 1024 < this.fileSize;
|
||||
if (!isLt) {
|
||||
this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.loading = this.$loading({
|
||||
lock: true,
|
||||
text: "上传中",
|
||||
background: "rgba(0, 0, 0, 0.7)",
|
||||
});
|
||||
},
|
||||
// 文件个数超出
|
||||
handleExceed() {
|
||||
this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
|
||||
},
|
||||
// 上传失败
|
||||
handleUploadError() {
|
||||
this.$message({
|
||||
type: "error",
|
||||
message: "上传失败",
|
||||
});
|
||||
this.loading.close();
|
||||
},
|
||||
// 预览
|
||||
handlePictureCardPreview(file) {
|
||||
this.dialogImageUrl = file.url;
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
// 对象转成指定字符串分隔
|
||||
listToString(list, separator) {
|
||||
let strs = "";
|
||||
separator = separator || ",";
|
||||
for (let i in list) {
|
||||
strs += list[i].url + separator;
|
||||
}
|
||||
return strs != '' ? strs.substr(0, strs.length - 1) : '';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
// .el-upload--picture-card 控制加号部分
|
||||
::v-deep.hide .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
// 去掉动画效果
|
||||
::v-deep .el-list-enter-active,
|
||||
::v-deep .el-list-leave-active {
|
||||
transition: all 0s;
|
||||
}
|
||||
|
||||
::v-deep .el-list-enter, .el-list-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateY(0);
|
||||
}
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div class="component-upload-image">
|
||||
<el-upload
|
||||
:action="uploadImgUrl"
|
||||
list-type="picture-card"
|
||||
:on-success="handleUploadSuccess"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:limit="limit"
|
||||
:on-error="handleUploadError"
|
||||
:on-exceed="handleExceed"
|
||||
name="file"
|
||||
:on-remove="handleRemove"
|
||||
:show-file-list="true"
|
||||
:headers="headers"
|
||||
:file-list="fileList"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:class="{hide: this.fileList.length >= this.limit}"
|
||||
>
|
||||
<i class="el-icon-plus"></i>
|
||||
</el-upload>
|
||||
|
||||
<!-- 上传提示 -->
|
||||
<div class="el-upload__tip" slot="tip" v-if="showTip">
|
||||
请上传
|
||||
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
|
||||
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
|
||||
的文件
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
:visible.sync="dialogVisible"
|
||||
title="预览"
|
||||
width="800"
|
||||
append-to-body
|
||||
>
|
||||
<img
|
||||
:src="dialogImageUrl"
|
||||
style="display: block; max-width: 100%; margin: 0 auto"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: [String, Object, Array],
|
||||
// 图片数量限制
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
// 大小限制(MB)
|
||||
fileSize: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||
fileType: {
|
||||
type: Array,
|
||||
default: () => ["png", "jpg", "jpeg"],
|
||||
},
|
||||
// 是否显示提示
|
||||
isShowTip: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogImageUrl: "",
|
||||
dialogVisible: false,
|
||||
hideUpload: false,
|
||||
uploadImgUrl: process.env.VUE_APP_BASE_API + "/resource/oss/upload", // 上传的图片服务器地址
|
||||
headers: {
|
||||
Authorization: "Bearer " + getToken(),
|
||||
},
|
||||
fileList: []
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
if (val) {
|
||||
// 首先将值转为数组
|
||||
const list = Array.isArray(val) ? val : this.value.split(',');
|
||||
// 然后将数组转为对象数组
|
||||
this.fileList = list.map(item => {
|
||||
if (typeof item === "string") {
|
||||
item = { name: item, url: item };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
} else {
|
||||
this.fileList = [];
|
||||
return [];
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否显示提示
|
||||
showTip() {
|
||||
return this.isShowTip && (this.fileType || this.fileSize);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 删除图片
|
||||
handleRemove(file, fileList) {
|
||||
const findex = this.fileList.map(f => f.name).indexOf(file.name);
|
||||
if(findex > -1) {
|
||||
this.fileList.splice(findex, 1);
|
||||
this.$emit("input", this.listToString(this.fileList));
|
||||
}
|
||||
},
|
||||
// 上传成功回调
|
||||
handleUploadSuccess(res) {
|
||||
this.fileList.push({ name: res.data.fileName, url: res.data.url });
|
||||
this.$emit("input", this.listToString(this.fileList));
|
||||
this.loading.close();
|
||||
},
|
||||
// 上传前loading加载
|
||||
handleBeforeUpload(file) {
|
||||
let isImg = false;
|
||||
if (this.fileType.length) {
|
||||
let fileExtension = "";
|
||||
if (file.name.lastIndexOf(".") > -1) {
|
||||
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
|
||||
}
|
||||
isImg = this.fileType.some(type => {
|
||||
if (file.type.indexOf(type) > -1) return true;
|
||||
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
isImg = file.type.indexOf("image") > -1;
|
||||
}
|
||||
|
||||
if (!isImg) {
|
||||
this.$message.error(
|
||||
`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (this.fileSize) {
|
||||
const isLt = file.size / 1024 / 1024 < this.fileSize;
|
||||
if (!isLt) {
|
||||
this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.loading = this.$loading({
|
||||
lock: true,
|
||||
text: "上传中",
|
||||
background: "rgba(0, 0, 0, 0.7)",
|
||||
});
|
||||
},
|
||||
// 文件个数超出
|
||||
handleExceed() {
|
||||
this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
|
||||
},
|
||||
// 上传失败
|
||||
handleUploadError() {
|
||||
this.$message({
|
||||
type: "error",
|
||||
message: "上传失败",
|
||||
});
|
||||
this.loading.close();
|
||||
},
|
||||
// 预览
|
||||
handlePictureCardPreview(file) {
|
||||
this.dialogImageUrl = file.url;
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
// 对象转成指定字符串分隔
|
||||
listToString(list, separator) {
|
||||
let strs = "";
|
||||
separator = separator || ",";
|
||||
for (let i in list) {
|
||||
strs += list[i].url + separator;
|
||||
}
|
||||
return strs != '' ? strs.substr(0, strs.length - 1) : '';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
// .el-upload--picture-card 控制加号部分
|
||||
::v-deep.hide .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
// 去掉动画效果
|
||||
::v-deep .el-list-enter-active,
|
||||
::v-deep .el-list-leave-active {
|
||||
transition: all 0s;
|
||||
}
|
||||
|
||||
::v-deep .el-list-enter, .el-list-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateY(0);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,86 +1,87 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
import Element from 'element-ui'
|
||||
import './assets/styles/element-variables.scss'
|
||||
|
||||
import '@/assets/styles/index.scss' // global css
|
||||
import '@/assets/styles/ruoyi.scss' // ruoyi css
|
||||
import App from './App'
|
||||
import store from './store'
|
||||
import router from './router'
|
||||
import directive from './directive' // directive
|
||||
import plugins from './plugins' // plugins
|
||||
import { download } from '@/utils/request'
|
||||
|
||||
import './assets/icons' // icon
|
||||
import './permission' // permission control
|
||||
import { getDicts } from "@/api/system/dict/data";
|
||||
import { getConfigKey } from "@/api/system/config";
|
||||
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
|
||||
// 分页组件
|
||||
import Pagination from "@/components/Pagination";
|
||||
// 自定义表格工具组件
|
||||
import RightToolbar from "@/components/RightToolbar"
|
||||
// 富文本组件
|
||||
import Editor from "@/components/Editor"
|
||||
// 文件上传组件
|
||||
import FileUpload from "@/components/FileUpload"
|
||||
// 图片上传组件
|
||||
import ImageUpload from "@/components/ImageUpload"
|
||||
// 图片预览组件
|
||||
import ImagePreview from "@/components/ImagePreview"
|
||||
// 字典标签组件
|
||||
import DictTag from '@/components/DictTag'
|
||||
// 头部标签组件
|
||||
import VueMeta from 'vue-meta'
|
||||
// 字典数据组件
|
||||
import DictData from '@/components/DictData'
|
||||
|
||||
// 全局方法挂载
|
||||
Vue.prototype.getDicts = getDicts
|
||||
Vue.prototype.getConfigKey = getConfigKey
|
||||
Vue.prototype.parseTime = parseTime
|
||||
Vue.prototype.resetForm = resetForm
|
||||
Vue.prototype.addDateRange = addDateRange
|
||||
Vue.prototype.selectDictLabel = selectDictLabel
|
||||
Vue.prototype.selectDictLabels = selectDictLabels
|
||||
Vue.prototype.download = download
|
||||
Vue.prototype.handleTree = handleTree
|
||||
|
||||
// 全局组件挂载
|
||||
Vue.component('DictTag', DictTag)
|
||||
Vue.component('Pagination', Pagination)
|
||||
Vue.component('RightToolbar', RightToolbar)
|
||||
Vue.component('Editor', Editor)
|
||||
Vue.component('FileUpload', FileUpload)
|
||||
Vue.component('ImageUpload', ImageUpload)
|
||||
Vue.component('ImagePreview', ImagePreview)
|
||||
|
||||
Vue.use(directive)
|
||||
Vue.use(plugins)
|
||||
Vue.use(VueMeta)
|
||||
DictData.install()
|
||||
|
||||
/**
|
||||
* If you don't want to use mock-server
|
||||
* you want to use MockJs for mock api
|
||||
* you can execute: mockXHR()
|
||||
*
|
||||
* Currently MockJs will be used in the production environment,
|
||||
* please remove it before going online! ! !
|
||||
*/
|
||||
|
||||
Vue.use(Element, {
|
||||
size: Cookies.get('size') || 'medium' // set element-ui default size
|
||||
})
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
store,
|
||||
render: h => h(App)
|
||||
})
|
||||
import Vue from 'vue'
|
||||
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
import Element from 'element-ui'
|
||||
import './assets/styles/element-variables.scss'
|
||||
|
||||
import '@/assets/styles/index.scss' // global css
|
||||
import '@/assets/styles/ruoyi.scss' // ruoyi css
|
||||
import App from './App'
|
||||
import store from './store'
|
||||
import router from './router'
|
||||
import directive from './directive' // directive
|
||||
import plugins from './plugins' // plugins
|
||||
import { download } from '@/utils/request'
|
||||
|
||||
import './assets/icons' // icon
|
||||
import './permission' // permission control
|
||||
import { getDicts } from "@/api/system/dict/data";
|
||||
import { getConfigKey, updateConfigByKey } from "@/api/system/config";
|
||||
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
|
||||
// 分页组件
|
||||
import Pagination from "@/components/Pagination";
|
||||
// 自定义表格工具组件
|
||||
import RightToolbar from "@/components/RightToolbar"
|
||||
// 富文本组件
|
||||
import Editor from "@/components/Editor"
|
||||
// 文件上传组件
|
||||
import FileUpload from "@/components/FileUpload"
|
||||
// 图片上传组件
|
||||
import ImageUpload from "@/components/ImageUpload"
|
||||
// 图片预览组件
|
||||
import ImagePreview from "@/components/ImagePreview"
|
||||
// 字典标签组件
|
||||
import DictTag from '@/components/DictTag'
|
||||
// 头部标签组件
|
||||
import VueMeta from 'vue-meta'
|
||||
// 字典数据组件
|
||||
import DictData from '@/components/DictData'
|
||||
|
||||
// 全局方法挂载
|
||||
Vue.prototype.getDicts = getDicts
|
||||
Vue.prototype.getConfigKey = getConfigKey
|
||||
Vue.prototype.updateConfigByKey = updateConfigByKey
|
||||
Vue.prototype.parseTime = parseTime
|
||||
Vue.prototype.resetForm = resetForm
|
||||
Vue.prototype.addDateRange = addDateRange
|
||||
Vue.prototype.selectDictLabel = selectDictLabel
|
||||
Vue.prototype.selectDictLabels = selectDictLabels
|
||||
Vue.prototype.download = download
|
||||
Vue.prototype.handleTree = handleTree
|
||||
|
||||
// 全局组件挂载
|
||||
Vue.component('DictTag', DictTag)
|
||||
Vue.component('Pagination', Pagination)
|
||||
Vue.component('RightToolbar', RightToolbar)
|
||||
Vue.component('Editor', Editor)
|
||||
Vue.component('FileUpload', FileUpload)
|
||||
Vue.component('ImageUpload', ImageUpload)
|
||||
Vue.component('ImagePreview', ImagePreview)
|
||||
|
||||
Vue.use(directive)
|
||||
Vue.use(plugins)
|
||||
Vue.use(VueMeta)
|
||||
DictData.install()
|
||||
|
||||
/**
|
||||
* If you don't want to use mock-server
|
||||
* you want to use MockJs for mock api
|
||||
* you can execute: mockXHR()
|
||||
*
|
||||
* Currently MockJs will be used in the production environment,
|
||||
* please remove it before going online! ! !
|
||||
*/
|
||||
|
||||
Vue.use(Element, {
|
||||
size: Cookies.get('size') || 'medium' // set element-ui default size
|
||||
})
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
store,
|
||||
render: h => h(App)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -134,6 +134,20 @@ export const dynamicRoutes = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/system/oss-config',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
permissions: ['system:oss:list'],
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
component: () => import('@/views/system/oss/config'),
|
||||
name: 'OssConfig',
|
||||
meta: { title: '配置管理', activeMenu: '/system/oss' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/tool/gen-edit',
|
||||
component: Layout,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,400 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="配置key" prop="configKey">
|
||||
<el-select v-model="queryParams.configKey" placeholder="请选择配置key" clearable size="small">
|
||||
<el-option
|
||||
v-for="configKey in configKeyOptions"
|
||||
:key="configKey.configKey"
|
||||
:label="configKey.label"
|
||||
:value="configKey.configKey"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="桶名称" prop="bucketName">
|
||||
<el-input
|
||||
v-model="queryParams.bucketName"
|
||||
placeholder="请输入桶名称"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
|
||||
<el-option
|
||||
v-for="dict in dict.type.sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['system:oss:add']"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="el-icon-edit"
|
||||
size="mini"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
v-hasPermi="['system:oss:edit']"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['system:oss:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="ossConfigList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="主建" align="center" prop="ossConfigId" v-if="false"/>
|
||||
<el-table-column label="配置key" align="center" prop="configKey" />
|
||||
<el-table-column label="访问站点" align="center" prop="endpoint" width="200" />
|
||||
<el-table-column label="桶名称" align="center" prop="bucketName" />
|
||||
<el-table-column label="前缀" align="center" prop="prefix" />
|
||||
<el-table-column label="域" align="center" prop="region" />
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.status"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
@change="handleStatusChange(scope.row)"
|
||||
></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:oss:edit']"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:oss:remove']"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改对象存储配置对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
||||
<el-form-item label="配置key" prop="configKey">
|
||||
<el-select v-model="form.configKey" placeholder="请选择配置key">
|
||||
<el-option
|
||||
v-for="configKey in configKeyOptions"
|
||||
:key="configKey.configKey"
|
||||
:label="configKey.label"
|
||||
:value="configKey.configKey"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="访问站点" prop="endpoint">
|
||||
<el-input v-model="form.endpoint" placeholder="请输入访问站点" />
|
||||
</el-form-item>
|
||||
<el-form-item label="accessKey" prop="accessKey">
|
||||
<el-input v-model="form.accessKey" placeholder="请输入accessKey" />
|
||||
</el-form-item>
|
||||
<el-form-item label="secretKey" prop="secretKey">
|
||||
<el-input v-model="form.secretKey" placeholder="请输入秘钥" show-password />
|
||||
</el-form-item>
|
||||
<el-form-item label="桶名称" prop="bucketName">
|
||||
<el-input v-model="form.bucketName" placeholder="请输入桶名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="前缀" prop="prefix">
|
||||
<el-input v-model="form.prefix" placeholder="请输入前缀" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否HTTPS">
|
||||
<el-radio-group v-model="form.isHttps">
|
||||
<el-radio
|
||||
v-for="dict in dict.type.sys_yes_no"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="域" prop="region">
|
||||
<el-input v-model="form.region" placeholder="请输入域" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {
|
||||
listOssConfig,
|
||||
getOssConfig,
|
||||
delOssConfig,
|
||||
addOssConfig,
|
||||
updateOssConfig,
|
||||
changeOssConfigStatus
|
||||
} from "@/api/system/ossConfig";
|
||||
|
||||
export default {
|
||||
name: "OssConfig",
|
||||
dicts: ['sys_yes_no', 'sys_normal_disable'],
|
||||
data() {
|
||||
return {
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 对象存储配置表格数据
|
||||
ossConfigList: [],
|
||||
// configKeyOptions
|
||||
configKeyOptions: [],
|
||||
configKeyDatas: [
|
||||
{ configKey: "minio", label: "Minio" },
|
||||
{ configKey: "qiniu", label: "七牛云" },
|
||||
{ configKey: "aliyun", label: "阿里云" },
|
||||
{ configKey: "qcloud", label: "腾讯云" },
|
||||
],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 是否https字典
|
||||
isHttpsOptions: [],
|
||||
// 状态(0正常 1停用)字典
|
||||
statusOptions: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
configKey: undefined,
|
||||
bucketName: undefined,
|
||||
status: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
configKey: [
|
||||
{ required: true, message: "configKey不能为空", trigger: "blur" },
|
||||
],
|
||||
accessKey: [
|
||||
{ required: true, message: "accessKey不能为空", trigger: "blur" },
|
||||
{
|
||||
min: 2,
|
||||
max: 200,
|
||||
message: "accessKey长度必须介于 2 和 100 之间",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
secretKey: [
|
||||
{ required: true, message: "secretKey不能为空", trigger: "blur" },
|
||||
{
|
||||
min: 2,
|
||||
max: 100,
|
||||
message: "secretKey长度必须介于 2 和 100 之间",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
bucketName: [
|
||||
{ required: true, message: "bucketName不能为空", trigger: "blur" },
|
||||
{
|
||||
min: 2,
|
||||
max: 100,
|
||||
message: "bucketName长度必须介于 2 和 100 之间",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
endpoint: [
|
||||
{ required: true, message: "endpoint不能为空", trigger: "blur" },
|
||||
{
|
||||
min: 2,
|
||||
max: 100,
|
||||
message: "endpoint名称长度必须介于 2 和 100 之间",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.configKeyOptions = this.configKeyDatas;
|
||||
},
|
||||
methods: {
|
||||
/** 查询对象存储配置列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listOssConfig(this.queryParams).then((response) => {
|
||||
this.ossConfigList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
ossConfigId: undefined,
|
||||
configKey: undefined,
|
||||
accessKey: undefined,
|
||||
secretKey: undefined,
|
||||
bucketName: undefined,
|
||||
prefix: undefined,
|
||||
endpoint: undefined,
|
||||
isHttps: "N",
|
||||
region: undefined,
|
||||
status: "1",
|
||||
remark: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.ossConfigId)
|
||||
this.single = selection.length!==1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加对象存储配置";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
const ossConfigId = row.ossConfigId || this.ids;
|
||||
getOssConfig(ossConfigId).then((response) => {
|
||||
this.loading = false;
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改对象存储配置";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.buttonLoading = true;
|
||||
if (this.form.ossConfigId != null) {
|
||||
updateOssConfig(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
addOssConfig(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const ossConfigIds = row.ossConfigId || this.ids;
|
||||
this.$modal.confirm('是否确认删除对象存储配置编号为"' + ossConfigIds + '"的数据项?').then(() => {
|
||||
this.loading = true;
|
||||
return delOssConfig(ossConfigIds);
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 对象存储配置状态修改
|
||||
handleStatusChange(row) {
|
||||
let text = row.status === "0" ? "启用" : "停用";
|
||||
this.$modal.confirm('确认要"' + text + '""' + row.configKey + '"配置吗?').then(() => {
|
||||
return changeOssConfigStatus(row.ossConfigId, row.status, row.configKey);
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess(text + "成功");
|
||||
}).catch(() => {
|
||||
row.status = row.status === "0" ? "1" : "0";
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,357 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="文件名" prop="fileName">
|
||||
<el-input
|
||||
v-model="queryParams.fileName"
|
||||
placeholder="请输入文件名"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="原名" prop="originalName">
|
||||
<el-input
|
||||
v-model="queryParams.originalName"
|
||||
placeholder="请输入原名"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件后缀" prop="fileSuffix">
|
||||
<el-input
|
||||
v-model="queryParams.fileSuffix"
|
||||
placeholder="请输入文件后缀"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker
|
||||
v-model="daterangeCreateTime"
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="上传人" prop="createBy">
|
||||
<el-input
|
||||
v-model="queryParams.createBy"
|
||||
placeholder="请输入上传人"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="服务商" prop="service">
|
||||
<el-input
|
||||
v-model="queryParams.service"
|
||||
placeholder="请输入服务商"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleFile"
|
||||
v-hasPermi="['system:oss:upload']"
|
||||
>上传文件</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleImage"
|
||||
v-hasPermi="['system:oss:upload']"
|
||||
>上传图片</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['system:oss:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
:type="previewListResource ? 'danger' : 'warning'"
|
||||
plain
|
||||
size="mini"
|
||||
@click="handlePreviewListResource(!previewListResource)"
|
||||
v-hasPermi="['system:oss:edit']"
|
||||
>预览开关 : {{previewListResource ? "禁用" : "启用"}}</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="info"
|
||||
plain
|
||||
icon="el-icon-s-operation"
|
||||
size="mini"
|
||||
@click="handleOssConfig"
|
||||
v-hasPermi="['system:oss:list']"
|
||||
>配置管理</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="ossList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="对象存储主键" align="center" prop="ossId" v-if="false"/>
|
||||
<el-table-column label="文件名" align="center" prop="fileName" />
|
||||
<el-table-column label="原名" align="center" prop="originalName" />
|
||||
<el-table-column label="文件后缀" align="center" prop="fileSuffix" />
|
||||
<el-table-column label="文件展示" align="center" prop="url">
|
||||
<template slot-scope="scope">
|
||||
<el-image
|
||||
v-if="previewListResource && checkFileSuffix(scope.row.fileSuffix)"
|
||||
style="width: 100px; height: 100px;"
|
||||
:src="scope.row.url"
|
||||
:preview-src-list="[scope.row.url]"/>
|
||||
<span v-text="scope.row.url"
|
||||
v-if="!checkFileSuffix(scope.row.fileSuffix) || !previewListResource"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传人" align="center" prop="createBy" />
|
||||
<el-table-column label="服务商" align="center" prop="service" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleDownload(scope.row)"
|
||||
v-hasPermi="['system:oss:download']"
|
||||
>下载</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:oss:remove']"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改OSS对象存储对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="文件名">
|
||||
<fileUpload v-model="form.file" v-if="type === 0"/>
|
||||
<imageUpload v-model="form.file" v-if="type === 1"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listOss, delOss } from "@/api/system/oss";
|
||||
|
||||
export default {
|
||||
name: "Oss",
|
||||
data() {
|
||||
return {
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// OSS对象存储表格数据
|
||||
ossList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 弹出层标题
|
||||
type: 0,
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 预览列表图片
|
||||
previewListResource: true,
|
||||
// 创建时间时间范围
|
||||
daterangeCreateTime: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
fileName: undefined,
|
||||
originalName: undefined,
|
||||
fileSuffix: undefined,
|
||||
url: undefined,
|
||||
createTime: undefined,
|
||||
createBy: undefined,
|
||||
service: undefined
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
file: [
|
||||
{ required: true, message: "文件不能为空", trigger: "blur" }
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询OSS对象存储列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
this.queryParams.params = {};
|
||||
if (null != this.daterangeCreateTime && '' != this.daterangeCreateTime) {
|
||||
this.queryParams.params["beginCreateTime"] = this.daterangeCreateTime[0];
|
||||
this.queryParams.params["endCreateTime"] = this.daterangeCreateTime[1];
|
||||
}
|
||||
this.getConfigKey("sys.oss.previewListResource").then(response => {
|
||||
this.previewListResource = response.msg === undefined ? true : response.msg === 'true';
|
||||
});
|
||||
listOss(this.queryParams).then(response => {
|
||||
this.ossList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
checkFileSuffix(fileSuffix) {
|
||||
let arr = ["png", "jpg", "jpeg"];
|
||||
return arr.some(type => {
|
||||
return fileSuffix.indexOf(type) > -1;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
file: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.daterangeCreateTime = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.ossId)
|
||||
this.single = selection.length!==1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 任务日志列表查询 */
|
||||
handleOssConfig() {
|
||||
this.$router.push({ path: '/system/oss-config/index'})
|
||||
},
|
||||
/** 文件按钮操作 */
|
||||
handleFile() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "上传文件";
|
||||
this.type = 0;
|
||||
},
|
||||
/** 图片按钮操作 */
|
||||
handleImage() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "上传图片";
|
||||
this.type = 1;
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.open = false;
|
||||
this.getList();
|
||||
},
|
||||
/** 下载按钮操作 */
|
||||
handleDownload(row) {
|
||||
this.$download.oss(row.ossId)
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const ossIds = row.ossId || this.ids;
|
||||
this.$modal.confirm('是否确认删除OSS对象存储编号为"' + ossIds + '"的数据项?').then(() => {
|
||||
this.loading = true;
|
||||
return delOss(ossIds);
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 预览列表图片状态修改
|
||||
handlePreviewListResource(previewListResource) {
|
||||
let text = previewListResource ? "启用" : "停用";
|
||||
this.$modal.confirm('确认要"' + text + '""预览列表图片"配置吗?').then(() => {
|
||||
return this.updateConfigByKey("sys.oss.previewListResource", previewListResource);
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess(text + "成功");
|
||||
}).catch(() => {
|
||||
this.previewListResource = previewListResource !== true;
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -77,7 +77,8 @@ export default {
|
|||
autoCrop: true, // 是否默认生成截图框
|
||||
autoCropWidth: 200, // 默认生成截图框宽度
|
||||
autoCropHeight: 200, // 默认生成截图框高度
|
||||
fixedBox: true // 固定截图框大小 不允许改变
|
||||
fixedBox: true, // 固定截图框大小 不允许改变
|
||||
filename: ''
|
||||
},
|
||||
previews: {}
|
||||
};
|
||||
|
|
@ -116,6 +117,7 @@ export default {
|
|||
reader.readAsDataURL(file);
|
||||
reader.onload = () => {
|
||||
this.options.img = reader.result;
|
||||
this.options.filename = file.name;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
|
@ -123,7 +125,8 @@ export default {
|
|||
uploadImg() {
|
||||
this.$refs.cropper.getCropBlob(data => {
|
||||
let formData = new FormData();
|
||||
formData.append("avatarfile", data);
|
||||
console.log(this.options.filename)
|
||||
formData.append("avatarfile", data, this.options.filename);
|
||||
uploadAvatar(formData).then(response => {
|
||||
this.open = false;
|
||||
this.options.img = response.data.imgUrl;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,6 @@ knife4j:
|
|||
- name: 代码生成
|
||||
uri: ${knife4j.cloud.gatewayUri}
|
||||
location: /code/v2/api-docs
|
||||
- name: 文件服务
|
||||
- name: 资源服务
|
||||
uri: ${knife4j.cloud.gatewayUri}
|
||||
location: /file/v2/api-docs
|
||||
location: /resource/v2/api-docs
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ create table sys_menu (
|
|||
insert into sys_menu values('1', '系统管理', '0', '1', 'system', null, '', 1, 0, 'M', '0', '0', '', 'system', 'admin', sysdate(), '', null, '系统管理目录');
|
||||
insert into sys_menu values('2', '系统监控', '0', '2', 'monitor', null, '', 1, 0, 'M', '0', '0', '', 'monitor', 'admin', sysdate(), '', null, '系统监控目录');
|
||||
insert into sys_menu values('3', '系统工具', '0', '3', 'tool', null, '', 1, 0, 'M', '0', '0', '', 'tool', 'admin', sysdate(), '', null, '系统工具目录');
|
||||
insert into sys_menu values('4', '若依官网', '0', '4', 'http://ruoyi.vip', null, '', 0, 0, 'M', '0', '0', '', 'guide', 'admin', sysdate(), '', null, '若依官网地址');
|
||||
insert into sys_menu values('4', 'PLUS官网', '0', '4', 'https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus', null, '', 0, 0, 'M', '0', '0', '', 'guide', 'admin', sysdate(), '', null, '若依官网地址');
|
||||
-- 二级菜单
|
||||
insert into sys_menu values('100', '用户管理', '1', '1', 'user', 'system/user/index', '', 1, 0, 'C', '0', '0', 'system:user:list', 'user', 'admin', sysdate(), '', null, '用户管理菜单');
|
||||
insert into sys_menu values('101', '角色管理', '1', '2', 'role', 'system/role/index', '', 1, 0, 'C', '0', '0', 'system:role:list', 'peoples', 'admin', sysdate(), '', null, '角色管理菜单');
|
||||
|
|
@ -181,6 +181,8 @@ insert into sys_menu values('113', 'Admin控制台', '2', '5', 'http://loc
|
|||
insert into sys_menu values('114', '表单构建', '3', '1', 'build', 'tool/build/index', '', 1, 0, 'C', '0', '0', 'tool:build:list', 'build', 'admin', sysdate(), '', null, '表单构建菜单');
|
||||
insert into sys_menu values('115', '代码生成', '3', '2', 'gen', 'tool/gen/index', '', 1, 0, 'C', '0', '0', 'tool:gen:list', 'code', 'admin', sysdate(), '', null, '代码生成菜单');
|
||||
insert into sys_menu values('116', '系统接口', '3', '3', 'http://localhost:18000/doc.html', '', '', 0, 0, 'C', '0', '0', 'tool:swagger:list', 'swagger', 'admin', sysdate(), '', null, '系统接口菜单');
|
||||
-- oss菜单
|
||||
insert into sys_menu values('118', '文件管理', '1', '10', 'oss', 'system/oss/index', '', 1, 0, 'C', '0', '0', 'system:oss:list', 'upload', 'admin', sysdate(), '', null, '文件管理菜单');
|
||||
-- 三级菜单
|
||||
insert into sys_menu values('500', '操作日志', '108', '1', 'operlog', 'system/operlog/index', '', 1, 0, 'C', '0', '0', 'system:operlog:list', 'form', 'admin', sysdate(), '', null, '操作日志菜单');
|
||||
insert into sys_menu values('501', '登录日志', '108', '2', 'logininfor', 'system/logininfor/index', '', 1, 0, 'C', '0', '0', 'system:logininfor:list', 'logininfor', 'admin', sysdate(), '', null, '登录日志菜单');
|
||||
|
|
@ -250,6 +252,13 @@ insert into sys_menu values('1057', '生成删除', '115', '3', '#', '', '', 1,
|
|||
insert into sys_menu values('1058', '导入代码', '115', '2', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:import', '#', 'admin', sysdate(), '', null, '');
|
||||
insert into sys_menu values('1059', '预览代码', '115', '4', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:preview', '#', 'admin', sysdate(), '', null, '');
|
||||
insert into sys_menu values('1060', '生成代码', '115', '5', '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:code', '#', 'admin', sysdate(), '', null, '');
|
||||
-- oss相关按钮
|
||||
insert into sys_menu values('1600', '文件查询', '118', '1', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:query', '#', 'admin', sysdate(), '', null, '');
|
||||
insert into sys_menu values('1601', '文件上传', '118', '2', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:upload', '#', 'admin', sysdate(), '', null, '');
|
||||
insert into sys_menu values('1602', '文件下载', '118', '3', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:download', '#', 'admin', sysdate(), '', null, '');
|
||||
insert into sys_menu values('1603', '文件删除', '118', '4', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:remove', '#', 'admin', sysdate(), '', null, '');
|
||||
insert into sys_menu values('1604', '配置添加', '118', '5', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:add', '#', 'admin', sysdate(), '', null, '');
|
||||
insert into sys_menu values('1605', '配置编辑', '118', '6', '#', '', '', 1, 0, 'F', '0', '0', 'system:oss:edit', '#', 'admin', sysdate(), '', null, '');
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
|
|
@ -533,7 +542,7 @@ insert into sys_config values(1, '主框架页-默认皮肤样式名称', 's
|
|||
insert into sys_config values(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', sysdate(), '', null, '初始化密码 123456' );
|
||||
insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null, '深色主题theme-dark,浅色主题theme-light' );
|
||||
insert into sys_config values(4, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能(true开启,false关闭)');
|
||||
|
||||
insert into sys_config values(11, 'OSS预览列表资源开关', 'sys.oss.previewListResource', 'true', 'Y', 'admin', sysdate(), '', null, 'true:开启, false:关闭');
|
||||
|
||||
-- ----------------------------
|
||||
-- 14、系统访问记录
|
||||
|
|
@ -573,6 +582,52 @@ create table sys_notice (
|
|||
insert into sys_notice values('1', '温馨提醒:2018-07-01 若依新版本发布啦', '2', '新版本内容', '0', 'admin', sysdate(), '', null, '管理员');
|
||||
insert into sys_notice values('2', '维护通知:2018-07-01 若依系统凌晨维护', '1', '维护内容', '0', 'admin', sysdate(), '', null, '管理员');
|
||||
|
||||
-- ----------------------------
|
||||
-- OSS对象存储表
|
||||
-- ----------------------------
|
||||
drop table if exists sys_oss;
|
||||
create table sys_oss (
|
||||
oss_id bigint(20) not null auto_increment comment '对象存储主键',
|
||||
file_name varchar(255) not null default '' comment '文件名',
|
||||
original_name varchar(255) not null default '' comment '原名',
|
||||
file_suffix varchar(10) not null default '' comment '文件后缀名',
|
||||
url varchar(500) not null comment 'URL地址',
|
||||
create_time datetime default null comment '创建时间',
|
||||
create_by varchar(64) default '' comment '上传人',
|
||||
update_time datetime default null comment '更新时间',
|
||||
update_by varchar(64) default '' comment '更新人',
|
||||
service varchar(10) not null default 'minio' comment '服务商',
|
||||
primary key (oss_id)
|
||||
) engine=innodb comment ='OSS对象存储表';
|
||||
|
||||
-- ----------------------------
|
||||
-- OSS对象存储动态配置表
|
||||
-- ----------------------------
|
||||
drop table if exists sys_oss_config;
|
||||
create table sys_oss_config (
|
||||
oss_config_id bigint(20) not null auto_increment comment '主建',
|
||||
config_key varchar(255) not null default '' comment '配置key',
|
||||
access_key varchar(255) default '' comment 'accessKey',
|
||||
secret_key varchar(255) default '' comment '秘钥',
|
||||
bucket_name varchar(255) default '' comment '桶名称',
|
||||
prefix varchar(255) default '' comment '前缀',
|
||||
endpoint varchar(255) default '' comment '访问站点',
|
||||
is_https char(1) default 'N' comment '是否https(Y=是,N=否)',
|
||||
region varchar(255) default '' comment '域',
|
||||
status char(1) default '1' comment '状态(0=正常,1=停用)',
|
||||
ext1 varchar(255) default '' comment '扩展字段',
|
||||
create_by varchar(64) default '' comment '创建者',
|
||||
create_time datetime default null comment '创建时间',
|
||||
update_by varchar(64) default '' comment '更新者',
|
||||
update_time datetime default null comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (oss_config_id)
|
||||
) engine=innodb comment='对象存储配置表';
|
||||
|
||||
insert into sys_oss_config values (1, 'minio', 'ruoyi', 'ruoyi123', 'ruoyi', '', 'http://localhost:9000', 'N', '', '0', '', 'admin', sysdate(), 'admin', sysdate(), NULL);
|
||||
insert into sys_oss_config values (2, 'qiniu', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'http://XXX.XXXX.com', 'N', 'z0', '1', '', 'admin', sysdate(), 'admin', sysdate(), NULL);
|
||||
insert into sys_oss_config values (3, 'aliyun', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'http://oss-cn-beijing.aliyuncs.com', 'N', '', '1', '', 'admin', sysdate(), 'admin', sysdate(), NULL);
|
||||
insert into sys_oss_config values (4, 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1250000000', '', 'http://cos.ap-beijing.myqcloud.com', 'N', 'ap-beijing', '1', '', 'admin', sysdate(), 'admin', sysdate(), NULL);
|
||||
|
||||
-- ----------------------------
|
||||
-- 18、代码生成业务表
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ insert into config_info(id, data_id, group_id, content, md5, gmt_create, gmt_mod
|
|||
(6, 'ruoyi-system.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:20:18', '2022-01-09 15:22:03', NULL, '0:0:0:0:0:0:0:1', '', 'dev', '系统模块', NULL, NULL, 'yaml', NULL),
|
||||
(7, 'ruoyi-gen.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:20:18', '2022-01-09 15:21:51', NULL, '0:0:0:0:0:0:0:1', '', 'dev', '代码生成', NULL, NULL, 'yaml', NULL),
|
||||
(8, 'ruoyi-job.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:20:18', '2022-01-09 15:21:36', NULL, '0:0:0:0:0:0:0:1', '', 'dev', '定时任务', NULL, NULL, 'yaml', NULL),
|
||||
(9, 'ruoyi-file.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:20:35', '2022-01-09 15:21:21', NULL, '0:0:0:0:0:0:0:1', '', 'dev', '文件服务', NULL, NULL, 'yaml', NULL),
|
||||
(9, 'ruoyi-resource.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:20:35', '2022-01-09 15:21:21', NULL, '0:0:0:0:0:0:0:1', '', 'dev', '文件服务', NULL, NULL, 'yaml', NULL),
|
||||
(10, 'sentinel-ruoyi-gateway.json', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:21:02', '2022-01-09 15:21:02', NULL, '0:0:0:0:0:0:0:1', '', 'dev', '限流策略', NULL, NULL, 'json', NULL),
|
||||
(11, 'ruoyi-xxl-job-admin.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:21:02', '2022-01-09 15:21:02', NULL, '0:0:0:0:0:0:0:1', '', 'dev', '定时任务控制台', NULL, NULL, 'yaml', NULL),
|
||||
(12, 'seata-server.properties', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:21:02', '2022-01-09 15:21:02', NULL, '0:0:0:0:0:0:0:1', '', 'dev', 'seata配置文件', NULL, NULL, 'properties', NULL),
|
||||
|
|
@ -53,7 +53,7 @@ insert into config_info(id, data_id, group_id, content, md5, gmt_create, gmt_mod
|
|||
(106, 'ruoyi-system.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:23:00', '2022-01-09 15:23:00', NULL, '0:0:0:0:0:0:0:1', '', 'prod', '系统模块', NULL, NULL, 'yaml', NULL),
|
||||
(107, 'ruoyi-gen.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:23:00', '2022-01-09 15:23:00', NULL, '0:0:0:0:0:0:0:1', '', 'prod', '代码生成', NULL, NULL, 'yaml', NULL),
|
||||
(108, 'ruoyi-job.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:23:00', '2022-01-09 15:23:00', NULL, '0:0:0:0:0:0:0:1', '', 'prod', '定时任务', NULL, NULL, 'yaml', NULL),
|
||||
(109, 'ruoyi-file.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:23:00', '2022-01-09 15:23:00', NULL, '0:0:0:0:0:0:0:1', '', 'prod', '文件服务', NULL, NULL, 'yaml', NULL),
|
||||
(109, 'ruoyi-resource.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:23:00', '2022-01-09 15:23:00', NULL, '0:0:0:0:0:0:0:1', '', 'prod', '文件服务', NULL, NULL, 'yaml', NULL),
|
||||
(110, 'sentinel-ruoyi-gateway.json', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:23:00', '2022-01-09 15:23:00', NULL, '0:0:0:0:0:0:0:1', '', 'prod', '限流策略', NULL, NULL, 'json', NULL),
|
||||
(111, 'ruoyi-xxl-job-admin.yml', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:21:02', '2022-01-09 15:21:02', NULL, '0:0:0:0:0:0:0:1', '', 'prod', '定时任务控制台', NULL, NULL, 'yaml', NULL),
|
||||
(112, 'seata-server.properties', 'DEFAULT_GROUP', '# 将项目路径:config/下对应文件中内容复制到此处', '2944a25cb97926efcaa43b3ad7a64cf0', '2022-01-09 15:21:02', '2022-01-09 15:21:02', NULL, '0:0:0:0:0:0:0:1', '', 'prod', 'seata配置文件', NULL, NULL, 'properties', NULL);
|
||||
|
|
|
|||
Loading…
Reference in New Issue