6 Commits

Author SHA1 Message Date
zhuoda
6867198bf6 v3.30.0 【增加】字典项增加回显样式;【优化】文件S3协议对最新minio的支持; 2026-03-01 21:37:24 +08:00
zhuoda
2c661120ca v3.30.0 【增加】字典项增加回显样式;【优化】文件S3协议对最新minio的支持; 2026-03-01 21:34:21 +08:00
1024创新实验室
a5adcf1cef !91 fix(code-generator): 修复表前缀去除功能
Merge pull request !91 from CoderKK/removePrefixTableName
2026-03-01 12:16:32 +00:00
1024创新实验室
fcbdb9afe0 !95 fix: 优化环境变量配置,支持代理目标动态化
Merge pull request !95 from yusg/fix/env-proxy-config
2026-03-01 12:14:38 +00:00
yusg
885ad21184 fix: optimize env config and support dynamic proxy target 2026-01-28 11:26:01 +08:00
CoderKK
374cc92a79 fix(code-generator): 修复表前缀去除功能
- 在去除表前缀时,使用 slice 方法替代 trimStart 和 trim 方法
- 修复了之前使用 _.trimStart 或 _.trim 导致的命名错误问题
2025-08-26 10:05:18 +08:00
131 changed files with 976 additions and 541 deletions

View File

