mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-31 09:30:05 +08:00
commit
e923bc661d
2
pom.xml
2
pom.xml
@ -25,7 +25,7 @@
|
||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>1.6.0-snapshot</revision>
|
||||
<revision>1.6.1-snapshot</revision>
|
||||
<!-- Maven 相关 -->
|
||||
<java.version>1.8</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
|
File diff suppressed because one or more lines are too long
@ -14,7 +14,7 @@
|
||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>1.6.0-snapshot</revision>
|
||||
<revision>1.6.1-snapshot</revision>
|
||||
<!-- 统一依赖管理 -->
|
||||
<spring.boot.version>2.5.10</spring.boot.version>
|
||||
<!-- Web 相关 -->
|
||||
@ -28,7 +28,7 @@
|
||||
<dynamic-datasource.version>3.5.0</dynamic-datasource.version>
|
||||
<redisson.version>3.16.6</redisson.version>
|
||||
<!-- Config 配置中心相关 -->
|
||||
<apollo.version>1.7.0</apollo.version>
|
||||
<apollo.version>1.9.2</apollo.version>
|
||||
<!-- Job 定时任务相关 -->
|
||||
<!-- 服务保障相关 -->
|
||||
<lock4j.version>2.2.0</lock4j.version>
|
||||
@ -52,11 +52,12 @@
|
||||
<velocity.version>2.2</velocity.version>
|
||||
<screw.version>1.0.5</screw.version>
|
||||
<guava.version>30.1.1-jre</guava.version>
|
||||
<guice.version>5.1.0</guice.version>
|
||||
<transmittable-thread-local.version>2.12.2</transmittable-thread-local.version>
|
||||
<commons-net.version>3.8.0</commons-net.version>
|
||||
<jsch.version>0.1.55</jsch.version>
|
||||
<!-- 三方云服务相关 -->
|
||||
<s3.version>2.17.147</s3.version>
|
||||
<minio.version>8.2.2</minio.version>
|
||||
<aliyun-java-sdk-core.version>4.5.25</aliyun-java-sdk-core.version>
|
||||
<aliyun-java-sdk-dysmsapi.version>2.1.0</aliyun-java-sdk-dysmsapi.version>
|
||||
<yunpian-java-sdk.version>1.2.7</yunpian-java-sdk.version>
|
||||
@ -490,6 +491,12 @@
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>${guice.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>transmittable-thread-local</artifactId> <!-- 解决 ThreadLocal 父子线程的传值问题 -->
|
||||
@ -514,9 +521,9 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>s3</artifactId>
|
||||
<version>${s3.version}</version>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>${minio.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SMS SDK begin -->
|
||||
|
@ -63,8 +63,8 @@
|
||||
|
||||
<!-- 三方云服务相关 -->
|
||||
<dependency>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>s3</artifactId>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test 测试相关 -->
|
||||
|
@ -20,15 +20,17 @@ public interface FileClient {
|
||||
* @param content 文件流
|
||||
* @param path 相对路径
|
||||
* @return 完整路径,即 HTTP 访问地址
|
||||
* @throws Exception 上传文件时,抛出 Exception 异常
|
||||
*/
|
||||
String upload(byte[] content, String path);
|
||||
String upload(byte[] content, String path) throws Exception;
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
* @param path 相对路径
|
||||
* @throws Exception 删除文件时,抛出 Exception 异常
|
||||
*/
|
||||
void delete(String path);
|
||||
void delete(String path) throws Exception;
|
||||
|
||||
/**
|
||||
* 获得文件的内容
|
||||
@ -36,6 +38,6 @@ public interface FileClient {
|
||||
* @param path 相对路径
|
||||
* @return 文件的内容
|
||||
*/
|
||||
byte[] getContent(String path);
|
||||
byte[] getContent(String path) throws Exception;
|
||||
|
||||
}
|
||||
|
@ -1,19 +1,14 @@
|
||||
package cn.iocoder.yudao.framework.file.core.client.s3;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.iocoder.yudao.framework.file.core.client.AbstractFileClient;
|
||||
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
|
||||
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
|
||||
import software.amazon.awssdk.core.sync.RequestBody;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
|
||||
import io.minio.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_QINIU;
|
||||
import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_ALIYUN;
|
||||
|
||||
/**
|
||||
* 基于 S3 协议的文件客户端,实现 MinIO、阿里云、腾讯云、七牛云、华为云等云服务
|
||||
@ -24,7 +19,7 @@ import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.
|
||||
*/
|
||||
public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
|
||||
|
||||
private S3Client client;
|
||||
private MinioClient client;
|
||||
|
||||
public S3FileClient(Long id, S3FileClientConfig config) {
|
||||
super(id, config);
|
||||
@ -34,34 +29,27 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
|
||||
protected void doInit() {
|
||||
// 补全 domain
|
||||
if (StrUtil.isEmpty(config.getDomain())) {
|
||||
config.setDomain(createDomain());
|
||||
config.setDomain(buildDomain());
|
||||
}
|
||||
// 初始化客户端
|
||||
client = S3Client.builder()
|
||||
.serviceConfiguration(sb -> sb.pathStyleAccessEnabled(false) // 关闭路径风格
|
||||
.chunkedEncodingEnabled(false)) // 禁用 chunk
|
||||
.endpointOverride(createURI()) // 上传地址
|
||||
.region(Region.of(config.getRegion())) // Region
|
||||
.credentialsProvider(StaticCredentialsProvider.create( // 认证密钥
|
||||
AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret())))
|
||||
.overrideConfiguration(cb -> cb.addExecutionInterceptor(new S3ModifyPathInterceptor(config.getBucket())))
|
||||
client = MinioClient.builder()
|
||||
.endpoint(buildEndpointURL()) // Endpoint URL
|
||||
.region(buildRegion()) // Region
|
||||
.credentials(config.getAccessKey(), config.getAccessSecret()) // 认证密钥
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于 endpoint 构建调用云服务的 URI 地址
|
||||
* 基于 endpoint 构建调用云服务的 URL 地址
|
||||
*
|
||||
* @return URI 地址
|
||||
*/
|
||||
private URI createURI() {
|
||||
String uri;
|
||||
// 如果是七牛,无需拼接 bucket
|
||||
if (config.getEndpoint().contains(ENDPOINT_QINIU)) {
|
||||
uri = StrUtil.format("https://{}", config.getEndpoint());
|
||||
} else {
|
||||
uri = StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint());
|
||||
private String buildEndpointURL() {
|
||||
// 如果已经是 http 或者 https,则不进行拼接.主要适配 MinIO
|
||||
if (HttpUtil.isHttp(config.getEndpoint()) || HttpUtil.isHttps(config.getEndpoint())) {
|
||||
return config.getEndpoint();
|
||||
}
|
||||
return URI.create(uri);
|
||||
return StrUtil.format("https://{}", config.getEndpoint());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,35 +57,56 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
|
||||
*
|
||||
* @return Domain 地址
|
||||
*/
|
||||
private String createDomain() {
|
||||
private String buildDomain() {
|
||||
// 如果已经是 http 或者 https,则不进行拼接.主要适配 MinIO
|
||||
if (HttpUtil.isHttp(config.getEndpoint()) || HttpUtil.isHttps(config.getEndpoint())) {
|
||||
return StrUtil.format("{}/{}", config.getEndpoint(), config.getBucket());
|
||||
}
|
||||
// 阿里云、腾讯云、华为云都适合。七牛云比较特殊,必须有自定义域名
|
||||
return StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint());
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于 bucket 构建 region 地区
|
||||
*
|
||||
* @return region 地区
|
||||
*/
|
||||
private String buildRegion() {
|
||||
// 阿里云必须有 region,否则会报错
|
||||
if (config.getEndpoint().contains(ENDPOINT_ALIYUN)) {
|
||||
return StrUtil.subBefore(config.getEndpoint(), '.', false)
|
||||
.replaceAll("-internal", ""); // 去除内网 Endpoint 的后缀
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(byte[] content, String path) {
|
||||
public String upload(byte[] content, String path) throws Exception {
|
||||
// 执行上传
|
||||
PutObjectRequest.Builder request = PutObjectRequest.builder()
|
||||
client.putObject(PutObjectArgs.builder()
|
||||
.bucket(config.getBucket()) // bucket 必须传递
|
||||
.key(path); // 相对路径作为 key
|
||||
client.putObject(request.build(), RequestBody.fromBytes(content));
|
||||
.object(path) // 相对路径作为 key
|
||||
.stream(new ByteArrayInputStream(content), content.length, -1) // 文件内容
|
||||
.build());
|
||||
// 拼接返回路径
|
||||
return config.getDomain() + "/" + path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String path) {
|
||||
DeleteObjectRequest.Builder request = DeleteObjectRequest.builder()
|
||||
public void delete(String path) throws Exception {
|
||||
client.removeObject(RemoveObjectArgs.builder()
|
||||
.bucket(config.getBucket()) // bucket 必须传递
|
||||
.key(path); // 相对路径作为 key
|
||||
client.deleteObject(request.build());
|
||||
.object(path) // 相对路径作为 key
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getContent(String path) {
|
||||
GetObjectRequest.Builder request = GetObjectRequest.builder()
|
||||
public byte[] getContent(String path) throws Exception {
|
||||
GetObjectResponse response = client.getObject(GetObjectArgs.builder()
|
||||
.bucket(config.getBucket()) // bucket 必须传递
|
||||
.key(path); // 相对路径作为 key
|
||||
return client.getObjectAsBytes(request.build()).asByteArray();
|
||||
.object(path) // 相对路径作为 key
|
||||
.build());
|
||||
return IoUtil.readBytes(response);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,37 +18,28 @@ import javax.validation.constraints.NotNull;
|
||||
public class S3FileClientConfig implements FileClientConfig {
|
||||
|
||||
public static final String ENDPOINT_QINIU = "qiniucs.com";
|
||||
public static final String ENDPOINT_ALIYUN = "aliyuncs.com";
|
||||
|
||||
/**
|
||||
* 节点地址
|
||||
* 1. MinIO:
|
||||
* 1. MinIO:https://www.iocoder.cn/Spring-Boot/MinIO 。例如说,http://127.0.0.1:9000
|
||||
* 2. 阿里云:https://help.aliyun.com/document_detail/31837.html
|
||||
* 3. 腾讯云:
|
||||
* 3. 腾讯云:https://cloud.tencent.com/document/product/436/6224
|
||||
* 4. 七牛云:https://developer.qiniu.com/kodo/4088/s3-access-domainname
|
||||
* 5. 华为云:
|
||||
* 5. 华为云:https://developer.huaweicloud.com/endpoint?OBS
|
||||
*/
|
||||
@NotNull(message = "endpoint 不能为空")
|
||||
private String endpoint;
|
||||
/**
|
||||
* 自定义域名
|
||||
* 1. MinIO:
|
||||
* 1. MinIO:通过 Nginx 配置
|
||||
* 2. 阿里云:https://help.aliyun.com/document_detail/31836.html
|
||||
* 3. 腾讯云:https://cloud.tencent.com/document/product/436/11142
|
||||
* 4. 七牛云:https://developer.qiniu.com/kodo/8556/set-the-custom-source-domain-name
|
||||
* 5. 华为云:
|
||||
* 5. 华为云:https://support.huaweicloud.com/usermanual-obs/obs_03_0032.html
|
||||
*/
|
||||
@URL(message = "domain 必须是 URL 格式")
|
||||
private String domain;
|
||||
/**
|
||||
* 区域
|
||||
* 1. MinIO:
|
||||
* 2. 阿里云:https://help.aliyun.com/document_detail/31837.html
|
||||
* 3. 腾讯云:
|
||||
* 4. 七牛云:https://developer.qiniu.com/kodo/4088/s3-access-domainname
|
||||
* 5. 华为云:
|
||||
*/
|
||||
@NotNull(message = "region 不能为空")
|
||||
private String region;
|
||||
/**
|
||||
* 存储 Bucket
|
||||
*/
|
||||
@ -57,11 +48,11 @@ public class S3FileClientConfig implements FileClientConfig {
|
||||
|
||||
/**
|
||||
* 访问 Key
|
||||
* 1. MinIO:
|
||||
* 2. 阿里云:
|
||||
* 1. MinIO:https://www.iocoder.cn/Spring-Boot/MinIO
|
||||
* 2. 阿里云:https://ram.console.aliyun.com/manage/ak
|
||||
* 3. 腾讯云:https://console.cloud.tencent.com/cam/capi
|
||||
* 4. 七牛云:https://portal.qiniu.com/user/key
|
||||
* 5. 华为云:
|
||||
* 5. 华为云:https://support.huaweicloud.com/qs-obs/obs_qs_0005.html
|
||||
*/
|
||||
@NotNull(message = "accessKey 不能为空")
|
||||
private String accessKey;
|
||||
|
@ -1,36 +0,0 @@
|
||||
package cn.iocoder.yudao.framework.file.core.client.s3;
|
||||
|
||||
import software.amazon.awssdk.core.interceptor.Context;
|
||||
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
|
||||
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
|
||||
import software.amazon.awssdk.http.SdkHttpRequest;
|
||||
|
||||
/**
|
||||
* S3 修改路径的拦截器,移除多余的 Bucket 前缀。
|
||||
* 如果不使用该拦截器,希望上传的路径是 /tudou.jpg 时,会被添加成 /bucket/tudou.jpg
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class S3ModifyPathInterceptor implements ExecutionInterceptor {
|
||||
|
||||
private final String bucket;
|
||||
|
||||
public S3ModifyPathInterceptor(String bucket) {
|
||||
this.bucket = "/" + bucket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) {
|
||||
SdkHttpRequest request = context.httpRequest();
|
||||
SdkHttpRequest.Builder rb = SdkHttpRequest.builder().protocol(request.protocol()).host(request.host()).port(request.port())
|
||||
.method(request.method()).headers(request.headers()).rawQueryParameters(request.rawQueryParameters());
|
||||
// 移除 path 前的 bucket 路径
|
||||
if (request.encodedPath().startsWith(bucket)) {
|
||||
rb.encodedPath(request.encodedPath().substring(bucket.length()));
|
||||
} else {
|
||||
rb.encodedPath(request.encodedPath());
|
||||
}
|
||||
return rb.build();
|
||||
}
|
||||
|
||||
}
|
@ -3,11 +3,13 @@ package cn.iocoder.yudao.framework.file.core.client.ftp;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.extra.ftp.FtpMode;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class FtpFileClientTest {
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void test() {
|
||||
// 创建客户端
|
||||
FtpFileClientConfig config = new FtpFileClientConfig();
|
||||
|
@ -2,11 +2,13 @@ package cn.iocoder.yudao.framework.file.core.client.local;
|
||||
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class LocalFileClientTest {
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void test() {
|
||||
// 创建客户端
|
||||
LocalFileClientConfig config = new LocalFileClientConfig();
|
||||
|
@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.file.core.client.s3;
|
||||
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -11,9 +10,25 @@ import javax.validation.Validation;
|
||||
|
||||
public class S3FileClientTest {
|
||||
|
||||
@Test
|
||||
@Disabled // MinIO,如果要集成测试,可以注释本行
|
||||
public void testMinIO() throws Exception {
|
||||
S3FileClientConfig config = new S3FileClientConfig();
|
||||
// 配置成你自己的
|
||||
config.setAccessKey("admin");
|
||||
config.setAccessSecret("password");
|
||||
config.setBucket("yudaoyuanma");
|
||||
config.setDomain(null);
|
||||
// 默认 9000 endpoint
|
||||
config.setEndpoint("http://127.0.0.1:9000");
|
||||
|
||||
// 执行上传
|
||||
testExecuteUpload(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // 阿里云 OSS,如果要集成测试,可以注释本行
|
||||
public void testAliyun() {
|
||||
public void testAliyun() throws Exception {
|
||||
S3FileClientConfig config = new S3FileClientConfig();
|
||||
// 配置成你自己的
|
||||
config.setAccessKey(System.getenv("ALIYUN_ACCESS_KEY"));
|
||||
@ -29,7 +44,7 @@ public class S3FileClientTest {
|
||||
|
||||
@Test
|
||||
@Disabled // 腾讯云 COS,如果要集成测试,可以注释本行
|
||||
public void testQCloud() {
|
||||
public void testQCloud() throws Exception {
|
||||
S3FileClientConfig config = new S3FileClientConfig();
|
||||
// 配置成你自己的
|
||||
config.setAccessKey(System.getenv("QCLOUD_ACCESS_KEY"));
|
||||
@ -38,7 +53,6 @@ public class S3FileClientTest {
|
||||
config.setDomain(null); // 如果有自定义域名,则可以设置。http://tengxun-oss.iocoder.cn
|
||||
// 默认上海的 endpoint
|
||||
config.setEndpoint("cos.ap-shanghai.myqcloud.com");
|
||||
config.setRegion("ap-shanghai");
|
||||
|
||||
// 执行上传
|
||||
testExecuteUpload(config);
|
||||
@ -46,7 +60,7 @@ public class S3FileClientTest {
|
||||
|
||||
@Test
|
||||
@Disabled // 七牛云存储,如果要集成测试,可以注释本行
|
||||
public void testQiniu() {
|
||||
public void testQiniu() throws Exception {
|
||||
S3FileClientConfig config = new S3FileClientConfig();
|
||||
// 配置成你自己的
|
||||
// config.setAccessKey(System.getenv("QINIU_ACCESS_KEY"));
|
||||
@ -62,11 +76,24 @@ public class S3FileClientTest {
|
||||
testExecuteUpload(config);
|
||||
}
|
||||
|
||||
private void testExecuteUpload(S3FileClientConfig config) {
|
||||
// 补全配置
|
||||
if (config.getRegion() == null) {
|
||||
config.setRegion(StrUtil.subBefore(config.getEndpoint(), '.', false));
|
||||
}
|
||||
@Test
|
||||
@Disabled // 华为云存储,如果要集成测试,可以注释本行
|
||||
public void testHuaweiCloud() throws Exception {
|
||||
S3FileClientConfig config = new S3FileClientConfig();
|
||||
// 配置成你自己的
|
||||
// config.setAccessKey(System.getenv("HUAWEI_CLOUD_ACCESS_KEY"));
|
||||
// config.setAccessSecret(System.getenv("HUAWEI_CLOUD_SECRET_KEY"));
|
||||
config.setBucket("yudao");
|
||||
config.setDomain(null); // 如果有自定义域名,则可以设置。
|
||||
// 默认上海的 endpoint
|
||||
config.setEndpoint("obs.cn-east-3.myhuaweicloud.com");
|
||||
|
||||
// 执行上传
|
||||
testExecuteUpload(config);
|
||||
}
|
||||
|
||||
private void testExecuteUpload(S3FileClientConfig config) throws Exception {
|
||||
// 校验配置
|
||||
ValidationUtils.validate(Validation.buildDefaultValidatorFactory().getValidator(), config);
|
||||
// 创建 Client
|
||||
S3FileClient client = new S3FileClient(0L, config);
|
||||
@ -77,9 +104,9 @@ public class S3FileClientTest {
|
||||
String fullPath = client.upload(content, path);
|
||||
System.out.println("访问地址:" + fullPath);
|
||||
// 读取文件
|
||||
if (false) {
|
||||
if (true) {
|
||||
byte[] bytes = client.getContent(path);
|
||||
System.out.println("文件内容:" + bytes);
|
||||
System.out.println("文件内容:" + bytes.length);
|
||||
}
|
||||
// 删除文件
|
||||
if (false) {
|
||||
|
@ -2,11 +2,13 @@ package cn.iocoder.yudao.framework.file.core.client.sftp;
|
||||
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SftpFileClientTest {
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void test() {
|
||||
// 创建客户端
|
||||
SftpFileClientConfig config = new SftpFileClientConfig();
|
||||
|
@ -22,7 +22,6 @@ public interface BpmMessageService {
|
||||
*/
|
||||
void sendMessageWhenProcessInstanceApprove(@Valid BpmMessageSendWhenProcessInstanceApproveReqDTO reqDTO);
|
||||
|
||||
|
||||
/**
|
||||
* 发送流程实例被不通过的消息
|
||||
*
|
||||
|
@ -5,7 +5,6 @@ import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
|
||||
import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRule;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
|
||||
@ -69,11 +68,13 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
|
||||
public BpmUserTaskActivityBehavior(UserTask userTask) {
|
||||
super(userTask);
|
||||
}
|
||||
|
||||
public void setScripts(List<BpmTaskAssignScript> scripts) {
|
||||
this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据
|
||||
protected void handleAssignments(TaskService taskService, String assignee, String owner, List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager, DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) {
|
||||
// 第一步,获得任务的规则
|
||||
BpmTaskAssignRuleDO rule = getTaskRule(task);
|
||||
@ -98,7 +99,6 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
|
||||
return taskRules.get(0);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Set<Long> calculateTaskCandidateUsers(TaskEntity task, BpmTaskAssignRuleDO rule) {
|
||||
Set<Long> assigneeUserIds = null;
|
||||
if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), rule.getType())) {
|
||||
|
@ -15,7 +15,6 @@ import java.util.Set;
|
||||
@Component
|
||||
public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript {
|
||||
|
||||
|
||||
@Override
|
||||
@DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据
|
||||
public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
|
||||
|
@ -15,7 +15,7 @@ public interface FileApi {
|
||||
* @param content 文件内容
|
||||
* @return 文件路径
|
||||
*/
|
||||
default String createFile(byte[] content) {
|
||||
default String createFile(byte[] content) throws Exception {
|
||||
return createFile(IdUtil.fastUUID(), content);
|
||||
}
|
||||
|
||||
@ -26,6 +26,6 @@ public interface FileApi {
|
||||
* @param content 文件内容
|
||||
* @return 文件路径
|
||||
*/
|
||||
String createFile(String path, byte[] content);
|
||||
String createFile(String path, byte[] content) throws Exception;
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package cn.iocoder.yudao.module.infra.api.file;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import cn.iocoder.yudao.module.infra.service.file.FileService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -20,7 +19,7 @@ public class FileApiImpl implements FileApi {
|
||||
private FileService fileService;
|
||||
|
||||
@Override
|
||||
public String createFile(String path, byte[] content) {
|
||||
public String createFile(String path, byte[] content) throws Exception {
|
||||
return fileService.createFile(path, content);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ public class FileConfigController {
|
||||
@GetMapping("/test")
|
||||
@ApiOperation("测试文件配置是否正确")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file-config:query')")
|
||||
public CommonResult<String> testFileConfig(@RequestParam("id") Long id) {
|
||||
public CommonResult<String> testFileConfig(@RequestParam("id") Long id) throws Exception {
|
||||
String url = fileConfigService.testFileConfig(id);
|
||||
return success(url);
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@ -44,7 +43,7 @@ public class FileController {
|
||||
@ApiImplicitParam(name = "path", value = "文件路径", example = "yudaoyuanma.png", dataTypeClass = String.class)
|
||||
})
|
||||
public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam("path") String path) throws IOException {
|
||||
@RequestParam("path") String path) throws Exception {
|
||||
return success(fileService.createFile(path, IoUtil.readBytes(file.getInputStream())));
|
||||
}
|
||||
|
||||
@ -52,7 +51,7 @@ public class FileController {
|
||||
@ApiOperation("删除文件")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('infra:file:delete')")
|
||||
public CommonResult<Boolean> deleteFile(@RequestParam("id") Long id) {
|
||||
public CommonResult<Boolean> deleteFile(@RequestParam("id") Long id) throws Exception {
|
||||
fileService.deleteFile(id);
|
||||
return success(true);
|
||||
}
|
||||
@ -65,7 +64,7 @@ public class FileController {
|
||||
})
|
||||
public void getFileContent(HttpServletResponse response,
|
||||
@PathVariable("configId") Long configId,
|
||||
@PathVariable("path") String path) throws IOException {
|
||||
@PathVariable("path") String path) throws Exception {
|
||||
byte[] content = fileService.getFileContent(configId, path);
|
||||
if (content == null) {
|
||||
log.warn("[getFileContent][configId({}) path({}) 文件不存在]", configId, path);
|
||||
|
@ -82,7 +82,7 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
table.setAuthor(userApi.getUser(userId).getNickname());
|
||||
codegenTableMapper.insert(table);
|
||||
// 构建 CodegenColumnDO 数组,插入到 DB 中
|
||||
List<CodegenColumnDO> columns = codegenBuilder.buildColumns(schemaColumns);
|
||||
List<CodegenColumnDO> columns = codegenBuilder.buildColumns(table.getId(), schemaColumns);
|
||||
codegenColumnMapper.insertBatch(columns);
|
||||
return table.getId();
|
||||
}
|
||||
@ -196,7 +196,7 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
}
|
||||
|
||||
// 插入新增的字段
|
||||
List<CodegenColumnDO> columns = codegenBuilder.buildColumns(schemaColumns);
|
||||
List<CodegenColumnDO> columns = codegenBuilder.buildColumns(tableId, schemaColumns);
|
||||
codegenColumnMapper.insertBatch(columns);
|
||||
// 删除不存在的字段
|
||||
if (CollUtil.isNotEmpty(deleteColumnIds)) {
|
||||
|
@ -133,9 +133,12 @@ public class CodegenBuilder {
|
||||
table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType());
|
||||
}
|
||||
|
||||
public List<CodegenColumnDO> buildColumns(List<SchemaColumnDO> schemaColumns) {
|
||||
public List<CodegenColumnDO> buildColumns(Long tableId, List<SchemaColumnDO> schemaColumns) {
|
||||
List<CodegenColumnDO> columns = CodegenConvert.INSTANCE.convertList(schemaColumns);
|
||||
columns.forEach(this::initColumnDefault);
|
||||
for (CodegenColumnDO column : columns) {
|
||||
column.setTableId(tableId);
|
||||
initColumnDefault(column);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ public interface FileConfigService {
|
||||
* @param id 编号
|
||||
* @return 文件 URL
|
||||
*/
|
||||
String testFileConfig(Long id);
|
||||
String testFileConfig(Long id) throws Exception;
|
||||
|
||||
/**
|
||||
* 获得指定编号的文件客户端
|
||||
|
@ -225,7 +225,7 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String testFileConfig(Long id) {
|
||||
public String testFileConfig(Long id) throws Exception {
|
||||
// 校验存在
|
||||
this.validateFileConfigExists(id);
|
||||
// 上传文件
|
||||
|
@ -26,14 +26,14 @@ public interface FileService {
|
||||
* @param content 文件内容
|
||||
* @return 文件路径
|
||||
*/
|
||||
String createFile(String path, byte[] content);
|
||||
String createFile(String path, byte[] content) throws Exception;
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteFile(Long id);
|
||||
void deleteFile(Long id) throws Exception;
|
||||
|
||||
/**
|
||||
* 获得文件内容
|
||||
@ -42,6 +42,6 @@ public interface FileService {
|
||||
* @param path 文件路径
|
||||
* @return 文件内容
|
||||
*/
|
||||
byte[] getFileContent(Long configId, String path);
|
||||
byte[] getFileContent(Long configId, String path) throws Exception;
|
||||
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public class FileServiceImpl implements FileService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createFile(String path, byte[] content) {
|
||||
public String createFile(String path, byte[] content) throws Exception {
|
||||
// 上传到文件存储器
|
||||
FileClient client = fileConfigService.getMasterFileClient();
|
||||
Assert.notNull(client, "客户端(master) 不能为空");
|
||||
@ -53,7 +53,7 @@ public class FileServiceImpl implements FileService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteFile(Long id) {
|
||||
public void deleteFile(Long id) throws Exception {
|
||||
// 校验存在
|
||||
FileDO file = this.validateFileExists(id);
|
||||
|
||||
@ -75,7 +75,7 @@ public class FileServiceImpl implements FileService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getFileContent(Long configId, String path) {
|
||||
public byte[] getFileContent(Long configId, String path) throws Exception {
|
||||
FileClient client = fileConfigService.getFileClient(configId);
|
||||
Assert.notNull(client, "客户端({}) 不能为空", configId);
|
||||
return client.getContent(path);
|
||||
|
@ -228,7 +228,7 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileConfig() {
|
||||
public void testFileConfig() throws Exception {
|
||||
// mock 数据
|
||||
FileConfigDO dbFileConfig = randomFileConfigDO().setMaster(false);
|
||||
fileConfigMapper.insert(dbFileConfig);// @Sql: 先插入出一条存在的数据
|
||||
|
@ -70,7 +70,7 @@ public class FileServiceTest extends BaseDbUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFile_success() {
|
||||
public void testCreateFile_success() throws Exception {
|
||||
// 准备参数
|
||||
String path = randomString();
|
||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
||||
@ -95,7 +95,7 @@ public class FileServiceTest extends BaseDbUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteFile_success() {
|
||||
public void testDeleteFile_success() throws Exception {
|
||||
// mock 数据
|
||||
FileDO dbFile = randomPojo(FileDO.class, o -> o.setConfigId(10L).setPath("tudou.jpg"));
|
||||
fileMapper.insert(dbFile);// @Sql: 先插入出一条存在的数据
|
||||
@ -123,7 +123,7 @@ public class FileServiceTest extends BaseDbUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFileContent() {
|
||||
public void testGetFileContent() throws Exception {
|
||||
// 准备参数
|
||||
Long configId = 10L;
|
||||
String path = "tudou.jpg";
|
||||
|
@ -16,9 +16,8 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_IS_EMPTY;
|
||||
@ -44,7 +43,7 @@ public class AppUserController {
|
||||
@PutMapping("/update-avatar")
|
||||
@ApiOperation("修改用户头像")
|
||||
@PreAuthenticated
|
||||
public CommonResult<String> updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException {
|
||||
public CommonResult<String> updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws Exception {
|
||||
if (file.isEmpty()) {
|
||||
throw exception(FILE_IS_EMPTY);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public interface MemberUserService {
|
||||
* @param inputStream 头像文件
|
||||
* @return 头像url
|
||||
*/
|
||||
String updateUserAvatar(Long userId, InputStream inputStream);
|
||||
String updateUserAvatar(Long userId, InputStream inputStream) throws Exception;
|
||||
|
||||
/**
|
||||
* 修改手机
|
||||
|
@ -100,7 +100,7 @@ public class MemberUserServiceImpl implements MemberUserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String updateUserAvatar(Long userId, InputStream avatarFile) {
|
||||
public String updateUserAvatar(Long userId, InputStream avatarFile) throws Exception {
|
||||
this.checkUserExists(userId);
|
||||
// 创建文件
|
||||
String avatar = fileApi.createFile(IoUtil.readBytes(avatarFile));
|
||||
|
@ -74,7 +74,7 @@ public class MemberUserServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAvatar_success(){
|
||||
public void testUpdateAvatar_success() throws Exception {
|
||||
// mock 数据
|
||||
MemberUserDO dbUser = randomUserDO();
|
||||
userMapper.insert(dbUser);
|
||||
|
@ -29,7 +29,6 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
@ -99,7 +98,7 @@ public class UserProfileController {
|
||||
|
||||
@PutMapping("/update-avatar")
|
||||
@ApiOperation("上传用户个人头像")
|
||||
public CommonResult<String> updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException {
|
||||
public CommonResult<String> updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws Exception {
|
||||
if (file.isEmpty()) {
|
||||
throw ServiceExceptionUtil.exception(FILE_IS_EMPTY);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.permission;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@ -28,9 +28,7 @@ public interface MenuMapper extends BaseMapperX<MenuDO> {
|
||||
.eqIfPresent(MenuDO::getStatus, reqVO.getStatus()));
|
||||
}
|
||||
|
||||
default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
|
||||
return selectOne(new LambdaQueryWrapper<MenuDO>().select(MenuDO::getId)
|
||||
.gt(MenuDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null;
|
||||
}
|
||||
@Select("SELECT id FROM system_menu WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
MenuDO selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
@ -7,9 +7,8 @@ import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
@ -45,10 +44,7 @@ public interface RoleMapper extends BaseMapperX<RoleDO> {
|
||||
return selectList(new LambdaQueryWrapperX<RoleDO>().inIfPresent(RoleDO::getStatus, statuses));
|
||||
}
|
||||
|
||||
@InterceptorIgnore(tenantLine = "true") // 该方法忽略多租户。原因:该方法被异步 task 调用,此时获取不到租户编号
|
||||
default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
|
||||
return selectOne(new QueryWrapper<RoleDO>().select("id")
|
||||
.gt("update_time", maxUpdateTime).last("LIMIT 1")) != null;
|
||||
}
|
||||
@Select("SELECT id FROM system_role WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
RoleDO selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ public class MenuServiceImpl implements MenuService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadMenuIfUpdate][首次加载全量菜单]");
|
||||
} else { // 判断数据库中是否有更新的菜单
|
||||
if (!menuMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) {
|
||||
if (menuMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadMenuIfUpdate][增量加载全量菜单]");
|
||||
|
@ -116,7 +116,7 @@ public class RoleServiceImpl implements RoleService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadRoleIfUpdate][首次加载全量角色]");
|
||||
} else { // 判断数据库中是否有更新的角色
|
||||
if (!roleMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) {
|
||||
if (roleMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadRoleIfUpdate][增量加载全量角色]");
|
||||
|
@ -64,7 +64,7 @@ public interface AdminUserService {
|
||||
* @param id 用户 id
|
||||
* @param avatarFile 头像文件
|
||||
*/
|
||||
String updateUserAvatar(Long id, InputStream avatarFile);
|
||||
String updateUserAvatar(Long id, InputStream avatarFile) throws Exception;
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
|
@ -63,6 +63,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
private FileApi fileApi;
|
||||
|
||||
@Override
|
||||
|
||||
public Long createUser(UserCreateReqVO reqVO) {
|
||||
// 校验账户配合
|
||||
tenantService.handleTenantInfo(tenant -> {
|
||||
@ -118,7 +119,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String updateUserAvatar(Long id, InputStream avatarFile) {
|
||||
public String updateUserAvatar(Long id, InputStream avatarFile) throws Exception {
|
||||
this.checkUserExists(id);
|
||||
// 存储文件
|
||||
String avatar = fileApi.createFile(IoUtil.readBytes(avatarFile));
|
||||
|
@ -196,7 +196,7 @@ public class UserServiceImplTest extends BaseDbUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateUserAvatar_success() {
|
||||
public void testUpdateUserAvatar_success() throws Exception {
|
||||
// mock 数据
|
||||
AdminUserDO dbUser = randomAdminUserDO();
|
||||
userMapper.insert(dbUser);
|
||||
|
@ -13,3 +13,9 @@ VUE_APP_BASE_API = 'http://127.0.0.1:48080'
|
||||
PUBLIC_PATH = '/admin-ui/'
|
||||
# 二级部署路径
|
||||
VUE_APP_APP_NAME ='/admin-ui/'
|
||||
|
||||
# 多租户的开关
|
||||
VUE_APP_TENANT_ENABLE = true
|
||||
|
||||
# 文档的开关
|
||||
VUE_APP_DOC_ENABLE = true
|
||||
|
@ -13,3 +13,6 @@ VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
||||
|
||||
# 多租户的开关
|
||||
VUE_APP_TENANT_ENABLE = true
|
||||
|
||||
# 文档的开关
|
||||
VUE_APP_DOC_ENABLE = true
|
||||
|
@ -12,3 +12,8 @@ PUBLIC_PATH = 'http://my-pi.com:8888/yudao-admin/'
|
||||
# 二级部署路径
|
||||
VUE_APP_APP_NAME ='yudao-admin'
|
||||
|
||||
# 多租户的开关
|
||||
VUE_APP_TENANT_ENABLE = true
|
||||
|
||||
# 文档的开关
|
||||
VUE_APP_DOC_ENABLE = false
|
||||
|
@ -11,3 +11,9 @@ VUE_APP_BASE_API = 'http://api-dashboard.yudao.iocoder.cn'
|
||||
|
||||
# 静态资源地址
|
||||
PUBLIC_PATH = 'http://static.yudao.iocoder.cn/'
|
||||
|
||||
# 多租户的开关
|
||||
VUE_APP_TENANT_ENABLE = true
|
||||
|
||||
# 文档的开关
|
||||
VUE_APP_DOC_ENABLE = false
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "yudao-ui-admin",
|
||||
"version": "1.6.0-snapshot",
|
||||
"version": "1.6.1-snapshot",
|
||||
"description": "芋道管理系统",
|
||||
"author": "芋道",
|
||||
"license": "MIT",
|
||||
|
25
yudao-ui-admin/src/components/DocAlert/index.vue
Normal file
25
yudao-ui-admin/src/components/DocAlert/index.vue
Normal file
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<el-alert v-if="enable()" :title="'【' + title + '】文档地址:' + url" type="success" show-icon />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getDocEnable} from "@/utils/ruoyi";
|
||||
|
||||
export default {
|
||||
name: "DocAlert",
|
||||
props: {
|
||||
title: String,
|
||||
url: String,
|
||||
},
|
||||
methods: {
|
||||
enable: function () {
|
||||
return getDocEnable();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.el-alert--success.is-light {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
@ -41,10 +41,12 @@ Vue.prototype.handleTree = handleTree
|
||||
|
||||
// 全局组件挂载
|
||||
Vue.component('DictTag', DictTag)
|
||||
Vue.component('DocAlert', DocAlert)
|
||||
Vue.component('Pagination', Pagination)
|
||||
Vue.component('RightToolbar', RightToolbar)
|
||||
// 字典标签组件
|
||||
import DictTag from '@/components/DictTag'
|
||||
import DocAlert from '@/components/DocAlert'
|
||||
// 头部标签插件
|
||||
import VueMeta from 'vue-meta'
|
||||
|
||||
|
@ -175,7 +175,7 @@ export function getNowDateTime(timeStr) {
|
||||
* 获得租户功能是否开启
|
||||
*/
|
||||
export function getTenantEnable() {
|
||||
console.log("enable: " + process.env.VUE_APP_TENANT_ENABLE)
|
||||
// console.log("enable: " + process.env.VUE_APP_TENANT_ENABLE)
|
||||
if (process.env.VUE_APP_TENANT_ENABLE === "true") {
|
||||
return true;
|
||||
}
|
||||
@ -184,3 +184,16 @@ export function getTenantEnable() {
|
||||
}
|
||||
return process.env.VUE_APP_TENANT_ENABLE || true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得文档是否开启
|
||||
*/
|
||||
export function getDocEnable() {
|
||||
if (process.env.VUE_APP_DOC_ENABLE === "true") {
|
||||
return true;
|
||||
}
|
||||
if (process.env.VUE_APP_DOC_ENABLE === "false") {
|
||||
return false;
|
||||
}
|
||||
return process.env.VUE_APP_DOC_ENABLE || false;
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="定义编号" align="center" prop="id" width="400" />
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
@ -24,7 +25,7 @@
|
||||
<el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" width="120" />
|
||||
<el-table-column label="结果" align="center" prop="result">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.result"/>
|
||||
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批意见" align="center" prop="comment" width="200" />
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
|
@ -44,9 +44,9 @@
|
||||
|
||||
<div class="center-board">
|
||||
<div class="action-bar">
|
||||
<el-button icon="el-icon-video-play" type="text" @click="run">
|
||||
运行
|
||||
</el-button>
|
||||
<!-- <el-button icon="el-icon-video-play" type="text" @click="run">-->
|
||||
<!-- 运行-->
|
||||
<!-- </el-button>-->
|
||||
<el-button icon="el-icon-view" type="text" @click="showJson">
|
||||
查看json
|
||||
</el-button>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="代码生成" url="https://doc.iocoder.cn/new-feature/" />
|
||||
<!-- 操作工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="表名称" prop="tableName">
|
||||
|
@ -1,16 +1,11 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<doc-alert title="上传下载" url="https://doc.iocoder.cn/file/" />
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="文件路径" prop="path">
|
||||
<el-input v-model="queryParams.path" placeholder="请输入文件路径" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件类型" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请选择文件类型" clearable size="small">
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</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="结束日期" />
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<doc-alert title="上传下载" url="https://doc.iocoder.cn/file/" />
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="配置名" prop="name">
|
||||
@ -51,7 +51,7 @@
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="240">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['infra:file-config:update']">修改</el-button>
|
||||
@ -109,9 +109,6 @@
|
||||
<el-form-item v-if="form.storage === 20" label="节点地址" prop="config.endpoint">
|
||||
<el-input v-model="form.config.endpoint" placeholder="请输入节点地址" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.storage === 20" label="区域" prop="config.region">
|
||||
<el-input v-model="form.config.region" placeholder="请输入区域" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.storage === 20" label="存储 bucket" prop="config.bucket">
|
||||
<el-input v-model="form.config.bucket" placeholder="请输入 bucket" />
|
||||
</el-form-item>
|
||||
@ -190,7 +187,6 @@ export default {
|
||||
password: [{ required: true, message: "密码不能为空", trigger: "blur" }],
|
||||
mode: [{ required: true, message: "连接模式不能为空", trigger: "change" }],
|
||||
endpoint: [{ required: true, message: "节点地址不能为空", trigger: "blur" }],
|
||||
region: [{ required: true, message: "区域名不能为空", trigger: "blur" }],
|
||||
bucket: [{ required: true, message: "存储 bucket 不能为空", trigger: "blur" }],
|
||||
accessKey: [{ required: true, message: "accessKey 不能为空", trigger: "blur" }],
|
||||
accessSecret: [{ required: true, message: "accessSecret 不能为空", trigger: "blur" }],
|
||||
|
@ -87,7 +87,7 @@ export default {
|
||||
// debugger
|
||||
getTenantIdByName(value).then(res => {
|
||||
const tenantId = res.data;
|
||||
if (tenantId >= 0) {
|
||||
if (tenantId && tenantId >= 0) {
|
||||
// 设置租户
|
||||
Cookies.set("tenantId", tenantId);
|
||||
callback();
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能权限" url="https://doc.iocoder.cn/resource-permission" />
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
|
||||
<el-form-item label="菜单名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入菜单名称" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
|
@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<doc-alert title="功能权限" url="https://doc.iocoder.cn/resource-permission" />
|
||||
<doc-alert title="数据权限" url="https://doc.iocoder.cn/data-permission" />
|
||||
<el-form :model="queryParams" ref="queryForm" v-show="showSearch" :inline="true">
|
||||
<el-form-item label="角色名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入角色名称" clearable size="small" style="width: 240px"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<doc-alert title="SaaS 多租户" url="https://doc.iocoder.cn/saas-tenant/" />
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="租户名" prop="name">
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<doc-alert title="SaaS 多租户" url="https://doc.iocoder.cn/saas-tenant/" />
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="套餐名" prop="name">
|
||||
|
Loading…
Reference in New Issue
Block a user