diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java index 98eb03fe..0c7d0abf 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java @@ -15,6 +15,7 @@ import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.presigner.S3Presigner; import java.net.URI; @@ -31,55 +32,70 @@ import java.net.URI; @Configuration public class FileConfig implements WebMvcConfigurer { - private static final String HTTPS = "https://"; - - private static final String HTTP = "http://"; - private static final String MODE_CLOUD = "cloud"; private static final String MODE_LOCAL = "local"; - @Value("${file.storage.cloud.region}") - private String region; - - @Value("${file.storage.cloud.endpoint}") - private String endpoint; - - @Value("${file.storage.cloud.bucket-name}") - private String bucketName; - - @Value("${file.storage.cloud.access-key}") - private String accessKey; - - @Value("${file.storage.cloud.secret-key}") - private String secretKey; - - @Value("${file.storage.cloud.private-url-expire-seconds}") - private Long privateUrlExpireSeconds; - - @Value("${file.storage.cloud.url-prefix}") - private String urlPrefix; - - @Value("${file.storage.local.upload-path}") - private String uploadPath; - @Value("${file.storage.mode}") private String mode; + @Value("${file.storage.cloud.region}") + private String cloudRegion; + + @Value("${file.storage.cloud.endpoint}") + private String cloudEndpoint; + + @Value("${file.storage.cloud.bucket-name}") + private String cloudBucketName; + + @Value("${file.storage.cloud.access-key}") + private String cloudAccessKey; + + @Value("${file.storage.cloud.secret-key}") + private String cloudSecretKey; + + @Value("${file.storage.cloud.private-url-expire-seconds}") + private Long cloudPrivateUrlExpireSeconds; + + @Value("${file.storage.cloud.public-url-prefix}") + private String cloudPublicUrlPrefix; + + @Value("${file.storage.local.upload-path}") + private String localUploadPath; + + /** - * 初始化 云oss client 配置 - * - * @return + * 初始化 s3 client 配置 */ @Bean @ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_CLOUD) - public S3Client initAmazonS3() { + public S3Client initS3Client() { return S3Client.builder() - .region(Region.AWS_GLOBAL) - .endpointOverride(URI.create((urlPrefix.startsWith(HTTPS) ? HTTPS : HTTP) + endpoint)) + .region(Region.of(cloudRegion)) + .endpointOverride(URI.create(cloudEndpoint)) .credentialsProvider( StaticCredentialsProvider.create( - AwsBasicCredentials.create(accessKey, secretKey))) + AwsBasicCredentials.create(cloudAccessKey, cloudSecretKey))) + .serviceConfiguration(S3Configuration.builder() + .pathStyleAccessEnabled(false) + .chunkedEncodingEnabled(false) + .build()) + .build(); + } + + /** + * 初始化 s3 预签名 + */ + @Bean + @ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_CLOUD) + public S3Presigner initS3Presigner() { + return S3Presigner + .builder() + .region(Region.of(cloudRegion)) + .endpointOverride(URI.create(cloudEndpoint)) + .credentialsProvider( + StaticCredentialsProvider.create( + AwsBasicCredentials.create(cloudAccessKey, cloudSecretKey))) .serviceConfiguration(S3Configuration.builder() .pathStyleAccessEnabled(false) .chunkedEncodingEnabled(false) @@ -102,7 +118,7 @@ public class FileConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { if (MODE_LOCAL.equals(mode)) { - String path = uploadPath.endsWith("/") ? uploadPath : uploadPath + "/"; + String path = localUploadPath.endsWith("/") ? localUploadPath : localUploadPath + "/"; registry.addResourceHandler(FileStorageLocalServiceImpl.UPLOAD_MAPPING + "/**").addResourceLocations("file:" + path); } } diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/constant/DictDataStyleEnum.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/constant/DictDataStyleEnum.java new file mode 100644 index 00000000..deb5d3d7 --- /dev/null +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/constant/DictDataStyleEnum.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.dict.constant; + +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 字典回显样式 枚举 + */ +@Getter +public enum DictDataStyleEnum implements BaseEnum { + + DEFAULT("默认", "default"), + PRIMARY("主要", "primary"), + SUCCESS("成功", "success"), + INFO("信息", "info"), + WARNING("警告", "warning"), + DANGER("危险", "danger"); + + private final String value; + + private final String desc; + + DictDataStyleEnum(String desc, String value) { + this.desc = desc; + this.value = value; + } +} diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java index 61b25b34..208ceef3 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java @@ -40,6 +40,11 @@ public class DictDataEntity { */ private String dataLabel; + /** + * 字典项样式 + */ + private String dataStyle; + /** * 备注 */ diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java index 4b344665..69c90cee 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java @@ -4,6 +4,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.dict.constant.DictDataStyleEnum; + /** * 字典数据表 新建表单 @@ -28,6 +32,10 @@ public class DictDataAddForm { @NotBlank(message = "字典项显示名称 不能为空") private String dataLabel; + @SchemaEnum(value = DictDataStyleEnum.class, desc = "数据样式") + @CheckEnum(message = "样式参数错误", value = DictDataStyleEnum.class) + private String dataStyle; + @Schema(description = "备注") private String remark; diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java index 761799a2..0da395a9 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java @@ -38,6 +38,9 @@ public class DictDataVO implements Serializable { @Schema(description = "字典项显示名称") private String dataLabel; + @Schema(description = "字典项回显") + private String dataStyle; + @Schema(description = "备注") private String remark; diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java index a56617ba..1b53536e 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java @@ -20,22 +20,22 @@ public enum FileFolderTypeEnum implements BaseEnum { /** * 通用 */ - COMMON(1, FileFolderTypeEnum.FOLDER_PUBLIC + "/common/", "通用"), + COMMON(1, FileFolderTypeEnum.FOLDER_PRIVATE + "/common/", "通用"), /** * 公告 */ - NOTICE(2, FileFolderTypeEnum.FOLDER_PUBLIC + "/notice/", "公告"), + NOTICE(2, FileFolderTypeEnum.FOLDER_PRIVATE + "/notice/", "公告"), /** * 帮助中心 */ - HELP_DOC(3, FileFolderTypeEnum.FOLDER_PUBLIC + "/help-doc/", "帮助中心"), + HELP_DOC(3, FileFolderTypeEnum.FOLDER_PRIVATE + "/help-doc/", "帮助中心"), /** * 意见反馈 */ - FEEDBACK(4, FileFolderTypeEnum.FOLDER_PUBLIC + "/feedback/", "意见反馈"), + FEEDBACK(4, FileFolderTypeEnum.FOLDER_PRIVATE + "/feedback/", "意见反馈"), ; diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java index 45664ec8..4015b8c5 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java @@ -71,6 +71,9 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { @Resource private S3Client s3Client; + @Resource + private S3Presigner s3Presigner; + @Resource private FileConfig cloudConfig; @@ -104,7 +107,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { // 根据文件路径获取并设置访问权限 ObjectCannedACL acl = this.getACL(path); PutObjectRequest putObjectRequest = PutObjectRequest.builder() - .bucket(cloudConfig.getBucketName()) + .bucket(cloudConfig.getCloudBucketName()) .key(fileKey) .metadata(userMetadata) .contentLength(file.getSize()) @@ -128,7 +131,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { uploadVO.setFileName(originalFileName); uploadVO.setFileType(fileType); // 根据 访问权限 返回不同的 URL - String url = cloudConfig.getUrlPrefix() + fileKey; + String url = cloudConfig.getCloudPublicUrlPrefix() + fileKey; if (ObjectCannedACL.PRIVATE.equals(acl)) { // 获取临时访问的URL url = this.getFileUrl(fileKey).getData(); @@ -153,11 +156,10 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { if (!fileKey.startsWith(FileFolderTypeEnum.FOLDER_PRIVATE)) { // 不是私有的 都公共读 - return ResponseDTO.ok(cloudConfig.getUrlPrefix() + fileKey); + return ResponseDTO.ok(cloudConfig.getCloudPublicUrlPrefix() + fileKey); } // 如果是私有的,则规定时间内可以访问,超过规定时间,则连接失效 - String fileRedisKey = RedisKeyConst.Support.FILE_PRIVATE_VO + fileKey; FileVO fileVO = redisService.getObject(fileRedisKey, FileVO.class); if (fileVO == null) { @@ -165,15 +167,22 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { if (fileVO == null) { return ResponseDTO.userErrorParam("文件不存在"); } - GetObjectRequest getUrlRequest = GetObjectRequest.builder().bucket(cloudConfig.getBucketName()).key(fileKey).build(); - GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder().signatureDuration(Duration.ofSeconds(cloudConfig.getPrivateUrlExpireSeconds())).getObjectRequest(getUrlRequest).build(); + GetObjectRequest getUrlRequest = GetObjectRequest + .builder() + .bucket(cloudConfig.getCloudBucketName()) + .key(fileKey) + .build(); - S3Presigner presigner = S3Presigner.builder().region(Region.of(cloudConfig.getRegion())).build(); + GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest + .builder() + .signatureDuration(Duration.ofSeconds(cloudConfig.getCloudPrivateUrlExpireSeconds())) + .getObjectRequest(getUrlRequest) + .build(); - PresignedGetObjectRequest presignedGetObjectRequest = presigner.presignGetObject(getObjectPresignRequest); + PresignedGetObjectRequest presignedGetObjectRequest = s3Presigner.presignGetObject(getObjectPresignRequest); String url = presignedGetObjectRequest.url().toString(); fileVO.setFileUrl(url); - redisService.set(fileRedisKey, fileVO, cloudConfig.getPrivateUrlExpireSeconds() - 5); + redisService.set(fileRedisKey, fileVO, cloudConfig.getCloudPrivateUrlExpireSeconds() - 5); } return ResponseDTO.ok(fileVO.getFileUrl()); @@ -187,7 +196,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { public ResponseDTO download(String key) { // 获取文件 meta - HeadObjectRequest objectRequest = HeadObjectRequest.builder().bucket(this.cloudConfig.getBucketName()).key(key).build(); + HeadObjectRequest objectRequest = HeadObjectRequest.builder().bucket(this.cloudConfig.getCloudBucketName()).key(key).build(); HeadObjectResponse headObjectResponse = s3Client.headObject(objectRequest); Map userMetadata = headObjectResponse.metadata(); FileMetadataVO metadataDTO = null; @@ -201,7 +210,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { } //获取oss对象 - GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(cloudConfig.getBucketName()).key(key).build(); + GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(cloudConfig.getCloudBucketName()).key(key).build(); ResponseBytes s3ClientObject = s3Client.getObject(getObjectRequest, ResponseTransformer.toBytes()); // 输入流转换为字节流 @@ -236,7 +245,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { */ @Override public ResponseDTO delete(String fileKey) { - DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder().bucket(cloudConfig.getBucketName()).key(fileKey).build(); + DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder().bucket(cloudConfig.getCloudBucketName()).key(fileKey).build(); s3Client.deleteObject(deleteObjectRequest); return ResponseDTO.ok(); } diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/resources/dev/sa-base.yaml b/smart-admin-api-java17-springboot3/sa-base/src/main/resources/dev/sa-base.yaml index c6cf7410..f3ef1e3b 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/resources/dev/sa-base.yaml +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/resources/dev/sa-base.yaml @@ -103,12 +103,13 @@ file: url-prefix: cloud: region: oss-cn-hangzhou - endpoint: oss-cn-hangzhou.aliyuncs.com + endpoint: https://oss-cn-hangzhou.aliyuncs.com bucket-name: 1024lab-smart-admin access-key: secret-key: - url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ private-url-expire-seconds: 3600 + # 云计算厂商支持公开的文件访问模式;minio默认是不支持的,对于minio用户可以配置为空 + public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/ # open api配置 springdoc: diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/resources/pre/sa-base.yaml b/smart-admin-api-java17-springboot3/sa-base/src/main/resources/pre/sa-base.yaml index ebcdf8f8..c714e7d2 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/resources/pre/sa-base.yaml +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/resources/pre/sa-base.yaml @@ -103,12 +103,13 @@ file: url-prefix: cloud: region: oss-cn-hangzhou - endpoint: oss-cn-hangzhou.aliyuncs.com + endpoint: https://oss-cn-hangzhou.aliyuncs.com bucket-name: 1024lab-smart-admin access-key: secret-key: - url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ private-url-expire-seconds: 3600 + # 云计算厂商支持公开的文件访问模式;minio默认是不支持的,对于minio用户可以配置为空 + public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/ # open api配置 springdoc: diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/resources/prod/sa-base.yaml b/smart-admin-api-java17-springboot3/sa-base/src/main/resources/prod/sa-base.yaml index f50a9669..947329bc 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/resources/prod/sa-base.yaml +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/resources/prod/sa-base.yaml @@ -103,12 +103,13 @@ file: url-prefix: cloud: region: oss-cn-hangzhou - endpoint: oss-cn-hangzhou.aliyuncs.com + endpoint: https://oss-cn-hangzhou.aliyuncs.com bucket-name: 1024lab-smart-admin access-key: secret-key: - url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ private-url-expire-seconds: 3600 + # 云计算厂商支持公开的文件访问模式;minio默认是不支持的,对于minio用户可以配置为空 + public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/ # open api配置 springdoc: diff --git a/smart-admin-api-java17-springboot3/sa-base/src/main/resources/test/sa-base.yaml b/smart-admin-api-java17-springboot3/sa-base/src/main/resources/test/sa-base.yaml index ebcdf8f8..c714e7d2 100644 --- a/smart-admin-api-java17-springboot3/sa-base/src/main/resources/test/sa-base.yaml +++ b/smart-admin-api-java17-springboot3/sa-base/src/main/resources/test/sa-base.yaml @@ -103,12 +103,13 @@ file: url-prefix: cloud: region: oss-cn-hangzhou - endpoint: oss-cn-hangzhou.aliyuncs.com + endpoint: https://oss-cn-hangzhou.aliyuncs.com bucket-name: 1024lab-smart-admin access-key: secret-key: - url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ private-url-expire-seconds: 3600 + # 云计算厂商支持公开的文件访问模式;minio默认是不支持的,对于minio用户可以配置为空 + public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/ # open api配置 springdoc: diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java index 98eb03fe..0c7d0abf 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java @@ -15,6 +15,7 @@ import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.presigner.S3Presigner; import java.net.URI; @@ -31,55 +32,70 @@ import java.net.URI; @Configuration public class FileConfig implements WebMvcConfigurer { - private static final String HTTPS = "https://"; - - private static final String HTTP = "http://"; - private static final String MODE_CLOUD = "cloud"; private static final String MODE_LOCAL = "local"; - @Value("${file.storage.cloud.region}") - private String region; - - @Value("${file.storage.cloud.endpoint}") - private String endpoint; - - @Value("${file.storage.cloud.bucket-name}") - private String bucketName; - - @Value("${file.storage.cloud.access-key}") - private String accessKey; - - @Value("${file.storage.cloud.secret-key}") - private String secretKey; - - @Value("${file.storage.cloud.private-url-expire-seconds}") - private Long privateUrlExpireSeconds; - - @Value("${file.storage.cloud.url-prefix}") - private String urlPrefix; - - @Value("${file.storage.local.upload-path}") - private String uploadPath; - @Value("${file.storage.mode}") private String mode; + @Value("${file.storage.cloud.region}") + private String cloudRegion; + + @Value("${file.storage.cloud.endpoint}") + private String cloudEndpoint; + + @Value("${file.storage.cloud.bucket-name}") + private String cloudBucketName; + + @Value("${file.storage.cloud.access-key}") + private String cloudAccessKey; + + @Value("${file.storage.cloud.secret-key}") + private String cloudSecretKey; + + @Value("${file.storage.cloud.private-url-expire-seconds}") + private Long cloudPrivateUrlExpireSeconds; + + @Value("${file.storage.cloud.public-url-prefix}") + private String cloudPublicUrlPrefix; + + @Value("${file.storage.local.upload-path}") + private String localUploadPath; + + /** - * 初始化 云oss client 配置 - * - * @return + * 初始化 s3 client 配置 */ @Bean @ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_CLOUD) - public S3Client initAmazonS3() { + public S3Client initS3Client() { return S3Client.builder() - .region(Region.AWS_GLOBAL) - .endpointOverride(URI.create((urlPrefix.startsWith(HTTPS) ? HTTPS : HTTP) + endpoint)) + .region(Region.of(cloudRegion)) + .endpointOverride(URI.create(cloudEndpoint)) .credentialsProvider( StaticCredentialsProvider.create( - AwsBasicCredentials.create(accessKey, secretKey))) + AwsBasicCredentials.create(cloudAccessKey, cloudSecretKey))) + .serviceConfiguration(S3Configuration.builder() + .pathStyleAccessEnabled(false) + .chunkedEncodingEnabled(false) + .build()) + .build(); + } + + /** + * 初始化 s3 预签名 + */ + @Bean + @ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_CLOUD) + public S3Presigner initS3Presigner() { + return S3Presigner + .builder() + .region(Region.of(cloudRegion)) + .endpointOverride(URI.create(cloudEndpoint)) + .credentialsProvider( + StaticCredentialsProvider.create( + AwsBasicCredentials.create(cloudAccessKey, cloudSecretKey))) .serviceConfiguration(S3Configuration.builder() .pathStyleAccessEnabled(false) .chunkedEncodingEnabled(false) @@ -102,7 +118,7 @@ public class FileConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { if (MODE_LOCAL.equals(mode)) { - String path = uploadPath.endsWith("/") ? uploadPath : uploadPath + "/"; + String path = localUploadPath.endsWith("/") ? localUploadPath : localUploadPath + "/"; registry.addResourceHandler(FileStorageLocalServiceImpl.UPLOAD_MAPPING + "/**").addResourceLocations("file:" + path); } } diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/constant/DictDataStyleEnum.java b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/constant/DictDataStyleEnum.java new file mode 100644 index 00000000..deb5d3d7 --- /dev/null +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/constant/DictDataStyleEnum.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.dict.constant; + +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 字典回显样式 枚举 + */ +@Getter +public enum DictDataStyleEnum implements BaseEnum { + + DEFAULT("默认", "default"), + PRIMARY("主要", "primary"), + SUCCESS("成功", "success"), + INFO("信息", "info"), + WARNING("警告", "warning"), + DANGER("危险", "danger"); + + private final String value; + + private final String desc; + + DictDataStyleEnum(String desc, String value) { + this.desc = desc; + this.value = value; + } +} diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java index 61b25b34..208ceef3 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java @@ -40,6 +40,11 @@ public class DictDataEntity { */ private String dataLabel; + /** + * 字典项样式 + */ + private String dataStyle; + /** * 备注 */ diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java index faf1ed68..54fc4bd8 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java @@ -2,6 +2,9 @@ package net.lab1024.sa.base.module.support.dict.domain.form; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.dict.constant.DictDataStyleEnum; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -29,6 +32,10 @@ public class DictDataAddForm { @NotBlank(message = "字典项显示名称 不能为空") private String dataLabel; + @SchemaEnum(value = DictDataStyleEnum.class, desc = "数据样式") + @CheckEnum(message = "样式参数错误", value = DictDataStyleEnum.class) + private String dataStyle; + @Schema(description = "备注") private String remark; diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java index 761799a2..0da395a9 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java @@ -38,6 +38,9 @@ public class DictDataVO implements Serializable { @Schema(description = "字典项显示名称") private String dataLabel; + @Schema(description = "字典项回显") + private String dataStyle; + @Schema(description = "备注") private String remark; diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java index a56617ba..1b53536e 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java @@ -20,22 +20,22 @@ public enum FileFolderTypeEnum implements BaseEnum { /** * 通用 */ - COMMON(1, FileFolderTypeEnum.FOLDER_PUBLIC + "/common/", "通用"), + COMMON(1, FileFolderTypeEnum.FOLDER_PRIVATE + "/common/", "通用"), /** * 公告 */ - NOTICE(2, FileFolderTypeEnum.FOLDER_PUBLIC + "/notice/", "公告"), + NOTICE(2, FileFolderTypeEnum.FOLDER_PRIVATE + "/notice/", "公告"), /** * 帮助中心 */ - HELP_DOC(3, FileFolderTypeEnum.FOLDER_PUBLIC + "/help-doc/", "帮助中心"), + HELP_DOC(3, FileFolderTypeEnum.FOLDER_PRIVATE + "/help-doc/", "帮助中心"), /** * 意见反馈 */ - FEEDBACK(4, FileFolderTypeEnum.FOLDER_PUBLIC + "/feedback/", "意见反馈"), + FEEDBACK(4, FileFolderTypeEnum.FOLDER_PRIVATE + "/feedback/", "意见反馈"), ; diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java index 99849a95..8e21f673 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java @@ -24,7 +24,6 @@ import org.springframework.web.multipart.MultipartFile; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.core.sync.ResponseTransformer; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.*; import software.amazon.awssdk.services.s3.presigner.S3Presigner; @@ -72,6 +71,9 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { @Resource private S3Client s3Client; + @Resource + private S3Presigner s3Presigner; + @Resource private FileConfig cloudConfig; @@ -109,7 +111,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { // 根据文件路径获取并设置访问权限 ObjectCannedACL acl = this.getACL(path); PutObjectRequest putObjectRequest = PutObjectRequest.builder() - .bucket(cloudConfig.getBucketName()) + .bucket(cloudConfig.getCloudBucketName()) .key(fileKey) .metadata(userMetadata) .contentLength(file.getSize()) @@ -133,7 +135,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { uploadVO.setFileName(originalFileName); uploadVO.setFileType(fileType); // 根据 访问权限 返回不同的 URL - String url = cloudConfig.getUrlPrefix() + fileKey; + String url = cloudConfig.getCloudPublicUrlPrefix() + fileKey; if (ObjectCannedACL.PRIVATE.equals(acl)) { // 获取临时访问的URL url = this.getFileUrl(fileKey).getData(); @@ -158,11 +160,10 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { if (!fileKey.startsWith(FileFolderTypeEnum.FOLDER_PRIVATE)) { // 不是私有的 都公共读 - return ResponseDTO.ok(cloudConfig.getUrlPrefix() + fileKey); + return ResponseDTO.ok(cloudConfig.getCloudPublicUrlPrefix() + fileKey); } // 如果是私有的,则规定时间内可以访问,超过规定时间,则连接失效 - String fileRedisKey = RedisKeyConst.Support.FILE_PRIVATE_VO + fileKey; FileVO fileVO = redisService.getObject(fileRedisKey, FileVO.class); if (fileVO == null) { @@ -170,15 +171,22 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { if (fileVO == null) { return ResponseDTO.userErrorParam("文件不存在"); } - GetObjectRequest getUrlRequest = GetObjectRequest.builder().bucket(cloudConfig.getBucketName()).key(fileKey).build(); - GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder().signatureDuration(Duration.ofSeconds(cloudConfig.getPrivateUrlExpireSeconds())).getObjectRequest(getUrlRequest).build(); + GetObjectRequest getUrlRequest = GetObjectRequest + .builder() + .bucket(cloudConfig.getCloudBucketName()) + .key(fileKey) + .build(); - S3Presigner presigner = S3Presigner.builder().region(Region.of(cloudConfig.getRegion())).build(); + GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest + .builder() + .signatureDuration(Duration.ofSeconds(cloudConfig.getCloudPrivateUrlExpireSeconds())) + .getObjectRequest(getUrlRequest) + .build(); - PresignedGetObjectRequest presignedGetObjectRequest = presigner.presignGetObject(getObjectPresignRequest); + PresignedGetObjectRequest presignedGetObjectRequest = s3Presigner.presignGetObject(getObjectPresignRequest); String url = presignedGetObjectRequest.url().toString(); fileVO.setFileUrl(url); - redisService.set(fileRedisKey, fileVO, cloudConfig.getPrivateUrlExpireSeconds() - 5); + redisService.set(fileRedisKey, fileVO, cloudConfig.getCloudPrivateUrlExpireSeconds() - 5); } return ResponseDTO.ok(fileVO.getFileUrl()); @@ -192,7 +200,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { public ResponseDTO download(String key) { // 获取文件 meta - HeadObjectRequest objectRequest = HeadObjectRequest.builder().bucket(this.cloudConfig.getBucketName()).key(key).build(); + HeadObjectRequest objectRequest = HeadObjectRequest.builder().bucket(this.cloudConfig.getCloudBucketName()).key(key).build(); HeadObjectResponse headObjectResponse = s3Client.headObject(objectRequest); Map userMetadata = headObjectResponse.metadata(); FileMetadataVO metadataDTO = null; @@ -206,7 +214,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { } //获取oss对象 - GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(cloudConfig.getBucketName()).key(key).build(); + GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(cloudConfig.getCloudBucketName()).key(key).build(); ResponseBytes s3ClientObject = s3Client.getObject(getObjectRequest, ResponseTransformer.toBytes()); // 输入流转换为字节流 @@ -241,7 +249,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService { */ @Override public ResponseDTO delete(String fileKey) { - DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder().bucket(cloudConfig.getBucketName()).key(fileKey).build(); + DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder().bucket(cloudConfig.getCloudBucketName()).key(fileKey).build(); s3Client.deleteObject(deleteObjectRequest); return ResponseDTO.ok(); } diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/resources/dev/sa-base.yaml b/smart-admin-api-java8-springboot2/sa-base/src/main/resources/dev/sa-base.yaml index 4a70d9ea..01d18d82 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/resources/dev/sa-base.yaml +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/resources/dev/sa-base.yaml @@ -102,12 +102,13 @@ file: url-prefix: cloud: region: oss-cn-hangzhou - endpoint: oss-cn-hangzhou.aliyuncs.com + endpoint: https://oss-cn-hangzhou.aliyuncs.com bucket-name: 1024lab-smart-admin access-key: secret-key: - url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ private-url-expire-seconds: 3600 + # 云计算厂商支持公开的文件访问模式;minio默认是不支持的,对于minio用户可以配置为空 + public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/ # open api配置 springdoc: diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/resources/pre/sa-base.yaml b/smart-admin-api-java8-springboot2/sa-base/src/main/resources/pre/sa-base.yaml index 7ba3d1e9..d2c46f78 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/resources/pre/sa-base.yaml +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/resources/pre/sa-base.yaml @@ -102,12 +102,13 @@ file: url-prefix: cloud: region: oss-cn-hangzhou - endpoint: oss-cn-hangzhou.aliyuncs.com + endpoint: https://oss-cn-hangzhou.aliyuncs.com bucket-name: 1024lab-smart-admin access-key: secret-key: - url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ private-url-expire-seconds: 3600 + # 云计算厂商支持公开的文件访问模式;minio默认是不支持的,对于minio用户可以配置为空 + public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/ # open api配置 springdoc: diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/resources/prod/sa-base.yaml b/smart-admin-api-java8-springboot2/sa-base/src/main/resources/prod/sa-base.yaml index bd2ecb97..1ad02f02 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/resources/prod/sa-base.yaml +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/resources/prod/sa-base.yaml @@ -102,12 +102,13 @@ file: url-prefix: cloud: region: oss-cn-hangzhou - endpoint: oss-cn-hangzhou.aliyuncs.com + endpoint: https://oss-cn-hangzhou.aliyuncs.com bucket-name: 1024lab-smart-admin access-key: secret-key: - url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ private-url-expire-seconds: 3600 + # 云计算厂商支持公开的文件访问模式;minio默认是不支持的,对于minio用户可以配置为空 + public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/ # open api配置 springdoc: diff --git a/smart-admin-api-java8-springboot2/sa-base/src/main/resources/test/sa-base.yaml b/smart-admin-api-java8-springboot2/sa-base/src/main/resources/test/sa-base.yaml index 7ba3d1e9..d2c46f78 100644 --- a/smart-admin-api-java8-springboot2/sa-base/src/main/resources/test/sa-base.yaml +++ b/smart-admin-api-java8-springboot2/sa-base/src/main/resources/test/sa-base.yaml @@ -102,12 +102,13 @@ file: url-prefix: cloud: region: oss-cn-hangzhou - endpoint: oss-cn-hangzhou.aliyuncs.com + endpoint: https://oss-cn-hangzhou.aliyuncs.com bucket-name: 1024lab-smart-admin access-key: secret-key: - url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ private-url-expire-seconds: 3600 + # 云计算厂商支持公开的文件访问模式;minio默认是不支持的,对于minio用户可以配置为空 + public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/ # open api配置 springdoc: diff --git a/smart-admin-web-javascript/.eslintrc.cjs b/smart-admin-web-javascript/.eslintrc.cjs index 81e7acc0..82d62576 100644 --- a/smart-admin-web-javascript/.eslintrc.cjs +++ b/smart-admin-web-javascript/.eslintrc.cjs @@ -17,14 +17,14 @@ module.exports = { ecmaVersion: 12, // 默认情况下,ESLint使用的是ECMAScript5语法,此处我们设置的选项是 es12 sourceType: 'module', // 指定js导入的方式 }, - extends: ['plugin:vue/vue3-essential', 'eslint:recommended', 'plugin:vue/base'], + extends: ['plugin:vue/vue3-essential', 'eslint:recommended', 'plugin:vue/base', 'prettier'], globals: { defineProps: 'readonly', defineEmits: 'readonly', defineExpose: 'readonly', withDefaults: 'readonly', }, - plugins: ['vue'], + plugins: ['vue', 'prettier'], rules: { 'no-unused-vars': [ 'error', @@ -62,5 +62,6 @@ module.exports = { ], // Enable vue/script-setup-uses-vars rule 'vue/script-setup-uses-vars': 'error', + 'prettier/prettier': 'error', }, }; diff --git a/smart-admin-web-javascript/README.en.md b/smart-admin-web-javascript/README.en.md deleted file mode 100644 index e69de29b..00000000 diff --git a/smart-admin-web-javascript/src/App.vue b/smart-admin-web-javascript/src/App.vue index 90baebfe..a6d2af38 100644 --- a/smart-admin-web-javascript/src/App.vue +++ b/smart-admin-web-javascript/src/App.vue @@ -49,7 +49,7 @@ import { useAppConfigStore } from '/@/store/modules/system/app-config'; import { useSpinStore } from '/@/store/modules/system/spin'; import { Popover, theme } from 'ant-design-vue'; - import { themeColors } from '/@/theme/color.js'; + import { themeColors } from '/@/theme/color'; import SmartCopyIcon from '/@/components/framework/smart-copy-icon/index.vue'; const antdLocale = computed(() => messages[useAppConfigStore().language].antdLocale); diff --git a/smart-admin-web-javascript/src/components/support/dict-code-select/index.vue b/smart-admin-web-javascript/src/components/support/dict-code-select/index.vue index dbd18d3d..ae1b91d8 100644 --- a/smart-admin-web-javascript/src/components/support/dict-code-select/index.vue +++ b/smart-admin-web-javascript/src/components/support/dict-code-select/index.vue @@ -29,7 +29,7 @@ diff --git a/smart-admin-web-javascript/src/components/support/dict-select/index.vue b/smart-admin-web-javascript/src/components/support/dict-select/index.vue index 1f5a1039..e5bfc315 100644 --- a/smart-admin-web-javascript/src/components/support/dict-select/index.vue +++ b/smart-admin-web-javascript/src/components/support/dict-select/index.vue @@ -29,7 +29,7 @@ diff --git a/smart-admin-web-typescript/src/components/support/dict-select/index.vue b/smart-admin-web-typescript/src/components/support/dict-select/index.vue index 9a4cc2dc..eb544bf6 100644 --- a/smart-admin-web-typescript/src/components/support/dict-select/index.vue +++ b/smart-admin-web-typescript/src/components/support/dict-select/index.vue @@ -29,7 +29,7 @@