@@ -15,6 +15,7 @@ import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import java.net.URI; import java.net.URI;
@@ -31,55 +32,70 @@ import java.net.URI;
@Configuration @Configuration
public class FileConfig implements WebMvcConfigurer { 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_CLOUD = "cloud";
private static final String MODE_LOCAL = "local"; 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}") @Value("${file.storage.mode}")
private String 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 配置 * 初始化 s3 client 配置
*
* @return
*/ */
@Bean @Bean
@ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_CLOUD) @ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_CLOUD)
public S3Client initAmazonS3() { public S3Client initS3Client() {
return S3Client.builder() return S3Client.builder()
.region(Region.AWS_GLOBAL) .region(Region.of(cloudRegion))
.endpointOverride(URI.create((urlPrefix.startsWith(HTTPS) ? HTTPS : HTTP) + endpoint)) .endpointOverride(URI.create(cloudEndpoint))
.credentialsProvider( .credentialsProvider(
StaticCredentialsProvider.create( 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() .serviceConfiguration(S3Configuration.builder()
.pathStyleAccessEnabled(false) .pathStyleAccessEnabled(false)
.chunkedEncodingEnabled(false) .chunkedEncodingEnabled(false)
@@ -102,7 +118,7 @@ public class FileConfig implements WebMvcConfigurer {
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (MODE_LOCAL.equals(mode)) { 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); registry.addResourceHandler(FileStorageLocalServiceImpl.UPLOAD_MAPPING + "/**").addResourceLocations("file:" + path);
} }
} }

View File

@@ -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;
}
}

View File

@@ -40,6 +40,11 @@ public class DictDataEntity {
*/ */
private String dataLabel; private String dataLabel;
/**
* 字典项样式
*/
private String dataStyle;
/** /**
* 备注 * 备注
*/ */

View File

@@ -4,6 +4,10 @@ import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; 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 = "字典项显示名称 不能为空") @NotBlank(message = "字典项显示名称 不能为空")
private String dataLabel; private String dataLabel;
@SchemaEnum(value = DictDataStyleEnum.class, desc = "数据样式")
@CheckEnum(message = "样式参数错误", value = DictDataStyleEnum.class)
private String dataStyle;
@Schema(description = "备注") @Schema(description = "备注")
private String remark; private String remark;

View File

@@ -38,6 +38,9 @@ public class DictDataVO implements Serializable {
@Schema(description = "字典项显示名称") @Schema(description = "字典项显示名称")
private String dataLabel; private String dataLabel;
@Schema(description = "字典项回显")
private String dataStyle;
@Schema(description = "备注") @Schema(description = "备注")
private String remark; private String remark;

View File

@@ -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/", "意见反馈"),
; ;

View File

@@ -71,6 +71,9 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
@Resource @Resource
private S3Client s3Client; private S3Client s3Client;
@Resource
private S3Presigner s3Presigner;
@Resource @Resource
private FileConfig cloudConfig; private FileConfig cloudConfig;
@@ -104,7 +107,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
// 根据文件路径获取并设置访问权限 // 根据文件路径获取并设置访问权限
ObjectCannedACL acl = this.getACL(path); ObjectCannedACL acl = this.getACL(path);
PutObjectRequest putObjectRequest = PutObjectRequest.builder() PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(cloudConfig.getBucketName()) .bucket(cloudConfig.getCloudBucketName())
.key(fileKey) .key(fileKey)
.metadata(userMetadata) .metadata(userMetadata)
.contentLength(file.getSize()) .contentLength(file.getSize())
@@ -128,7 +131,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
uploadVO.setFileName(originalFileName); uploadVO.setFileName(originalFileName);
uploadVO.setFileType(fileType); uploadVO.setFileType(fileType);
// 根据 访问权限 返回不同的 URL // 根据 访问权限 返回不同的 URL
String url = cloudConfig.getUrlPrefix() + fileKey; String url = cloudConfig.getCloudPublicUrlPrefix() + fileKey;
if (ObjectCannedACL.PRIVATE.equals(acl)) { if (ObjectCannedACL.PRIVATE.equals(acl)) {
// 获取临时访问的URL // 获取临时访问的URL
url = this.getFileUrl(fileKey).getData(); url = this.getFileUrl(fileKey).getData();
@@ -153,11 +156,10 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
if (!fileKey.startsWith(FileFolderTypeEnum.FOLDER_PRIVATE)) { 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; String fileRedisKey = RedisKeyConst.Support.FILE_PRIVATE_VO + fileKey;
FileVO fileVO = redisService.getObject(fileRedisKey, FileVO.class); FileVO fileVO = redisService.getObject(fileRedisKey, FileVO.class);
if (fileVO == null) { if (fileVO == null) {
@@ -165,15 +167,22 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
if (fileVO == null) { if (fileVO == null) {
return ResponseDTO.userErrorParam("文件不存在"); return ResponseDTO.userErrorParam("文件不存在");
} }
GetObjectRequest getUrlRequest = GetObjectRequest.builder().bucket(cloudConfig.getBucketName()).key(fileKey).build(); GetObjectRequest getUrlRequest = GetObjectRequest
GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder().signatureDuration(Duration.ofSeconds(cloudConfig.getPrivateUrlExpireSeconds())).getObjectRequest(getUrlRequest).build(); .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(); String url = presignedGetObjectRequest.url().toString();
fileVO.setFileUrl(url); fileVO.setFileUrl(url);
redisService.set(fileRedisKey, fileVO, cloudConfig.getPrivateUrlExpireSeconds() - 5); redisService.set(fileRedisKey, fileVO, cloudConfig.getCloudPrivateUrlExpireSeconds() - 5);
} }
return ResponseDTO.ok(fileVO.getFileUrl()); return ResponseDTO.ok(fileVO.getFileUrl());
@@ -187,7 +196,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
public ResponseDTO<FileDownloadVO> download(String key) { public ResponseDTO<FileDownloadVO> download(String key) {
// 获取文件 meta // 获取文件 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); HeadObjectResponse headObjectResponse = s3Client.headObject(objectRequest);
Map<String, String> userMetadata = headObjectResponse.metadata(); Map<String, String> userMetadata = headObjectResponse.metadata();
FileMetadataVO metadataDTO = null; FileMetadataVO metadataDTO = null;
@@ -201,7 +210,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
} }
//获取oss对象 //获取oss对象
GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(cloudConfig.getBucketName()).key(key).build(); GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(cloudConfig.getCloudBucketName()).key(key).build();
ResponseBytes<GetObjectResponse> s3ClientObject = s3Client.getObject(getObjectRequest, ResponseTransformer.toBytes()); ResponseBytes<GetObjectResponse> s3ClientObject = s3Client.getObject(getObjectRequest, ResponseTransformer.toBytes());
// 输入流转换为字节流 // 输入流转换为字节流
@@ -236,7 +245,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
*/ */
@Override @Override
public ResponseDTO<String> delete(String fileKey) { public ResponseDTO<String> 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); s3Client.deleteObject(deleteObjectRequest);
return ResponseDTO.ok(); return ResponseDTO.ok();
} }

View File

@@ -103,12 +103,13 @@ file:
url-prefix: url-prefix:
cloud: cloud:
region: oss-cn-hangzhou region: oss-cn-hangzhou
endpoint: oss-cn-hangzhou.aliyuncs.com endpoint: https://oss-cn-hangzhou.aliyuncs.com
bucket-name: 1024lab-smart-admin bucket-name: 1024lab-smart-admin
access-key: access-key:
secret-key: secret-key:
url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/
private-url-expire-seconds: 3600 private-url-expire-seconds: 3600
# 云计算厂商支持公开的文件访问模式minio默认是不支持的对于minio用户可以配置为空
public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/
# open api配置 # open api配置
springdoc: springdoc:

View File

@@ -103,12 +103,13 @@ file:
url-prefix: url-prefix:
cloud: cloud:
region: oss-cn-hangzhou region: oss-cn-hangzhou
endpoint: oss-cn-hangzhou.aliyuncs.com endpoint: https://oss-cn-hangzhou.aliyuncs.com
bucket-name: 1024lab-smart-admin bucket-name: 1024lab-smart-admin
access-key: access-key:
secret-key: secret-key:
url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/
private-url-expire-seconds: 3600 private-url-expire-seconds: 3600
# 云计算厂商支持公开的文件访问模式minio默认是不支持的对于minio用户可以配置为空
public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/
# open api配置 # open api配置
springdoc: springdoc:

View File

@@ -103,12 +103,13 @@ file:
url-prefix: url-prefix:
cloud: cloud:
region: oss-cn-hangzhou region: oss-cn-hangzhou
endpoint: oss-cn-hangzhou.aliyuncs.com endpoint: https://oss-cn-hangzhou.aliyuncs.com
bucket-name: 1024lab-smart-admin bucket-name: 1024lab-smart-admin
access-key: access-key:
secret-key: secret-key:
url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/
private-url-expire-seconds: 3600 private-url-expire-seconds: 3600
# 云计算厂商支持公开的文件访问模式minio默认是不支持的对于minio用户可以配置为空
public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/
# open api配置 # open api配置
springdoc: springdoc:

View File

@@ -103,12 +103,13 @@ file:
url-prefix: url-prefix:
cloud: cloud:
region: oss-cn-hangzhou region: oss-cn-hangzhou
endpoint: oss-cn-hangzhou.aliyuncs.com endpoint: https://oss-cn-hangzhou.aliyuncs.com
bucket-name: 1024lab-smart-admin bucket-name: 1024lab-smart-admin
access-key: access-key:
secret-key: secret-key:
url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/
private-url-expire-seconds: 3600 private-url-expire-seconds: 3600
# 云计算厂商支持公开的文件访问模式minio默认是不支持的对于minio用户可以配置为空
public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/
# open api配置 # open api配置
springdoc: springdoc:

View File

@@ -15,6 +15,7 @@ import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import java.net.URI; import java.net.URI;
@@ -31,55 +32,70 @@ import java.net.URI;
@Configuration @Configuration
public class FileConfig implements WebMvcConfigurer { 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_CLOUD = "cloud";
private static final String MODE_LOCAL = "local"; 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}") @Value("${file.storage.mode}")
private String 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 配置 * 初始化 s3 client 配置
*
* @return
*/ */
@Bean @Bean
@ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_CLOUD) @ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_CLOUD)
public S3Client initAmazonS3() { public S3Client initS3Client() {
return S3Client.builder() return S3Client.builder()
.region(Region.AWS_GLOBAL) .region(Region.of(cloudRegion))
.endpointOverride(URI.create((urlPrefix.startsWith(HTTPS) ? HTTPS : HTTP) + endpoint)) .endpointOverride(URI.create(cloudEndpoint))
.credentialsProvider( .credentialsProvider(
StaticCredentialsProvider.create( 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() .serviceConfiguration(S3Configuration.builder()
.pathStyleAccessEnabled(false) .pathStyleAccessEnabled(false)
.chunkedEncodingEnabled(false) .chunkedEncodingEnabled(false)
@@ -102,7 +118,7 @@ public class FileConfig implements WebMvcConfigurer {
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (MODE_LOCAL.equals(mode)) { 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); registry.addResourceHandler(FileStorageLocalServiceImpl.UPLOAD_MAPPING + "/**").addResourceLocations("file:" + path);
} }
} }

View File

@@ -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;
}
}

View File

@@ -40,6 +40,11 @@ public class DictDataEntity {
*/ */
private String dataLabel; private String dataLabel;
/**
* 字典项样式
*/
private String dataStyle;
/** /**
* 备注 * 备注
*/ */

View File

@@ -2,6 +2,9 @@ package net.lab1024.sa.base.module.support.dict.domain.form;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; 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.NotBlank;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@@ -29,6 +32,10 @@ public class DictDataAddForm {
@NotBlank(message = "字典项显示名称 不能为空") @NotBlank(message = "字典项显示名称 不能为空")
private String dataLabel; private String dataLabel;
@SchemaEnum(value = DictDataStyleEnum.class, desc = "数据样式")
@CheckEnum(message = "样式参数错误", value = DictDataStyleEnum.class)
private String dataStyle;
@Schema(description = "备注") @Schema(description = "备注")
private String remark; private String remark;

View File

@@ -38,6 +38,9 @@ public class DictDataVO implements Serializable {
@Schema(description = "字典项显示名称") @Schema(description = "字典项显示名称")
private String dataLabel; private String dataLabel;
@Schema(description = "字典项回显")
private String dataStyle;
@Schema(description = "备注") @Schema(description = "备注")
private String remark; private String remark;

View File

@@ -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/", "意见反馈"),
; ;

View File

@@ -24,7 +24,6 @@ import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.ResponseBytes;
import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.core.sync.ResponseTransformer; 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.S3Client;
import software.amazon.awssdk.services.s3.model.*; import software.amazon.awssdk.services.s3.model.*;
import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.S3Presigner;
@@ -72,6 +71,9 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
@Resource @Resource
private S3Client s3Client; private S3Client s3Client;
@Resource
private S3Presigner s3Presigner;
@Resource @Resource
private FileConfig cloudConfig; private FileConfig cloudConfig;
@@ -109,7 +111,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
// 根据文件路径获取并设置访问权限 // 根据文件路径获取并设置访问权限
ObjectCannedACL acl = this.getACL(path); ObjectCannedACL acl = this.getACL(path);
PutObjectRequest putObjectRequest = PutObjectRequest.builder() PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(cloudConfig.getBucketName()) .bucket(cloudConfig.getCloudBucketName())
.key(fileKey) .key(fileKey)
.metadata(userMetadata) .metadata(userMetadata)
.contentLength(file.getSize()) .contentLength(file.getSize())
@@ -133,7 +135,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
uploadVO.setFileName(originalFileName); uploadVO.setFileName(originalFileName);
uploadVO.setFileType(fileType); uploadVO.setFileType(fileType);
// 根据 访问权限 返回不同的 URL // 根据 访问权限 返回不同的 URL
String url = cloudConfig.getUrlPrefix() + fileKey; String url = cloudConfig.getCloudPublicUrlPrefix() + fileKey;
if (ObjectCannedACL.PRIVATE.equals(acl)) { if (ObjectCannedACL.PRIVATE.equals(acl)) {
// 获取临时访问的URL // 获取临时访问的URL
url = this.getFileUrl(fileKey).getData(); url = this.getFileUrl(fileKey).getData();
@@ -158,11 +160,10 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
if (!fileKey.startsWith(FileFolderTypeEnum.FOLDER_PRIVATE)) { 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; String fileRedisKey = RedisKeyConst.Support.FILE_PRIVATE_VO + fileKey;
FileVO fileVO = redisService.getObject(fileRedisKey, FileVO.class); FileVO fileVO = redisService.getObject(fileRedisKey, FileVO.class);
if (fileVO == null) { if (fileVO == null) {
@@ -170,15 +171,22 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
if (fileVO == null) { if (fileVO == null) {
return ResponseDTO.userErrorParam("文件不存在"); return ResponseDTO.userErrorParam("文件不存在");
} }
GetObjectRequest getUrlRequest = GetObjectRequest.builder().bucket(cloudConfig.getBucketName()).key(fileKey).build(); GetObjectRequest getUrlRequest = GetObjectRequest
GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder().signatureDuration(Duration.ofSeconds(cloudConfig.getPrivateUrlExpireSeconds())).getObjectRequest(getUrlRequest).build(); .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(); String url = presignedGetObjectRequest.url().toString();
fileVO.setFileUrl(url); fileVO.setFileUrl(url);
redisService.set(fileRedisKey, fileVO, cloudConfig.getPrivateUrlExpireSeconds() - 5); redisService.set(fileRedisKey, fileVO, cloudConfig.getCloudPrivateUrlExpireSeconds() - 5);
} }
return ResponseDTO.ok(fileVO.getFileUrl()); return ResponseDTO.ok(fileVO.getFileUrl());
@@ -192,7 +200,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
public ResponseDTO<FileDownloadVO> download(String key) { public ResponseDTO<FileDownloadVO> download(String key) {
// 获取文件 meta // 获取文件 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); HeadObjectResponse headObjectResponse = s3Client.headObject(objectRequest);
Map<String, String> userMetadata = headObjectResponse.metadata(); Map<String, String> userMetadata = headObjectResponse.metadata();
FileMetadataVO metadataDTO = null; FileMetadataVO metadataDTO = null;
@@ -206,7 +214,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
} }
//获取oss对象 //获取oss对象
GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(cloudConfig.getBucketName()).key(key).build(); GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(cloudConfig.getCloudBucketName()).key(key).build();
ResponseBytes<GetObjectResponse> s3ClientObject = s3Client.getObject(getObjectRequest, ResponseTransformer.toBytes()); ResponseBytes<GetObjectResponse> s3ClientObject = s3Client.getObject(getObjectRequest, ResponseTransformer.toBytes());
// 输入流转换为字节流 // 输入流转换为字节流
@@ -241,7 +249,7 @@ public class FileStorageCloudServiceImpl implements IFileStorageService {
*/ */
@Override @Override
public ResponseDTO<String> delete(String fileKey) { public ResponseDTO<String> 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); s3Client.deleteObject(deleteObjectRequest);
return ResponseDTO.ok(); return ResponseDTO.ok();
} }

View File

@@ -102,12 +102,13 @@ file:
url-prefix: url-prefix:
cloud: cloud:
region: oss-cn-hangzhou region: oss-cn-hangzhou
endpoint: oss-cn-hangzhou.aliyuncs.com endpoint: https://oss-cn-hangzhou.aliyuncs.com
bucket-name: 1024lab-smart-admin bucket-name: 1024lab-smart-admin
access-key: access-key:
secret-key: secret-key:
url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/
private-url-expire-seconds: 3600 private-url-expire-seconds: 3600
# 云计算厂商支持公开的文件访问模式minio默认是不支持的对于minio用户可以配置为空
public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/
# open api配置 # open api配置
springdoc: springdoc:

View File

@@ -102,12 +102,13 @@ file:
url-prefix: url-prefix:
cloud: cloud:
region: oss-cn-hangzhou region: oss-cn-hangzhou
endpoint: oss-cn-hangzhou.aliyuncs.com endpoint: https://oss-cn-hangzhou.aliyuncs.com
bucket-name: 1024lab-smart-admin bucket-name: 1024lab-smart-admin
access-key: access-key:
secret-key: secret-key:
url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/
private-url-expire-seconds: 3600 private-url-expire-seconds: 3600
# 云计算厂商支持公开的文件访问模式minio默认是不支持的对于minio用户可以配置为空
public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/
# open api配置 # open api配置
springdoc: springdoc:

View File

@@ -102,12 +102,13 @@ file:
url-prefix: url-prefix:
cloud: cloud:
region: oss-cn-hangzhou region: oss-cn-hangzhou
endpoint: oss-cn-hangzhou.aliyuncs.com endpoint: https://oss-cn-hangzhou.aliyuncs.com
bucket-name: 1024lab-smart-admin bucket-name: 1024lab-smart-admin
access-key: access-key:
secret-key: secret-key:
url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/
private-url-expire-seconds: 3600 private-url-expire-seconds: 3600
# 云计算厂商支持公开的文件访问模式minio默认是不支持的对于minio用户可以配置为空
public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/
# open api配置 # open api配置
springdoc: springdoc:

View File

@@ -102,12 +102,13 @@ file:
url-prefix: url-prefix:
cloud: cloud:
region: oss-cn-hangzhou region: oss-cn-hangzhou
endpoint: oss-cn-hangzhou.aliyuncs.com endpoint: https://oss-cn-hangzhou.aliyuncs.com
bucket-name: 1024lab-smart-admin bucket-name: 1024lab-smart-admin
access-key: access-key:
secret-key: secret-key:
url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/
private-url-expire-seconds: 3600 private-url-expire-seconds: 3600
# 云计算厂商支持公开的文件访问模式minio默认是不支持的对于minio用户可以配置为空
public-url-prefix: https://1024lab-smart-admin.oss-cn-hangzhou.aliyuncs.com/
# open api配置 # open api配置
springdoc: springdoc:

View File

@@ -17,14 +17,14 @@ module.exports = {
ecmaVersion: 12, // 默认情况下ESLint使用的是ECMAScript5语法此处我们设置的选项是 es12 ecmaVersion: 12, // 默认情况下ESLint使用的是ECMAScript5语法此处我们设置的选项是 es12
sourceType: 'module', // 指定js导入的方式 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: { globals: {
defineProps: 'readonly', defineProps: 'readonly',
defineEmits: 'readonly', defineEmits: 'readonly',
defineExpose: 'readonly', defineExpose: 'readonly',
withDefaults: 'readonly', withDefaults: 'readonly',
}, },
plugins: ['vue'], plugins: ['vue', 'prettier'],
rules: { rules: {
'no-unused-vars': [ 'no-unused-vars': [
'error', 'error',
@@ -62,5 +62,6 @@ module.exports = {
], ],
// Enable vue/script-setup-uses-vars rule // Enable vue/script-setup-uses-vars rule
'vue/script-setup-uses-vars': 'error', 'vue/script-setup-uses-vars': 'error',
'prettier/prettier': 'error',
}, },
}; };

View File

@@ -49,7 +49,7 @@
import { useAppConfigStore } from '/@/store/modules/system/app-config'; import { useAppConfigStore } from '/@/store/modules/system/app-config';
import { useSpinStore } from '/@/store/modules/system/spin'; import { useSpinStore } from '/@/store/modules/system/spin';
import { Popover, theme } from 'ant-design-vue'; 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'; import SmartCopyIcon from '/@/components/framework/smart-copy-icon/index.vue';
const antdLocale = computed(() => messages[useAppConfigStore().language].antdLocale); const antdLocale = computed(() => messages[useAppConfigStore().language].antdLocale);

View File

@@ -29,7 +29,7 @@
<script setup> <script setup>
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
const props = defineProps({ const props = defineProps({
value: [Array, String, Number], value: [Array, String, Number],

View File

@@ -1,16 +1,46 @@
<template> <template>
<span>{{ dataLabels }}</span> <template v-if="props.showStyle">
<template v-for="(item, index) in dataList" :key="item.dictDataId">
<span v-if="item.color" :style="{ color: token[item.color] }"> {{ item.dataLabel }} </span>
<span v-else>{{ item.dataLabel }}</span>
{{ index < dataList.length - 1 ? ',' : '' }}
</template>
</template>
<!--不显示回显的颜色演示-->
<template v-else>
<span>{{ dataList }}</span>
</template>
</template> </template>
<script setup> <script setup>
import { computed } from 'vue'; import { computed } from 'vue';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
import { theme } from 'ant-design-vue';
import { DICT_DATA_STYLE_ENUM } from '/@/constants/support/dict-const';
const props = defineProps({ const props = defineProps({
dictCode: String, dictCode: String,
dataValue: [String, Number], dataValue: [String, Number],
showStyle: { type: Boolean, default: false },
}); });
const dataLabels = computed(() => {
return useDictStore().getDataLabels(props.dictCode, props.dataValue); const dataList = computed(() => {
if (!props.showStyle) {
return useDictStore().getDataLabels(props.dictCode, props.dataValue);
}
let dictDataList = useDictStore().getDataList(props.dictCode, props.dataValue);
let dataList = [];
for (const item of dictDataList) {
if (item.dataStyle) {
dataList.push(Object.assign({}, item, { color: DICT_DATA_STYLE_ENUM[item.dataStyle.toUpperCase()].color }));
} else {
dataList.push(Object.assign({}, item));
}
}
return dataList;
}); });
const { useToken } = theme;
const { token } = useToken();
</script> </script>

View File

@@ -29,7 +29,7 @@
<script setup> <script setup>
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
const props = defineProps({ const props = defineProps({
dictCode: String, dictCode: String,

View File

@@ -43,7 +43,7 @@
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { mergeColumn } from './smart-table-column-merge'; import { mergeColumn } from './smart-table-column-merge';
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { useAppConfigStore } from '/@/store/modules/system/app-config.js'; import { useAppConfigStore } from '/@/store/modules/system/app-config';
const props = defineProps({ const props = defineProps({
// 表格列数组 // 表格列数组

View File

@@ -26,7 +26,7 @@
<script setup> <script setup>
import { onMounted, ref, watch } from 'vue'; import { onMounted, ref, watch } from 'vue';
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { positionApi } from '/@/api/system/position-api.js'; import { positionApi } from '/@/api/system/position-api';
// =========== 属性定义 和 事件方法暴露 ============= // =========== 属性定义 和 事件方法暴露 =============

View File

@@ -21,6 +21,7 @@ import message from './business/message/message-const';
import codeGeneratorConst from './support/code-generator-const'; import codeGeneratorConst from './support/code-generator-const';
import changeLogConst from './support/change-log-const'; import changeLogConst from './support/change-log-const';
import jobConst from './support/job-const'; import jobConst from './support/job-const';
import dictConst from './support/dict-const';
export default { export default {
FLAG_NUMBER_ENUM, FLAG_NUMBER_ENUM,
@@ -39,4 +40,5 @@ export default {
...codeGeneratorConst, ...codeGeneratorConst,
...changeLogConst, ...changeLogConst,
...jobConst, ...jobConst,
...dictConst,
}; };

View File

@@ -16,6 +16,40 @@ export const DICT_CODE_ENUM = {
GOODS_PLACE: 'GOODS_PLACE', GOODS_PLACE: 'GOODS_PLACE',
}; };
export const DICT_DATA_STYLE_ENUM = {
DEFAULT: {
value: 'default',
desc: '默认',
color: 'colorText',
},
PRIMARY: {
value: 'primary',
desc: '主要',
color: 'colorPrimary',
},
SUCCESS: {
value: 'success',
desc: '成功',
color: 'colorSuccess',
},
INFO: {
value: 'info',
desc: '信息',
color: 'colorInfo',
},
WARN: {
value: 'warn',
desc: '警告',
color: 'colorWarning',
},
DANGER: {
value: 'danger',
desc: '危险',
color: 'colorError',
},
};
export default { export default {
DICT_CODE_ENUM, DICT_CODE_ENUM,
DICT_DATA_STYLE_ENUM,
}; };

View File

@@ -16,10 +16,10 @@
<script setup> <script setup>
import { computed } from 'vue'; import { computed } from 'vue';
import Password from '/@/views/system/account/components/password/index.vue'; import Password from '/@/views/system/account/components/password/index.vue';
import { useUserStore } from '/@/store/modules/system/user.js'; import { useUserStore } from '/@/store/modules/system/user';
import { loginApi } from '/@/api/system/login-api.js'; import { loginApi } from '/@/api/system/login-api';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
import { SmartLoading } from '/@/components/framework/smart-loading/index.js'; import { SmartLoading } from '/@/components/framework/smart-loading/index';
/** /**
* 修改密码弹窗 * 修改密码弹窗

View File

@@ -40,7 +40,7 @@
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import HeaderResetPassword from './header-reset-password-modal/index.vue'; import HeaderResetPassword from './header-reset-password-modal/index.vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { ACCOUNT_MENU } from '/@/views/system/account/account-menu.js'; import { ACCOUNT_MENU } from '/@/views/system/account/account-menu';
// 头像背景颜色 // 头像背景颜色
const AVATAR_BACKGROUND_COLOR_ARRAY = ['#87d068', '#00B853', '#f56a00', '#1890ff']; const AVATAR_BACKGROUND_COLOR_ARRAY = ['#87d068', '#00B853', '#f56a00', '#1890ff'];

View File

@@ -17,7 +17,7 @@
</template> </template>
<script setup> <script setup>
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
import { messageApi } from '/@/api/support/message-api.js'; import { messageApi } from '/@/api/support/message-api';
const emit = defineEmits(['refresh']); const emit = defineEmits(['refresh']);

View File

@@ -74,9 +74,9 @@
<script setup> <script setup>
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { BellOutlined } from '@ant-design/icons-vue'; import { BellOutlined } from '@ant-design/icons-vue';
import { useUserStore } from '/@/store/modules/system/user.js'; import { useUserStore } from '/@/store/modules/system/user';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
import { messageApi } from '/@/api/support/message-api.js'; import { messageApi } from '/@/api/support/message-api';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { theme } from 'ant-design-vue'; import { theme } from 'ant-design-vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';

View File

@@ -137,7 +137,7 @@
import { useAppConfigStore } from '/@/store/modules/system/app-config'; import { useAppConfigStore } from '/@/store/modules/system/app-config';
import { Modal } from 'ant-design-vue'; import { Modal } from 'ant-design-vue';
import { appDefaultConfig } from '/@/config/app-config'; import { appDefaultConfig } from '/@/config/app-config';
import { themeColors } from '/@/theme/color.js'; import { themeColors } from '/@/theme/color';
// ----------------- modal 显示与隐藏 ----------------- // ----------------- modal 显示与隐藏 -----------------

View File

@@ -21,7 +21,7 @@
import DefaultTab from './components/default-tab.vue'; import DefaultTab from './components/default-tab.vue';
import AntdTab from './components/antd-tab.vue'; import AntdTab from './components/antd-tab.vue';
import ChromeTab from './components/chrome-tab.vue'; import ChromeTab from './components/chrome-tab.vue';
import { PAGE_TAG_ENUM } from '/@/constants/layout-const.js'; import { PAGE_TAG_ENUM } from '/@/constants/layout-const';
import { theme } from 'ant-design-vue'; import { theme } from 'ant-design-vue';
const pageTagStyle = computed(() => useAppConfigStore().$state.pageTagStyle); const pageTagStyle = computed(() => useAppConfigStore().$state.pageTagStyle);

View File

@@ -104,7 +104,7 @@
import SideHelpDoc from './components/side-help-doc/index.vue'; import SideHelpDoc from './components/side-help-doc/index.vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const.js'; import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const';
import { theme as antDesignTheme } from 'ant-design-vue'; import { theme as antDesignTheme } from 'ant-design-vue';
const appConfigStore = useAppConfigStore(); const appConfigStore = useAppConfigStore();

View File

@@ -112,7 +112,7 @@
import SideHelpDoc from './components/side-help-doc/index.vue'; import SideHelpDoc from './components/side-help-doc/index.vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const.js'; import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const';
import { theme as antDesignTheme } from 'ant-design-vue'; import { theme as antDesignTheme } from 'ant-design-vue';
const appConfigStore = useAppConfigStore(); const appConfigStore = useAppConfigStore();

View File

@@ -62,7 +62,7 @@
import { useUserStore } from '/@/store/modules/system/user'; import { useUserStore } from '/@/store/modules/system/user';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const.js'; import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const';
import MenuLocationBreadcrumb from './components/menu-location-breadcrumb/index.vue'; import MenuLocationBreadcrumb from './components/menu-location-breadcrumb/index.vue';
import { theme as antDesignTheme } from 'ant-design-vue'; import { theme as antDesignTheme } from 'ant-design-vue';

View File

@@ -14,7 +14,7 @@ import { useUserStore } from '/@/store/modules/system/user';
import { decryptData, encryptData } from './encrypt'; import { decryptData, encryptData } from './encrypt';
import { DATA_TYPE_ENUM } from '../constants/common-const'; import { DATA_TYPE_ENUM } from '../constants/common-const';
import _ from 'lodash'; import _ from 'lodash';
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; import LocalStorageKeyConst from '/@/constants/local-storage-key-const';
// token的消息头 // token的消息头
const TOKEN_HEADER = 'Authorization'; const TOKEN_HEADER = 'Authorization';

View File

@@ -28,11 +28,11 @@ import { store } from '/@/store';
import { useUserStore } from '/@/store/modules/system/user'; import { useUserStore } from '/@/store/modules/system/user';
import 'ant-design-vue/dist/reset.css'; import 'ant-design-vue/dist/reset.css';
import '/@/theme/index.less'; import '/@/theme/index.less';
import { localRead } from '/@/utils/local-util.js'; import { localRead } from '/@/utils/local-util';
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; import LocalStorageKeyConst from '/@/constants/local-storage-key-const';
import '/@/utils/ployfill'; import '/@/utils/ployfill';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
import { dictApi } from '/@/api/support/dict-api.js'; import { dictApi } from '/@/api/support/dict-api';
/* /*
* -------------------- ※ 着重 解释说明下main.js的初始化逻辑 begin ※ -------------------- * -------------------- ※ 着重 解释说明下main.js的初始化逻辑 begin ※ --------------------

View File

@@ -8,7 +8,7 @@
* @Email: lab1024@163.com * @Email: lab1024@163.com
* @Copyright 1024创新实验室 https://1024lab.net Since 2012 * @Copyright 1024创新实验室 https://1024lab.net Since 2012
*/ */
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
export default { export default {
install: (app) => { install: (app) => {

View File

@@ -18,7 +18,7 @@ import SmartLayout from '../layout/index.vue';
import { useUserStore } from '/@/store/modules/system/user'; import { useUserStore } from '/@/store/modules/system/user';
import { localClear, localRead } from '/@/utils/local-util'; import { localClear, localRead } from '/@/utils/local-util';
import _ from 'lodash'; import _ from 'lodash';
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; import LocalStorageKeyConst from '/@/constants/local-storage-key-const';
export const router = createRouter({ export const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),

View File

@@ -12,7 +12,7 @@ export const loginRouters = [
{ {
path: '/login', path: '/login',
name: 'Login', name: 'Login',
component: () => import('/@/views/system/login3/login.vue'), component: () => import('/@/views/system/login/login.vue'),
meta: { meta: {
title: '登录', title: '登录',
hideInMenu: true, hideInMenu: true,

View File

@@ -1,8 +1,8 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { DICT_SPLIT } from '/@/constants/support/dict-const.js'; import { DICT_SPLIT } from '/@/constants/support/dict-const';
import _ from 'lodash'; import _ from 'lodash';
import { dictApi } from '/@/api/support/dict-api.js'; import { dictApi } from '/@/api/support/dict-api';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
export const useDictStore = defineStore({ export const useDictStore = defineStore({
id: 'dict', id: 'dict',
@@ -26,6 +26,34 @@ export const useDictStore = defineStore({
return dictDataList ? dictDataList : []; return dictDataList ? dictDataList : [];
}, },
// 获取字典的值名称
getDataList(dictCode, dataValue) {
if (_.isNil(dataValue) || _.isNaN(dataValue)) {
return '';
}
let dict = this.getDictData(dictCode);
if (dict.length === 0) {
return '';
}
// 是数字的话,需要特殊处理
if (_.isNumber(dataValue)) {
let target = _.find(dict, { dataValue: String(dataValue) });
return target ? target.dataLabel : '';
}
let valueArray = dataValue.split(DICT_SPLIT);
let result = [];
for (let item of valueArray) {
let target = _.find(dict, { dataValue: item });
if (target) {
result.push(target);
}
}
return result;
},
// 获取字典的值名称 // 获取字典的值名称
getDataLabels(dictCode, dataValue) { getDataLabels(dictCode, dataValue) {
if (_.isNil(dataValue) || _.isNaN(dataValue)) { if (_.isNil(dataValue) || _.isNaN(dataValue)) {

View File

@@ -8,7 +8,7 @@
* @Copyright 1024创新实验室 https://1024lab.net Since 2012 * @Copyright 1024创新实验室 https://1024lab.net Since 2012
*/ */
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
export const useSpinStore = defineStore({ export const useSpinStore = defineStore({
id: 'spin', id: 'spin',

View File

@@ -12,8 +12,8 @@ import { defineStore } from 'pinia';
import localKey from '/@/constants/local-storage-key-const'; import localKey from '/@/constants/local-storage-key-const';
import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
import { MENU_TYPE_ENUM } from '/@/constants/system/menu-const'; import { MENU_TYPE_ENUM } from '/@/constants/system/menu-const';
import { messageApi } from '/@/api/support/message-api.js'; import { messageApi } from '/@/api/support/message-api';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
import { localRead, localSave, localRemove } from '/@/utils/local-util'; import { localRead, localSave, localRemove } from '/@/utils/local-util';

View File

@@ -118,7 +118,7 @@
{{ text }} {{ text }}
</template> </template>
<template v-if="column.dataIndex === 'place'"> <template v-if="column.dataIndex === 'place'">
<DictLabel :dict-code="DICT_CODE_ENUM.GOODS_PLACE" :data-value="text" /> <DictLabel :show-style="true" :dict-code="DICT_CODE_ENUM.GOODS_PLACE" :data-value="text" />
</template> </template>
<template v-if="column.dataIndex === 'remark'"> <template v-if="column.dataIndex === 'remark'">
<span>{{ text ? text : '' }}</span> <span>{{ text ? text : '' }}</span>
@@ -200,7 +200,7 @@
import SmartEnumSelect from '/@/components/framework/smart-enum-select/index.vue'; import SmartEnumSelect from '/@/components/framework/smart-enum-select/index.vue';
import _ from 'lodash'; import _ from 'lodash';
import SmartHeaderCell from '/@/components/support/table-header-cell/index.vue'; import SmartHeaderCell from '/@/components/support/table-header-cell/index.vue';
import { DICT_CODE_ENUM } from '/@/constants/support/dict-const.js'; import { DICT_CODE_ENUM } from '/@/constants/support/dict-const';
import DictLabel from '/@/components/support/dict-label/index.vue'; import DictLabel from '/@/components/support/dict-label/index.vue';
// ---------------------------- 表格列 ---------------------------- // ---------------------------- 表格列 ----------------------------

View File

@@ -92,7 +92,7 @@
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import TableOperator from '/@/components/support/table-operator/index.vue'; import TableOperator from '/@/components/support/table-operator/index.vue';
import { TABLE_ID_CONST } from '/@/constants/support/table-id-const'; import { TABLE_ID_CONST } from '/@/constants/support/table-id-const';
import { defaultTimeRanges } from '/@/lib/default-time-ranges.js'; import { defaultTimeRanges } from '/@/lib/default-time-ranges';
const props = defineProps({ const props = defineProps({
enterpriseId: { enterpriseId: {

View File

@@ -183,6 +183,7 @@
let removePrefixTableName = tableInfo.tableName; let removePrefixTableName = tableInfo.tableName;
if (_.startsWith(tableInfo.tableName, tablePrefix.value)) { if (_.startsWith(tableInfo.tableName, tablePrefix.value)) {
removePrefixTableName = _.trimStart(removePrefixTableName, tablePrefix.value); removePrefixTableName = _.trimStart(removePrefixTableName, tablePrefix.value);
removePrefixTableName = removePrefixTableName.slice(tablePrefix.value.length);
} }
formData.moduleName = basic && basic.moduleName ? basic.moduleName : removePrefixTableName; formData.moduleName = basic && basic.moduleName ? basic.moduleName : removePrefixTableName;
formData.moduleName = convertUpperCamel(formData.moduleName); formData.moduleName = convertUpperCamel(formData.moduleName);
@@ -205,7 +206,7 @@
function onChangeTablePrefix(e) { function onChangeTablePrefix(e) {
let removePrefixTableName = tableInfo.tableName; let removePrefixTableName = tableInfo.tableName;
if (_.startsWith(tableInfo.tableName, tablePrefix.value)) { if (_.startsWith(tableInfo.tableName, tablePrefix.value)) {
removePrefixTableName = _.trim(removePrefixTableName, tablePrefix.value); removePrefixTableName = tableInfo.tableName.slice(tablePrefix.value.length);
} }
formData.moduleName = convertUpperCamel(removePrefixTableName); formData.moduleName = convertUpperCamel(removePrefixTableName);
} }

View File

@@ -84,7 +84,7 @@
import DictCodeSelect from '/@/components/support/dict-code-select/index.vue'; import DictCodeSelect from '/@/components/support/dict-code-select/index.vue';
import { convertUpperCamel, convertLowerCamel } from '/@/utils/str-util'; import { convertUpperCamel, convertLowerCamel } from '/@/utils/str-util';
import _ from 'lodash'; import _ from 'lodash';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
const dictRef = ref(); const dictRef = ref();
function refreshDict() { function refreshDict() {

View File

@@ -42,7 +42,7 @@
import { JAVA_FILE_LIST, LANGUAGE_LIST, JS_FILE_LIST, TS_FILE_LIST } from '../../code-generator-util'; import { JAVA_FILE_LIST, LANGUAGE_LIST, JS_FILE_LIST, TS_FILE_LIST } from '../../code-generator-util';
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { lineNumbersBlock } from '/@/lib/highlight-line-number'; import { lineNumbersBlock } from '/@/lib/highlight-line-number';
import hljs from 'highlight.js'; import hljs from 'highlight';
import 'highlight.js/styles/github-dark.css'; import 'highlight.js/styles/github-dark.css';
import javascript from 'highlight.js/lib/languages/javascript'; import javascript from 'highlight.js/lib/languages/javascript';
import typescript from 'highlight.js/lib/languages/typescript'; import typescript from 'highlight.js/lib/languages/typescript';

View File

@@ -17,6 +17,15 @@
<a-form-item label="字典项值" name="dataValue"> <a-form-item label="字典项值" name="dataValue">
<a-input v-model:value="form.dataValue" placeholder="请输入 字典项值" /> <a-input v-model:value="form.dataValue" placeholder="请输入 字典项值" />
</a-form-item> </a-form-item>
<a-form-item label="显示样式">
<a-select ref="dataStyleSelect" v-model:value="form.dataStyle" :allowClear="true">
<template v-for="item in DICT_DATA_STYLE_ENUM" :key="item.value">
<a-select-option :value="item.value">
<div :style="{ color: token[item.color] }">{{ item.desc }}({{ item.value }})</div>
</a-select-option>
</template>
</a-select>
</a-form-item>
<a-form-item label="排序" name="sort" help="值越大越靠前"> <a-form-item label="排序" name="sort" help="值越大越靠前">
<a-input-number style="width: 100%" v-model:value="form.sortOrder" :min="0" :max="1000" /> <a-input-number style="width: 100%" v-model:value="form.sortOrder" :min="0" :max="1000" />
</a-form-item> </a-form-item>
@@ -28,10 +37,14 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive } from 'vue'; import { ref, reactive } from 'vue';
import { message } from 'ant-design-vue'; import { message, theme } from 'ant-design-vue';
import { SmartLoading } from '/@/components/framework/smart-loading'; import { SmartLoading } from '/@/components/framework/smart-loading';
import { dictApi } from '/@/api/support/dict-api'; import { dictApi } from '/@/api/support/dict-api';
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { DICT_DATA_STYLE_ENUM } from '/@/constants/support/dict-const';
const { useToken } = theme;
const { token } = useToken();
// emit // emit
const emit = defineEmits(['reloadList']); const emit = defineEmits(['reloadList']);
@@ -46,6 +59,7 @@
sortOrder: 0, sortOrder: 0,
dataValue: '', dataValue: '',
dataLabel: '', dataLabel: '',
dataStyle: '',
remark: '', remark: '',
}; };
let form = reactive({ ...formDefault }); let form = reactive({ ...formDefault });

View File

@@ -145,11 +145,12 @@
title: '文件夹', title: '文件夹',
dataIndex: 'folderType', dataIndex: 'folderType',
ellipsis: true, ellipsis: true,
width: 100, width: 70,
}, },
{ {
title: '文件名称', title: '文件名称',
dataIndex: 'fileName', dataIndex: 'fileName',
ellipsis: true,
width: 200, width: 200,
}, },
{ {
@@ -164,24 +165,18 @@
ellipsis: true, ellipsis: true,
width: 80, width: 80,
}, },
{
title: '上传人',
dataIndex: 'creatorName',
ellipsis: true,
width: 100,
},
{
title: '人类型',
dataIndex: 'creatorUserType',
ellipsis: true,
width: 100,
},
{ {
title: '上传时间', title: '上传时间',
dataIndex: 'createTime', dataIndex: 'createTime',
ellipsis: true, ellipsis: true,
width: 150, width: 150,
}, },
{
title: '文件Key',
dataIndex: 'fileKey',
ellipsis: true,
width: 100,
},
{ {
title: '操作', title: '操作',
dataIndex: 'action', dataIndex: 'action',

View File

@@ -130,7 +130,7 @@
import { jobApi } from '/@/api/support/job-api'; import { jobApi } from '/@/api/support/job-api';
import { PAGE_SIZE_OPTIONS } from '/@/constants/common-const'; import { PAGE_SIZE_OPTIONS } from '/@/constants/common-const';
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { TRIGGER_TYPE_ENUM } from '/@/constants/support/job-const.js'; import { TRIGGER_TYPE_ENUM } from '/@/constants/support/job-const';
import JobLogListModal from './job-log-list-modal.vue'; import JobLogListModal from './job-log-list-modal.vue';
import {TABLE_ID_CONST} from "/@/constants/support/table-id-const.js"; import {TABLE_ID_CONST} from "/@/constants/support/table-id-const.js";
import TableOperator from "/@/components/support/table-operator/index.vue"; import TableOperator from "/@/components/support/table-operator/index.vue";

View File

@@ -120,8 +120,8 @@ import { message } from 'ant-design-vue';
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
import { jobApi } from '/@/api/support/job-api'; import { jobApi } from '/@/api/support/job-api';
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { SmartLoading } from '/@/components/framework/smart-loading/index.js'; import { SmartLoading } from '/@/components/framework/smart-loading/index';
import { TRIGGER_TYPE_ENUM } from '/@/constants/support/job-const.js'; import { TRIGGER_TYPE_ENUM } from '/@/constants/support/job-const';
// emit // emit
const emit = defineEmits(['reloadList']); const emit = defineEmits(['reloadList']);

View File

@@ -94,7 +94,7 @@
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import TableOperator from '/@/components/support/table-operator/index.vue'; import TableOperator from '/@/components/support/table-operator/index.vue';
import { TABLE_ID_CONST } from '/@/constants/support/table-id-const'; import { TABLE_ID_CONST } from '/@/constants/support/table-id-const';
import { defaultTimeRanges } from '/@/lib/default-time-ranges.js'; import { defaultTimeRanges } from '/@/lib/default-time-ranges';
const showFlag = ref(false); const showFlag = ref(false);
const title = ref(''); const title = ref('');

View File

@@ -160,10 +160,10 @@
import TableOperator from '/@/components/support/table-operator/index.vue'; import TableOperator from '/@/components/support/table-operator/index.vue';
import { TABLE_ID_CONST } from '/@/constants/support/table-id-const'; import { TABLE_ID_CONST } from '/@/constants/support/table-id-const';
import DeletedJobList from './components/deleted-job-list.vue'; import DeletedJobList from './components/deleted-job-list.vue';
import { TRIGGER_TYPE_ENUM } from '/@/constants/support/job-const.js'; import { TRIGGER_TYPE_ENUM } from '/@/constants/support/job-const';
import JobFormModal from './components/job-form-modal.vue'; import JobFormModal from './components/job-form-modal.vue';
import JobLogListModal from './components/job-log-list-modal.vue'; import JobLogListModal from './components/job-log-list-modal.vue';
import { SmartLoading } from '/@/components/framework/smart-loading/index.js'; import { SmartLoading } from '/@/components/framework/smart-loading/index';
const activeKey = ref('1'); const activeKey = ref('1');
const columns = ref([ const columns = ref([
{ {

View File

@@ -62,7 +62,7 @@
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import TableOperator from '/@/components/support/table-operator/index.vue'; import TableOperator from '/@/components/support/table-operator/index.vue';
import { TABLE_ID_CONST } from '/@/constants/support/table-id-const'; import { TABLE_ID_CONST } from '/@/constants/support/table-id-const';
import { dataMaskingApi } from '/@/api/support/data-masking-api.js'; import { dataMaskingApi } from '/@/api/support/data-masking-api';
//------------------------ 表格渲染 --------------------- //------------------------ 表格渲染 ---------------------

View File

@@ -117,9 +117,9 @@
</template> </template>
<script setup> <script setup>
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { level3ProtectApi } from '/@/api/support/level3-protect-api.js'; import { level3ProtectApi } from '/@/api/support/level3-protect-api';
import { SmartLoading } from '/@/components/framework/smart-loading/index.js'; import { SmartLoading } from '/@/components/framework/smart-loading/index';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
import { message, Modal } from 'ant-design-vue'; import { message, Modal } from 'ant-design-vue';
// 三级等保的默认值 // 三级等保的默认值

View File

@@ -96,7 +96,7 @@
import TableOperator from '/@/components/support/table-operator/index.vue'; import TableOperator from '/@/components/support/table-operator/index.vue';
import MessageSendForm from './components/message-send-form.vue'; import MessageSendForm from './components/message-send-form.vue';
import { TABLE_ID_CONST } from '/@/constants/support/table-id-const'; import { TABLE_ID_CONST } from '/@/constants/support/table-id-const';
import { defaultTimeRanges } from '/@/lib/default-time-ranges.js'; import { defaultTimeRanges } from '/@/lib/default-time-ranges';
// ---------------------------- 表格列 ---------------------------- // ---------------------------- 表格列 ----------------------------
const columns = ref([ const columns = ref([

View File

@@ -76,18 +76,18 @@
</template> </template>
<script setup> <script setup>
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { regular } from '/@/constants/regular-const.js'; import { regular } from '/@/constants/regular-const';
import DepartmentTreeSelect from '/@/components/system/department-tree-select/index.vue'; import DepartmentTreeSelect from '/@/components/system/department-tree-select/index.vue';
import PositionSelect from '/@/components/system/position-select/index.vue'; import PositionSelect from '/@/components/system/position-select/index.vue';
import SmartEnumSelect from '/@/components/framework/smart-enum-select/index.vue'; import SmartEnumSelect from '/@/components/framework/smart-enum-select/index.vue';
import { loginApi } from '/@/api/system/login-api.js'; import { loginApi } from '/@/api/system/login-api';
import { useUserStore } from '/@/store/modules/system/user.js'; import { useUserStore } from '/@/store/modules/system/user';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
import { employeeApi } from '/@/api/system/employee-api'; import { employeeApi } from '/@/api/system/employee-api';
import { SmartLoading } from '/@/components/framework/smart-loading/index.js'; import { SmartLoading } from '/@/components/framework/smart-loading/index';
import { fileApi } from '/@/api/support/file-api.js'; import { fileApi } from '/@/api/support/file-api';
import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const.js'; import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const';
// 组件ref // 组件ref
const formRef = ref(); const formRef = ref();

View File

@@ -14,8 +14,8 @@
</template> </template>
<script setup> <script setup>
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
import { messageApi } from '/@/api/support/message-api.js'; import { messageApi } from '/@/api/support/message-api';
import { useUserStore } from '/@/store/modules/system/user.js'; import { useUserStore } from '/@/store/modules/system/user';
const emit = defineEmits(['refresh']); const emit = defineEmits(['refresh']);

View File

@@ -86,7 +86,7 @@
import { messageApi } from '/@/api/support/message-api'; import { messageApi } from '/@/api/support/message-api';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '/@/constants/common-const'; import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '/@/constants/common-const';
import SmartEnumSelect from '/@/components/framework/smart-enum-select//index.vue'; import SmartEnumSelect from '/@/components/framework/smart-enum-select//index.vue';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
import MessageDetail from './components/message-detail.vue'; import MessageDetail from './components/message-detail.vue';
const columns = reactive([ const columns = reactive([

View File

@@ -20,9 +20,9 @@
<script setup> <script setup>
import { computed, onMounted, reactive, ref } from 'vue'; import { computed, onMounted, reactive, ref } from 'vue';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { SmartLoading } from '/@/components/framework/smart-loading/index.js'; import { SmartLoading } from '/@/components/framework/smart-loading/index';
import { employeeApi } from '/@/api/system/employee-api.js'; import { employeeApi } from '/@/api/system/employee-api';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
const emits = defineEmits(['onSuccess']); const emits = defineEmits(['onSuccess']);

View File

@@ -21,9 +21,9 @@
<script setup> <script setup>
import { computed, onMounted, ref, watch } from 'vue'; import { computed, onMounted, ref, watch } from 'vue';
import _ from 'lodash'; import _ from 'lodash';
import { ACCOUNT_MENU } from '/@/views/system/account/account-menu.js'; import { ACCOUNT_MENU } from '/@/views/system/account/account-menu';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useUserStore } from '/@/store/modules/system/user.js'; import { useUserStore } from '/@/store/modules/system/user';
import { theme as antDesignTheme } from 'ant-design-vue'; import { theme as antDesignTheme } from 'ant-design-vue';
// 菜单展示 // 菜单展示

View File

@@ -43,7 +43,7 @@
import ToBeDoneModal from './to-be-done-modal.vue'; import ToBeDoneModal from './to-be-done-modal.vue';
import localKey from '/@/constants/local-storage-key-const'; import localKey from '/@/constants/local-storage-key-const';
import { localRead, localSave } from '/@/utils/local-util'; import { localRead, localSave } from '/@/utils/local-util';
import { useUserStore } from '/@/store/modules/system/user.js'; import { useUserStore } from '/@/store/modules/system/user';
import { computed, ref, onMounted } from 'vue'; import { computed, ref, onMounted } from 'vue';
import { Modal } from 'ant-design-vue'; import { Modal } from 'ant-design-vue';

View File

@@ -7,7 +7,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
.box-item { .box-item {
width: 444px; width: 464px;
height: 600px; height: 600px;
&.desc { &.desc {
background: #003b94; background: #003b94;
@@ -108,7 +108,7 @@
transform: translateX(0); transform: translateX(0);
} }
100% { 100% {
transform: translateX(-30%); transform: translateX(-5%);
} }
} }
@@ -119,7 +119,7 @@
display: inline-block; display: inline-block;
width: 100%; width: 100%;
white-space: nowrap; white-space: nowrap;
animation: marquee 5s linear infinite; animation: marquee 3s linear infinite;
} }
} }
} }
@@ -151,7 +151,7 @@
.code-btn{ .code-btn{
height: 44px; height: 44px;
padding: 4px 5px; padding: 4px 5px;
width: 108px; width: 100%;
} }
.eye-box { .eye-box {
@@ -165,7 +165,7 @@
} }
} }
.btn { .btn {
width: 350px; width: 100%;
height: 50px; height: 50px;
background: #1748FD; background: #1748FD;
border-radius: 4px; border-radius: 4px;

View File

@@ -46,7 +46,8 @@
<img :src="gzh" /> <img :src="gzh" />
<div class="qr-desc-marquee"> <div class="qr-desc-marquee">
<div class="marquee"> <div class="marquee">
<span>关注六边形工程师分享赚钱代码生活</span> <span>关注六边形工程师</span>
<span>分享AI赚钱代码健康</span>
</div> </div>
</div> </div>
</div> </div>
@@ -68,24 +69,33 @@
</a-input-group> </a-input-group>
</a-form-item> </a-form-item>
<a-form-item name="password"> <a-form-item name="password">
<a-input-password <a-popover placement="top">
v-model:value="loginForm.password" <template #content>
autocomplete="on" <a-flex :vertical="true" justify="center" align="center">
:type="showPassword ? 'text' : 'password'" <img :src="gzh" />
placeholder="请输入密码" <a-typography-text type="danger">扫码关注六边形工程师</a-typography-text>
/> <a-typography-text type="danger">完成问卷调查获取登录密码</a-typography-text>
</a-flex>
</template>
<a-input-password
v-model:value="loginForm.password"
autocomplete="on"
:type="showPassword ? 'text' : 'password'"
placeholder="请输入密码"
/>
</a-popover>
</a-form-item> </a-form-item>
<a-form-item name="captchaCode"> <a-form-item name="captchaCode">
<a-input class="captcha-input" v-model:value.trim="loginForm.captchaCode" placeholder="请输入验证码" /> <a-input class="captcha-input" v-model:value.trim="loginForm.captchaCode" placeholder="请输入验证码" />
<img class="captcha-img" :src="captchaBase64Image" @click="getCaptcha" /> <img class="captcha-img" :src="captchaBase64Image" @click="getCaptcha" />
</a-form-item> </a-form-item>
<a-form-item>
<a-checkbox v-model:checked="rememberPwd">记住密码</a-checkbox>
<span> ( 账号admin, 密码123456)</span>
</a-form-item>
<a-form-item> <a-form-item>
<div class="btn" @click="onLogin">登录</div> <div class="btn" @click="onLogin">登录</div>
</a-form-item> </a-form-item>
<a-form-item>
<span> 账号admin, 关注六边形工程师参与问卷获取密码</span>
</a-form-item>
</a-form> </a-form>
<div class="more"> <div class="more">
<div class="title-box"> <div class="title-box">
@@ -129,10 +139,10 @@
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { encryptData } from '/@/lib/encrypt'; import { encryptData } from '/@/lib/encrypt';
import { h } from 'vue'; import { h } from 'vue';
import { localSave } from '/@/utils/local-util.js'; import { localSave } from '/@/utils/local-util';
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; import LocalStorageKeyConst from '/@/constants/local-storage-key-const';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
import {dictApi} from "/@/api/support/dict-api.js"; import { dictApi } from '/@/api/support/dict-api';
//--------------------- 登录表单 --------------------------------- //--------------------- 登录表单 ---------------------------------
@@ -221,6 +231,7 @@
//--------------------- 验证码 --------------------------------- //--------------------- 验证码 ---------------------------------
const captchaBase64Image = ref(''); const captchaBase64Image = ref('');
async function getCaptcha() { async function getCaptcha() {
try { try {
let captchaResult = await loginApi.getCaptcha(); let captchaResult = await loginApi.getCaptcha();
@@ -233,6 +244,7 @@
} }
let refreshCaptchaInterval = null; let refreshCaptchaInterval = null;
function beginRefreshCaptchaInterval(expireSeconds) { function beginRefreshCaptchaInterval(expireSeconds) {
if (refreshCaptchaInterval === null) { if (refreshCaptchaInterval === null) {
refreshCaptchaInterval = setInterval(getCaptcha, (expireSeconds - 5) * 1000); refreshCaptchaInterval = setInterval(getCaptcha, (expireSeconds - 5) * 1000);
@@ -258,6 +270,7 @@
let emailCodeButtonDisabled = ref(false); let emailCodeButtonDisabled = ref(false);
// 定时器 // 定时器
let countDownTimer = null; let countDownTimer = null;
// 开始倒计时 // 开始倒计时
function runCountDown() { function runCountDown() {
emailCodeButtonDisabled.value = true; emailCodeButtonDisabled.value = true;

View File

@@ -90,10 +90,10 @@
import { buildRoutes } from '/@/router/index'; import { buildRoutes } from '/@/router/index';
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { encryptData } from '/@/lib/encrypt'; import { encryptData } from '/@/lib/encrypt';
import { localSave } from '/@/utils/local-util.js'; import { localSave } from '/@/utils/local-util';
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; import LocalStorageKeyConst from '/@/constants/local-storage-key-const';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
import { dictApi } from '/@/api/support/dict-api.js'; import { dictApi } from '/@/api/support/dict-api';
//--------------------- 登录表单 --------------------------------- //--------------------- 登录表单 ---------------------------------

View File

@@ -92,10 +92,10 @@
import { buildRoutes } from '/@/router/index'; import { buildRoutes } from '/@/router/index';
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { encryptData } from '/@/lib/encrypt'; import { encryptData } from '/@/lib/encrypt';
import { localSave } from '/@/utils/local-util.js'; import { localSave } from '/@/utils/local-util';
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; import LocalStorageKeyConst from '/@/constants/local-storage-key-const';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
import { dictApi } from '/@/api/support/dict-api.js'; import { dictApi } from '/@/api/support/dict-api';
//--------------------- 登录表单 --------------------------------- //--------------------- 登录表单 ---------------------------------

View File

@@ -9,91 +9,96 @@
*/ */
import { resolve } from 'path'; import { resolve } from 'path';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import customVariables from '/@/theme/custom-variables.js'; import { loadEnv } from 'vite';
import customVariables from '/@/theme/custom-variables';
const pathResolve = (dir) => { const pathResolve = (dir) => {
return resolve(__dirname, '.', dir); return resolve(__dirname, '.', dir);
}; };
export default {
base: process.env.NODE_ENV === 'production' ? '/' : '/', export default ({ mode }) => {
root: process.cwd(), const env = loadEnv(mode, process.cwd());
resolve: { return {
alias: [ base: process.env.NODE_ENV === 'production' ? '/' : '/',
// 国际化替换 root: process.cwd(),
{ resolve: {
find: 'vue-i18n', alias: [
replacement: 'vue-i18n/dist/vue-i18n.cjs.js', // 国际化替换
}, {
// 绝对路径重命名:/@/xxxx => src/xxxx find: 'vue-i18n',
{ replacement: 'vue-i18n/dist/vue-i18n.cjs.js',
find: /\/@\//, },
replacement: pathResolve('src') + '/', // 绝对路径重命名:/@/xxxx => src/xxxx
}, {
{ find: /\/@\//,
find: /^~/, replacement: pathResolve('src') + '/',
replacement: '', },
}, {
], find: /^~/,
}, replacement: '',
server: { },
host: '0.0.0.0', ],
port: 8081, },
server: { server: {
proxy: { host: '0.0.0.0',
// 代理路径 port: 8081,
'/': { server: {
target: 'http://127.0.0.1:1024/', // 目标服务器地址 proxy: {
changeOrigin: true, // 是否修改请求头中的 Origin 字段 // 代理路径
rewrite: (path) => path, // 重写路径 '/': {
}, target: env.VITE_APP_API_URL, // 目标服务器地址
}, changeOrigin: true, // 是否修改请求头中的 Origin 字段
} rewrite: (path) => path, // 重写路径
}, },
plugins: [vue()],
optimizeDeps: {
include: ['ant-design-vue/es/locale/zh_CN', 'dayjs/locale/zh-cn', 'ant-design-vue/es/locale/en_US'],
exclude: ['vue-demi'],
},
build: {
// 清除console和debugger
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
rollupOptions: {
output: {
//配置这个是让不同类型文件放在不同文件夹,不会显得太乱
chunkFileNames: 'js/[name]-[hash].js',
entryFileNames: 'js/[name]-[hash].js',
assetFileNames: '[ext]/[name]-[hash].[ext]',
manualChunks(id) {
//静态资源分拆打包
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
}, },
}, },
}, },
target: 'esnext', plugins: [vue()],
outDir: 'dist', // 指定输出路径 optimizeDeps: {
assetsDir: 'assets', // 指定生成静态文件目录 include: ['ant-design-vue/es/locale/zh_CN', 'dayjs/locale/zh-cn', 'ant-design-vue/es/locale/en_US'],
assetsInlineLimit: '4096', // 小于此阈值的导入或引用资源将内联为 base64 编码 exclude: ['vue-demi'],
chunkSizeWarningLimit: 500, // chunk 大小警告的限制 },
minify: 'terser', // 混淆器terser构建后文件体积更小 build: {
emptyOutDir: true, //打包前先清空原有打包文件 // 清除console和debugger
}, terserOptions: {
css: { compress: {
preprocessorOptions: { drop_console: true,
less: { drop_debugger: true,
modifyVars: customVariables, },
javascriptEnabled: true, },
rollupOptions: {
output: {
//配置这个是让不同类型文件放在不同文件夹,不会显得太乱
chunkFileNames: 'js/[name]-[hash].js',
entryFileNames: 'js/[name]-[hash].js',
assetFileNames: '[ext]/[name]-[hash].[ext]',
manualChunks(id) {
//静态资源分拆打包
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
},
},
},
target: 'esnext',
outDir: 'dist', // 指定输出路径
assetsDir: 'assets', // 指定生成静态文件目录
assetsInlineLimit: '4096', // 小于此阈值的导入或引用资源将内联为 base64 编码
chunkSizeWarningLimit: 500, // chunk 大小警告的限制
minify: 'terser', // 混淆器terser构建后文件体积更小
emptyOutDir: true, //打包前先清空原有打包文件
},
css: {
preprocessorOptions: {
less: {
modifyVars: customVariables,
javascriptEnabled: true,
},
}, },
}, },
}, define: {
define: { __INTLIFY_PROD_DEVTOOLS__: false,
__INTLIFY_PROD_DEVTOOLS__: false, 'process.env': process.env,
'process.env': process.env, },
}, };
}; };

View File

@@ -17,14 +17,14 @@ module.exports = {
ecmaVersion: 12, // 默认情况下ESLint使用的是ECMAScript5语法此处我们设置的选项是 es12 ecmaVersion: 12, // 默认情况下ESLint使用的是ECMAScript5语法此处我们设置的选项是 es12
sourceType: 'module', // 指定js导入的方式 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: { globals: {
defineProps: 'readonly', defineProps: 'readonly',
defineEmits: 'readonly', defineEmits: 'readonly',
defineExpose: 'readonly', defineExpose: 'readonly',
withDefaults: 'readonly', withDefaults: 'readonly',
}, },
plugins: ['vue'], plugins: ['vue', 'prettier'],
rules: { rules: {
'no-unused-vars': [ 'no-unused-vars': [
'error', 'error',
@@ -62,5 +62,6 @@ module.exports = {
], ],
// Enable vue/script-setup-uses-vars rule // Enable vue/script-setup-uses-vars rule
'vue/script-setup-uses-vars': 'error', 'vue/script-setup-uses-vars': 'error',
'prettier/prettier': 'error',
}, },
}; };

View File

@@ -6,12 +6,16 @@
* @LastEditors: zhuoda * @LastEditors: zhuoda
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" id="htmlRoot">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8"/>
<link rel="icon" href="/favicon.ico"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="renderer" content="webkit"/>
<title> %VITE_APP_TITLE%</title> <meta name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/>
<title> %VITE_APP_TITLE%</title>
<link rel="icon" href="/favicon.ico"/>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View File

@@ -24,7 +24,7 @@
"axios": "1.6.8", "axios": "1.6.8",
"clipboard": "2.0.11", "clipboard": "2.0.11",
"crypto-js": "4.1.1", "crypto-js": "4.1.1",
"dayjs": "1.11.13", "dayjs": "1.10.5",
"decimal.js": "10.3.1", "decimal.js": "10.3.1",
"default-passive-events": "^2.0.0", "default-passive-events": "^2.0.0",
"diff": "5.2.0", "diff": "5.2.0",

View File

@@ -49,7 +49,7 @@
import { useAppConfigStore } from '/@/store/modules/system/app-config'; import { useAppConfigStore } from '/@/store/modules/system/app-config';
import { useSpinStore } from '/@/store/modules/system/spin'; import { useSpinStore } from '/@/store/modules/system/spin';
import { Popover, theme } from 'ant-design-vue'; 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'; import SmartCopyIcon from '/@/components/framework/smart-copy-icon/index.vue';
const antdLocale = computed(() => messages[useAppConfigStore().language].antdLocale); const antdLocale = computed(() => messages[useAppConfigStore().language].antdLocale);

View File

@@ -29,7 +29,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
const props = defineProps({ const props = defineProps({
value: [Array, String, Number], value: [Array, String, Number],

View File

@@ -1,16 +1,46 @@
<template> <template>
<span>{{ dataLabels }}</span> <template v-if="props.showStyle">
<template v-for="(item, index) in dataList" :key="item.dictDataId">
<span v-if="item.color" :style="{ color: token[item.color] }"> {{ item.dataLabel }} </span>
<span v-else>{{ item.dataLabel }}</span>
{{ index < dataList.length - 1 ? ',' : '' }}
</template>
</template>
<!--<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>Ե<EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD>ʾ-->
<template v-else>
<span>{{ dataList }}</span>
</template>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
import { theme } from 'ant-design-vue';
import { DICT_DATA_STYLE_ENUM } from '/@/constants/support/dict-const';
const props = defineProps({ const props = defineProps({
dictCode: String, dictCode: String,
dataValue: [String, Number], dataValue: [String, Number],
showStyle: { type: Boolean, default: false },
}); });
const dataLabels = computed(() => {
return useDictStore().getDataLabels(props.dictCode, props.dataValue); const dataList = computed(() => {
if (!props.showStyle) {
return useDictStore().getDataLabels(props.dictCode, props.dataValue);
}
let dictDataList = useDictStore().getDataList(props.dictCode, props.dataValue);
let dataList = [];
for (const item of dictDataList) {
if (item.dataStyle) {
dataList.push(Object.assign({}, item, { color: DICT_DATA_STYLE_ENUM[item.dataStyle.toUpperCase()].color }));
} else {
dataList.push(Object.assign({}, item));
}
}
return dataList;
}); });
const { useToken } = theme;
const { token } = useToken();
</script> </script>

View File

@@ -29,7 +29,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
const props = defineProps({ const props = defineProps({
dictCode: String, dictCode: String,

View File

@@ -43,7 +43,7 @@
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { mergeColumn } from './smart-table-column-merge'; import { mergeColumn } from './smart-table-column-merge';
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { useAppConfigStore } from '/@/store/modules/system/app-config.js'; import { useAppConfigStore } from '/@/store/modules/system/app-config';
const props = defineProps({ const props = defineProps({
// 表格列数组 // 表格列数组

View File

@@ -26,7 +26,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, watch } from 'vue'; import { onMounted, ref, watch } from 'vue';
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import { positionApi } from '/@/api/system/position-api.js'; import { positionApi } from '/@/api/system/position-api';
// =========== 属性定义 和 事件方法暴露 ============= // =========== 属性定义 和 事件方法暴露 =============

View File

@@ -21,6 +21,7 @@ import message from './business/message/message-const';
import codeGeneratorConst from './support/code-generator-const'; import codeGeneratorConst from './support/code-generator-const';
import changeLogConst from './support/change-log-const'; import changeLogConst from './support/change-log-const';
import jobConst from './support/job-const'; import jobConst from './support/job-const';
import dictConst from './support/dict-const';
export default { export default {
FLAG_NUMBER_ENUM, FLAG_NUMBER_ENUM,
@@ -39,4 +40,5 @@ export default {
...codeGeneratorConst, ...codeGeneratorConst,
...changeLogConst, ...changeLogConst,
...jobConst, ...jobConst,
...dictConst,
}; };

View File

@@ -16,6 +16,40 @@ export const DICT_CODE_ENUM = {
GOODS_PLACE: 'GOODS_PLACE', GOODS_PLACE: 'GOODS_PLACE',
}; };
export const DICT_DATA_STYLE_ENUM = {
DEFAULT: {
value: 'default',
desc: '默认',
color: 'colorText',
},
PRIMARY: {
value: 'primary',
desc: '主要',
color: 'colorPrimary',
},
SUCCESS: {
value: 'success',
desc: '成功',
color: 'colorSuccess',
},
INFO: {
value: 'info',
desc: '信息',
color: 'colorInfo',
},
WARN: {
value: 'warn',
desc: '警告',
color: 'colorWarning',
},
DANGER: {
value: 'danger',
desc: '危险',
color: 'colorError',
},
};
export default { export default {
DICT_CODE_ENUM, DICT_CODE_ENUM,
DICT_DATA_STYLE_ENUM,
}; };

View File

@@ -16,10 +16,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import Password from '/@/views/system/account/components/password/index.vue'; import Password from '/@/views/system/account/components/password/index.vue';
import { useUserStore } from '/@/store/modules/system/user.js'; import { useUserStore } from '/@/store/modules/system/user';
import { loginApi } from '/@/api/system/login-api.js'; import { loginApi } from '/@/api/system/login-api';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
import { SmartLoading } from '/@/components/framework/smart-loading/index.js'; import { SmartLoading } from '/@/components/framework/smart-loading/index';
/** /**
* 修改密码弹窗 * 修改密码弹窗

View File

@@ -40,7 +40,7 @@
import { smartSentry } from '/@/lib/smart-sentry'; import { smartSentry } from '/@/lib/smart-sentry';
import HeaderResetPassword from './header-reset-password-modal/index.vue'; import HeaderResetPassword from './header-reset-password-modal/index.vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { ACCOUNT_MENU } from '/@/views/system/account/account-menu.js'; import { ACCOUNT_MENU } from '/@/views/system/account/account-menu';
// 头像背景颜色 // 头像背景颜色
const AVATAR_BACKGROUND_COLOR_ARRAY = ['#87d068', '#00B853', '#f56a00', '#1890ff']; const AVATAR_BACKGROUND_COLOR_ARRAY = ['#87d068', '#00B853', '#f56a00', '#1890ff'];

View File

@@ -17,7 +17,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
import { messageApi } from '/@/api/support/message-api.js'; import { messageApi } from '/@/api/support/message-api';
const emit = defineEmits(['refresh']); const emit = defineEmits(['refresh']);

View File

@@ -74,9 +74,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { BellOutlined } from '@ant-design/icons-vue'; import { BellOutlined } from '@ant-design/icons-vue';
import { useUserStore } from '/@/store/modules/system/user.js'; import { useUserStore } from '/@/store/modules/system/user';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
import { messageApi } from '/@/api/support/message-api.js'; import { messageApi } from '/@/api/support/message-api';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { theme } from 'ant-design-vue'; import { theme } from 'ant-design-vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';

View File

@@ -137,7 +137,7 @@
import { useAppConfigStore } from '/@/store/modules/system/app-config'; import { useAppConfigStore } from '/@/store/modules/system/app-config';
import { Modal } from 'ant-design-vue'; import { Modal } from 'ant-design-vue';
import { appDefaultConfig } from '/@/config/app-config'; import { appDefaultConfig } from '/@/config/app-config';
import { themeColors } from '/@/theme/color.js'; import { themeColors } from '/@/theme/color';
// ----------------- modal 显示与隐藏 ----------------- // ----------------- modal 显示与隐藏 -----------------

View File

@@ -21,7 +21,7 @@
import DefaultTab from './components/default-tab.vue'; import DefaultTab from './components/default-tab.vue';
import AntdTab from './components/antd-tab.vue'; import AntdTab from './components/antd-tab.vue';
import ChromeTab from './components/chrome-tab.vue'; import ChromeTab from './components/chrome-tab.vue';
import { PAGE_TAG_ENUM } from '/@/constants/layout-const.js'; import { PAGE_TAG_ENUM } from '/@/constants/layout-const';
import { theme } from 'ant-design-vue'; import { theme } from 'ant-design-vue';
const pageTagStyle = computed(() => useAppConfigStore().$state.pageTagStyle); const pageTagStyle = computed(() => useAppConfigStore().$state.pageTagStyle);

View File

@@ -104,7 +104,7 @@
import SideHelpDoc from './components/side-help-doc/index.vue'; import SideHelpDoc from './components/side-help-doc/index.vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const.js'; import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const';
import { theme as antDesignTheme } from 'ant-design-vue'; import { theme as antDesignTheme } from 'ant-design-vue';
const appConfigStore = useAppConfigStore(); const appConfigStore = useAppConfigStore();

View File

@@ -112,7 +112,7 @@
import SideHelpDoc from './components/side-help-doc/index.vue'; import SideHelpDoc from './components/side-help-doc/index.vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const.js'; import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const';
import { theme as antDesignTheme } from 'ant-design-vue'; import { theme as antDesignTheme } from 'ant-design-vue';
const appConfigStore = useAppConfigStore(); const appConfigStore = useAppConfigStore();

View File

@@ -62,7 +62,7 @@
import { useUserStore } from '/@/store/modules/system/user'; import { useUserStore } from '/@/store/modules/system/user';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const.js'; import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const';
import MenuLocationBreadcrumb from './components/menu-location-breadcrumb/index.vue'; import MenuLocationBreadcrumb from './components/menu-location-breadcrumb/index.vue';
import { theme as antDesignTheme } from 'ant-design-vue'; import { theme as antDesignTheme } from 'ant-design-vue';

View File

@@ -14,7 +14,7 @@ import { useUserStore } from '/@/store/modules/system/user';
import { decryptData, encryptData } from './encrypt'; import { decryptData, encryptData } from './encrypt';
import { DATA_TYPE_ENUM } from '../constants/common-const'; import { DATA_TYPE_ENUM } from '../constants/common-const';
import _ from 'lodash'; import _ from 'lodash';
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; import LocalStorageKeyConst from '/@/constants/local-storage-key-const';
// token的消息头 // token的消息头
const TOKEN_HEADER = 'Authorization'; const TOKEN_HEADER = 'Authorization';

View File

@@ -28,11 +28,11 @@ import { store } from '/@/store';
import { useUserStore } from '/@/store/modules/system/user'; import { useUserStore } from '/@/store/modules/system/user';
import 'ant-design-vue/dist/reset.css'; import 'ant-design-vue/dist/reset.css';
import '/@/theme/index.less'; import '/@/theme/index.less';
import { localRead } from '/@/utils/local-util.js'; import { localRead } from '/@/utils/local-util';
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; import LocalStorageKeyConst from '/@/constants/local-storage-key-const';
import '/@/utils/ployfill'; import '/@/utils/ployfill';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
import { dictApi } from '/@/api/support/dict-api.js'; import { dictApi } from '/@/api/support/dict-api';
/* /*
* -------------------- ※ 着重 解释说明下main.js的初始化逻辑 begin ※ -------------------- * -------------------- ※ 着重 解释说明下main.js的初始化逻辑 begin ※ --------------------

View File

@@ -8,7 +8,7 @@
* @Email: lab1024@163.com * @Email: lab1024@163.com
* @Copyright 1024创新实验室 https://1024lab.net Since 2012 * @Copyright 1024创新实验室 https://1024lab.net Since 2012
*/ */
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict';
export default { export default {
install: (app) => { install: (app) => {

View File

@@ -18,7 +18,7 @@ import SmartLayout from '../layout/index.vue';
import { useUserStore } from '/@/store/modules/system/user'; import { useUserStore } from '/@/store/modules/system/user';
import { localClear, localRead } from '/@/utils/local-util'; import { localClear, localRead } from '/@/utils/local-util';
import _ from 'lodash'; import _ from 'lodash';
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; import LocalStorageKeyConst from '/@/constants/local-storage-key-const';
export const router = createRouter({ export const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),

View File

@@ -1,8 +1,8 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { DICT_SPLIT } from '/@/constants/support/dict-const.js'; import { DICT_SPLIT } from '/@/constants/support/dict-const';
import _ from 'lodash'; import _ from 'lodash';
import { dictApi } from '/@/api/support/dict-api.js'; import { dictApi } from '/@/api/support/dict-api';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
export const useDictStore = defineStore({ export const useDictStore = defineStore({
id: 'dict', id: 'dict',
@@ -26,6 +26,34 @@ export const useDictStore = defineStore({
return dictDataList ? dictDataList : []; return dictDataList ? dictDataList : [];
}, },
// 获取字典的值名称
getDataList(dictCode, dataValue) {
if (_.isNil(dataValue) || _.isNaN(dataValue)) {
return '';
}
let dict = this.getDictData(dictCode);
if (dict.length === 0) {
return '';
}
// 是数字的话,需要特殊处理
if (_.isNumber(dataValue)) {
let target = _.find(dict, { dataValue: String(dataValue) });
return target ? target.dataLabel : '';
}
let valueArray = dataValue.split(DICT_SPLIT);
let result = [];
for (let item of valueArray) {
let target = _.find(dict, { dataValue: item });
if (target) {
result.push(target);
}
}
return result;
},
// 获取字典的值名称 // 获取字典的值名称
getDataLabels(dictCode, dataValue) { getDataLabels(dictCode, dataValue) {
if (_.isNil(dataValue) || _.isNaN(dataValue)) { if (_.isNil(dataValue) || _.isNaN(dataValue)) {

View File

@@ -8,6 +8,7 @@
* @Copyright 1024创新实验室 https://1024lab.net Since 2012 * @Copyright 1024创新实验室 https://1024lab.net Since 2012
*/ */
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { smartSentry } from '/@/lib/smart-sentry';
export const useSpinStore = defineStore({ export const useSpinStore = defineStore({
id: 'spin', id: 'spin',
@@ -18,13 +19,27 @@ export const useSpinStore = defineStore({
actions: { actions: {
hide() { hide() {
this.loading = false; this.loading = false;
let spins = document.querySelector('.ant-spin-nested-loading'); // 安全的DOM操作避免null引用错误
spins.style.zIndex = 999; try {
const spins = document.querySelector('.ant-spin-nested-loading');
if (spins) {
spins.style.zIndex = '999';
}
} catch (error) {
smartSentry.captureError('Spin hide操作失败:', error);
}
}, },
show() { show() {
this.loading = true; this.loading = true;
let spins = document.querySelector('.ant-spin-nested-loading'); // 安全的DOM操作避免null引用错误
spins.style.zIndex = 1001; try {
const spins = document.querySelector('.ant-spin-nested-loading');
if (spins) {
spins.style.zIndex = '1001';
}
} catch (error) {
smartSentry.captureError('Spin hide操作失败:', error);
}
}, },
}, },
}); });

View File

@@ -12,8 +12,8 @@ import { defineStore } from 'pinia';
import localKey from '/@/constants/local-storage-key-const'; import localKey from '/@/constants/local-storage-key-const';
import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
import { MENU_TYPE_ENUM } from '/@/constants/system/menu-const'; import { MENU_TYPE_ENUM } from '/@/constants/system/menu-const';
import { messageApi } from '/@/api/support/message-api.js'; import { messageApi } from '/@/api/support/message-api';
import { smartSentry } from '/@/lib/smart-sentry.js'; import { smartSentry } from '/@/lib/smart-sentry';
import { localRead, localSave, localRemove } from '/@/utils/local-util'; import { localRead, localSave, localRemove } from '/@/utils/local-util';

Some files were not shown because too many files have changed in this diff Show More