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