mirror of
https://github.com/continew-org/continew-admin.git
synced 2025-09-13 14:57:16 +08:00
refactor: 💥 项目包结构 top.charles7c.cnadmin => top.charles7c.continew.admin
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 数据权限注解
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/3/6 23:34
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface DataPermission {
|
||||
|
||||
/**
|
||||
* 表别名
|
||||
*/
|
||||
String value() default "";
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.base;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
|
||||
import top.charles7c.continew.admin.common.annotation.DataPermission;
|
||||
import top.charles7c.continew.starter.extension.crud.base.BaseMapper;
|
||||
|
||||
/**
|
||||
* 数据权限 Mapper 基类
|
||||
*
|
||||
* @param <T>
|
||||
* 实体类
|
||||
* @author Charles7c
|
||||
* @since 2023/9/3 21:50
|
||||
*/
|
||||
public interface DataPermissionMapper<T> extends BaseMapper<T> {
|
||||
|
||||
@Override
|
||||
@DataPermission
|
||||
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
|
||||
|
||||
@Override
|
||||
@DataPermission
|
||||
List<T> selectList(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.boot.autoconfigure.cache.CacheProperties;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.interceptor.KeyGenerator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||
import org.springframework.data.redis.serializer.*;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
|
||||
/**
|
||||
* Spring Cache 配置
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/28 23:17
|
||||
*/
|
||||
@Slf4j
|
||||
@EnableCaching
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class SpringCacheConfiguration extends CachingConfigurerSupport {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* 解决 Spring Cache(@Cacheable)缓存乱码问题
|
||||
*/
|
||||
@Bean
|
||||
public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
|
||||
ObjectMapper objectMapperCopy = objectMapper.copy();
|
||||
objectMapperCopy.activateDefaultTyping(objectMapperCopy.getPolymorphicTypeValidator(),
|
||||
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
|
||||
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
|
||||
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
|
||||
.serializeValuesWith(RedisSerializationContext.SerializationPair
|
||||
.fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapperCopy)));
|
||||
CacheProperties.Redis redisCacheProperties = cacheProperties.getRedis();
|
||||
if (null != redisCacheProperties.getTimeToLive()) {
|
||||
redisCacheConfiguration = redisCacheConfiguration.entryTtl(redisCacheProperties.getTimeToLive());
|
||||
}
|
||||
if (!redisCacheProperties.isCacheNullValues()) {
|
||||
redisCacheConfiguration = redisCacheConfiguration.disableCachingNullValues();
|
||||
}
|
||||
return redisCacheConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义缓存 key 生成策略(如果 @Cacheable 不指定 key,则默认使用该策略)
|
||||
*/
|
||||
@Bean
|
||||
@Override
|
||||
public KeyGenerator keyGenerator() {
|
||||
return (target, method, params) -> {
|
||||
String key = StrUtil.toUnderlineCase(method.getName()).toUpperCase();
|
||||
Map<String, Object> paramMap = MapUtil.newHashMap(params.length);
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
paramMap.put(String.valueOf(i), params[i]);
|
||||
}
|
||||
return String.format("%s:%s", key, DigestUtil.sha256Hex(JSONUtil.toJsonStr(paramMap)));
|
||||
};
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import top.charles7c.continew.admin.common.config.properties.LocalStorageProperties;
|
||||
import top.charles7c.continew.starter.core.constant.StringConstants;
|
||||
|
||||
/**
|
||||
* Web MVC 配置
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/11 19:40
|
||||
*/
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class WebMvcConfiguration implements WebMvcConfigurer {
|
||||
|
||||
private final LocalStorageProperties localStorageProperties;
|
||||
private final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;
|
||||
|
||||
/**
|
||||
* 静态资源处理器配置
|
||||
*/
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
LocalStorageProperties.LocalStoragePath path = localStorageProperties.getPath();
|
||||
String avatarUtl = "file:" + path.getAvatar().replace(StringConstants.BACKSLASH, StringConstants.SLASH);
|
||||
String fileUrl = "file:" + path.getFile().replace(StringConstants.BACKSLASH, StringConstants.SLASH);
|
||||
registry.addResourceHandler(localStorageProperties.getFilePattern()).addResourceLocations(fileUrl)
|
||||
.setCachePeriod(0);
|
||||
registry.addResourceHandler(localStorageProperties.getAvatarPattern()).addResourceLocations(avatarUtl)
|
||||
.setCachePeriod(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解决 Jackson2ObjectMapperBuilderCustomizer 配置不生效的问题
|
||||
* <p>
|
||||
* MappingJackson2HttpMessageConverter 对象在程序启动时创建了多个,移除多余的,保证只有一个
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
// 自定义 converters 时,需要手动在最前面添加 ByteArrayHttpMessageConverter
|
||||
// 否则 Spring Doc OpenAPI 的 /*/api-docs/**(例如:/v3/api-docs/default)接口响应内容会变为 Base64 编码后的内容,最终导致接口文档解析失败
|
||||
// 详情请参阅:https://github.com/springdoc/springdoc-openapi/issues/2143
|
||||
converters.add(new ByteArrayHttpMessageConverter());
|
||||
converters.removeIf(MappingJackson2HttpMessageConverter.class::isInstance);
|
||||
if (Objects.isNull(mappingJackson2HttpMessageConverter)) {
|
||||
converters.add(new MappingJackson2HttpMessageConverter());
|
||||
} else {
|
||||
converters.add(mappingJackson2HttpMessageConverter);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.easyexcel;
|
||||
|
||||
import com.alibaba.excel.converters.Converter;
|
||||
import com.alibaba.excel.enums.CellDataTypeEnum;
|
||||
import com.alibaba.excel.metadata.GlobalConfiguration;
|
||||
import com.alibaba.excel.metadata.data.ReadCellData;
|
||||
import com.alibaba.excel.metadata.data.WriteCellData;
|
||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
|
||||
import top.charles7c.continew.starter.core.constant.StringConstants;
|
||||
import top.charles7c.continew.starter.extension.crud.base.IBaseEnum;
|
||||
|
||||
/**
|
||||
* Easy Excel 枚举基类转换器
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/5 19:29
|
||||
*/
|
||||
public class ExcelBaseEnumConverter implements Converter<IBaseEnum<Integer>> {
|
||||
|
||||
@Override
|
||||
public Class<IBaseEnum> supportJavaTypeKey() {
|
||||
return IBaseEnum.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellDataTypeEnum supportExcelTypeKey() {
|
||||
return CellDataTypeEnum.STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 Java 数据(读取 Excel)
|
||||
*/
|
||||
@Override
|
||||
public IBaseEnum convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
|
||||
GlobalConfiguration globalConfiguration) {
|
||||
return this.getEnum(IBaseEnum.class, Convert.toStr(cellData.getData()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 Excel 数据(写入 Excel)
|
||||
*/
|
||||
@Override
|
||||
public WriteCellData<String> convertToExcelData(IBaseEnum<Integer> value, ExcelContentProperty contentProperty,
|
||||
GlobalConfiguration globalConfiguration) {
|
||||
if (null == value) {
|
||||
return new WriteCellData<>(StringConstants.EMPTY);
|
||||
}
|
||||
return new WriteCellData<>(value.getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 value 获取枚举对象,获取不到时为 {@code null}
|
||||
*
|
||||
* @param enumType
|
||||
* 枚举类型
|
||||
* @param description
|
||||
* 描述
|
||||
* @return 对应枚举 ,获取不到时为 {@code null}
|
||||
*/
|
||||
private IBaseEnum<Integer> getEnum(Class<?> enumType, String description) {
|
||||
Object[] enumConstants = enumType.getEnumConstants();
|
||||
for (Object enumConstant : enumConstants) {
|
||||
if (ClassUtil.isAssignable(IBaseEnum.class, enumType)) {
|
||||
IBaseEnum<Integer> baseEnum = (IBaseEnum<Integer>)enumConstant;
|
||||
if (baseEnum.getDescription().equals(description)) {
|
||||
return baseEnum;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.jackson;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import com.fasterxml.jackson.core.*;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
|
||||
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
|
||||
import top.charles7c.continew.starter.extension.crud.base.IBaseEnum;
|
||||
|
||||
/**
|
||||
* 通用枚举基类 BaseEnum 反序列化器
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/8 13:56
|
||||
*/
|
||||
@JacksonStdImpl
|
||||
public class BaseEnumDeserializer extends JsonDeserializer<IBaseEnum> {
|
||||
|
||||
/** 静态实例 */
|
||||
public static final BaseEnumDeserializer SERIALIZER_INSTANCE = new BaseEnumDeserializer();
|
||||
|
||||
@Override
|
||||
public IBaseEnum deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
|
||||
throws IOException {
|
||||
Class<?> targetClass = jsonParser.getCurrentValue().getClass();
|
||||
String fieldName = jsonParser.getCurrentName();
|
||||
String value = jsonParser.getText();
|
||||
return this.getEnum(targetClass, value, fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过某字段对应值获取枚举实例,获取不到时为 {@code null}
|
||||
*
|
||||
* @param targetClass
|
||||
* 目标类型
|
||||
* @param value
|
||||
* 字段值
|
||||
* @param fieldName
|
||||
* 字段名
|
||||
* @return 对应枚举实例 ,获取不到时为 {@code null}
|
||||
*/
|
||||
private IBaseEnum getEnum(Class<?> targetClass, String value, String fieldName) {
|
||||
Field field = ReflectUtil.getField(targetClass, fieldName);
|
||||
Class<?> fieldTypeClass = field.getType();
|
||||
Object[] enumConstants = fieldTypeClass.getEnumConstants();
|
||||
for (Object enumConstant : enumConstants) {
|
||||
if (ClassUtil.isAssignable(IBaseEnum.class, fieldTypeClass)) {
|
||||
IBaseEnum baseEnum = (IBaseEnum)enumConstant;
|
||||
if (baseEnum.getValue().equals(Integer.valueOf(value))) {
|
||||
return baseEnum;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.jackson;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
|
||||
|
||||
import top.charles7c.continew.starter.extension.crud.base.IBaseEnum;
|
||||
|
||||
/**
|
||||
* 通用枚举接口 BaseEnum 序列化器
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/8 13:56
|
||||
*/
|
||||
@JacksonStdImpl
|
||||
public class BaseEnumSerializer extends JsonSerializer<IBaseEnum> {
|
||||
|
||||
/** 静态实例 */
|
||||
public static final BaseEnumSerializer SERIALIZER_INSTANCE = new BaseEnumSerializer();
|
||||
|
||||
@Override
|
||||
public void serialize(IBaseEnum value, JsonGenerator generator, SerializerProvider serializers) throws IOException {
|
||||
generator.writeObject(value.getValue());
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.jackson;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
|
||||
import top.charles7c.continew.starter.extension.crud.base.IBaseEnum;
|
||||
|
||||
/**
|
||||
* Jackson 配置
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/11 13:23
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class JacksonConfiguration {
|
||||
|
||||
/**
|
||||
* 针对枚举基类 BaseEnum 的序列化和反序列化
|
||||
*/
|
||||
@Bean
|
||||
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
|
||||
SimpleModule simpleModule = new SimpleModule();
|
||||
simpleModule.addSerializer(IBaseEnum.class, BaseEnumSerializer.SERIALIZER_INSTANCE);
|
||||
|
||||
SimpleDeserializersWrapper deserializers = new SimpleDeserializersWrapper();
|
||||
deserializers.addDeserializer(IBaseEnum.class, BaseEnumDeserializer.SERIALIZER_INSTANCE);
|
||||
simpleModule.setDeserializers(deserializers);
|
||||
|
||||
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
|
||||
objectMapper.registerModule(simpleModule);
|
||||
return objectMapper;
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.jackson;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import com.fasterxml.jackson.databind.BeanDescription;
|
||||
import com.fasterxml.jackson.databind.DeserializationConfig;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
|
||||
import com.fasterxml.jackson.databind.type.ClassKey;
|
||||
|
||||
/**
|
||||
* 反序列化器包装类(重写 Jackson 反序列化枚举方法,参阅:FasterXML/jackson-databind#2842)
|
||||
*
|
||||
* <p>
|
||||
* 默认处理:<br>
|
||||
* 1. Jackson 会先查找指定枚举类型对应的反序列化器(例如:GenderEnum 枚举类型,则是找 GenderEnum 枚举类型的对应反序列化器);<br>
|
||||
* 2. 如果找不到则开始查找 Enum 类型(所有枚举父类)的反序列化器;<br>
|
||||
* 3. 如果都找不到则会采用默认的枚举反序列化器(它仅能根据枚举类型的 name、ordinal 来进行反序列化)。
|
||||
* </p>
|
||||
* <p>
|
||||
* 重写增强后:<br>
|
||||
* 1. 同默认 1;<br>
|
||||
* 2. 同默认 2;<br>
|
||||
* 3. 如果也找不到 Enum 类型(所有枚举父类)的反序列化器,开始查找指定枚举类型的接口的反序列化器(例如:GenderEnum 枚举类型,则是找它的接口 BaseEnum 的反序列化器);<br>
|
||||
* 4. 同默认 3。
|
||||
* </p>
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/8 13:28
|
||||
*/
|
||||
@Slf4j
|
||||
public class SimpleDeserializersWrapper extends SimpleDeserializers {
|
||||
|
||||
@Override
|
||||
public JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config,
|
||||
BeanDescription beanDesc) throws JsonMappingException {
|
||||
JsonDeserializer<?> deser = super.findEnumDeserializer(type, config, beanDesc);
|
||||
if (null != deser) {
|
||||
return deser;
|
||||
}
|
||||
|
||||
// 重写增强:开始查找指定枚举类型的接口的反序列化器(例如:GenderEnum 枚举类型,则是找它的接口 BaseEnum 的反序列化器)
|
||||
for (Class<?> typeInterface : type.getInterfaces()) {
|
||||
deser = this._classMappings.get(new ClassKey(typeInterface));
|
||||
if (null != deser) {
|
||||
return deser;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.mybatis;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
|
||||
|
||||
import top.charles7c.continew.admin.common.annotation.DataPermission;
|
||||
import top.charles7c.continew.admin.common.enums.DataScopeEnum;
|
||||
import top.charles7c.continew.admin.common.model.dto.LoginUser;
|
||||
import top.charles7c.continew.admin.common.model.dto.RoleDTO;
|
||||
import top.charles7c.continew.admin.common.util.helper.LoginHelper;
|
||||
import top.charles7c.continew.starter.core.constant.StringConstants;
|
||||
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.Function;
|
||||
import net.sf.jsqlparser.expression.LongValue;
|
||||
import net.sf.jsqlparser.expression.Parenthesis;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
|
||||
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
|
||||
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
|
||||
import net.sf.jsqlparser.expression.operators.relational.InExpression;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.schema.Table;
|
||||
import net.sf.jsqlparser.statement.select.PlainSelect;
|
||||
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
|
||||
import net.sf.jsqlparser.statement.select.SubSelect;
|
||||
|
||||
/**
|
||||
* 数据权限处理器实现
|
||||
* <p>
|
||||
* 来源:<a href="https://gitee.com/baomidou/mybatis-plus/issues/I37I90">DataPermissionInterceptor 如何使用?</a>
|
||||
* </p>
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/3/6 23:19
|
||||
*/
|
||||
@Slf4j
|
||||
public class DataPermissionHandlerImpl implements DataPermissionHandler {
|
||||
|
||||
/** ID */
|
||||
private static final String ID = "id";
|
||||
/** 部门 ID */
|
||||
private static final String DEPT_ID = "dept_id";
|
||||
/** 创建人 */
|
||||
private static final String CREATE_USER = "create_user";
|
||||
/** 部门表 */
|
||||
private static final String DEPT_TABLE = "sys_dept";
|
||||
/** 角色和部门关联表 */
|
||||
private static final String ROLE_DEPT_TABLE = "sys_role_dept";
|
||||
/** 角色和部门关联表:角色 ID */
|
||||
private static final String ROLE_ID = "role_id";
|
||||
|
||||
@Override
|
||||
public Expression getSqlSegment(Expression where, String mappedStatementId) {
|
||||
try {
|
||||
Class<?> clazz =
|
||||
Class.forName(mappedStatementId.substring(0, mappedStatementId.lastIndexOf(StringConstants.DOT)));
|
||||
String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(StringConstants.DOT) + 1);
|
||||
Method[] methodArr = clazz.getMethods();
|
||||
for (Method method : methodArr) {
|
||||
DataPermission dataPermission = method.getAnnotation(DataPermission.class);
|
||||
if (null != dataPermission
|
||||
&& (method.getName().equals(methodName) || (method.getName() + "_COUNT").equals(methodName))) {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
if (null != loginUser && !loginUser.isAdmin()) {
|
||||
return buildDataScopeFilter(loginUser, dataPermission.value(), where);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.error("Data permission handler build data scope filter occurred an error: {}.", e.getMessage(), e);
|
||||
}
|
||||
return where;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建数据范围过滤条件
|
||||
*
|
||||
* @param user
|
||||
* 当前登录用户
|
||||
* @param tableAlias
|
||||
* 表别名
|
||||
* @param where
|
||||
* 当前查询条件
|
||||
* @return 构建后查询条件
|
||||
*/
|
||||
private Expression buildDataScopeFilter(LoginUser user, String tableAlias, Expression where) {
|
||||
Expression expression = null;
|
||||
for (RoleDTO role : user.getRoles()) {
|
||||
DataScopeEnum dataScope = role.getDataScope();
|
||||
if (DataScopeEnum.ALL.equals(dataScope)) {
|
||||
return where;
|
||||
}
|
||||
if (DataScopeEnum.DEPT_AND_CHILD.equals(dataScope)) {
|
||||
// select t1.* from table as t1 where t1.`dept_id` in (select `id` from `sys_dept` where `id` = xxx or
|
||||
// find_in_set(xxx, `ancestors`));
|
||||
// 构建子查询
|
||||
SubSelect subSelect = new SubSelect();
|
||||
PlainSelect select = new PlainSelect();
|
||||
select.setSelectItems(Collections.singletonList(new SelectExpressionItem(new Column(ID))));
|
||||
select.setFromItem(new Table(DEPT_TABLE));
|
||||
EqualsTo equalsTo = new EqualsTo();
|
||||
equalsTo.setLeftExpression(new Column(ID));
|
||||
equalsTo.setRightExpression(new LongValue(user.getDeptId()));
|
||||
Function function = new Function();
|
||||
function.setName("find_in_set");
|
||||
function.setParameters(new ExpressionList(new LongValue(user.getDeptId()), new Column("ancestors")));
|
||||
select.setWhere(new OrExpression(equalsTo, function));
|
||||
subSelect.setSelectBody(select);
|
||||
// 构建父查询
|
||||
InExpression inExpression = new InExpression();
|
||||
inExpression.setLeftExpression(this.buildColumn(tableAlias, DEPT_ID));
|
||||
inExpression.setRightExpression(subSelect);
|
||||
expression = null != expression ? new OrExpression(expression, inExpression) : inExpression;
|
||||
} else if (DataScopeEnum.DEPT.equals(dataScope)) {
|
||||
// select t1.* from table as t1 where t1.`dept_id` = xxx;
|
||||
EqualsTo equalsTo = new EqualsTo();
|
||||
equalsTo.setLeftExpression(this.buildColumn(tableAlias, DEPT_ID));
|
||||
equalsTo.setRightExpression(new LongValue(user.getDeptId()));
|
||||
expression = null != expression ? new OrExpression(expression, equalsTo) : equalsTo;
|
||||
} else if (DataScopeEnum.SELF.equals(dataScope)) {
|
||||
// select t1.* from table as t1 where t1.`create_user` = xxx;
|
||||
EqualsTo equalsTo = new EqualsTo();
|
||||
equalsTo.setLeftExpression(this.buildColumn(tableAlias, CREATE_USER));
|
||||
equalsTo.setRightExpression(new LongValue(user.getId()));
|
||||
expression = null != expression ? new OrExpression(expression, equalsTo) : equalsTo;
|
||||
} else if (DataScopeEnum.CUSTOM.equals(dataScope)) {
|
||||
// select t1.* from table as t1 where t1.`dept_id` in (select `dept_id` from `sys_role_dept` where
|
||||
// `role_id` = xxx);
|
||||
// 构建子查询
|
||||
SubSelect subSelect = new SubSelect();
|
||||
PlainSelect select = new PlainSelect();
|
||||
select.setSelectItems(Collections.singletonList(new SelectExpressionItem(new Column(DEPT_ID))));
|
||||
select.setFromItem(new Table(ROLE_DEPT_TABLE));
|
||||
EqualsTo equalsTo = new EqualsTo();
|
||||
equalsTo.setLeftExpression(new Column(ROLE_ID));
|
||||
equalsTo.setRightExpression(new LongValue(role.getId()));
|
||||
select.setWhere(equalsTo);
|
||||
subSelect.setSelectBody(select);
|
||||
// 构建父查询
|
||||
InExpression inExpression = new InExpression();
|
||||
inExpression.setLeftExpression(this.buildColumn(tableAlias, DEPT_ID));
|
||||
inExpression.setRightExpression(subSelect);
|
||||
expression = null != expression ? new OrExpression(expression, inExpression) : inExpression;
|
||||
}
|
||||
}
|
||||
return null != where ? new AndExpression(where, new Parenthesis(expression)) : expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 Column
|
||||
*
|
||||
* @param tableAlias
|
||||
* 表别名
|
||||
* @param columnName
|
||||
* 字段名称
|
||||
* @return 带表别名字段
|
||||
*/
|
||||
private Column buildColumn(String tableAlias, String columnName) {
|
||||
if (StringUtils.isNotEmpty(tableAlias)) {
|
||||
columnName = String.format("%s.%s", tableAlias, columnName);
|
||||
}
|
||||
return new Column(columnName);
|
||||
}
|
||||
}
|
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.mybatis;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
|
||||
import top.charles7c.continew.admin.common.util.helper.LoginHelper;
|
||||
import top.charles7c.continew.starter.extension.crud.base.BaseDO;
|
||||
import top.charles7c.continew.starter.extension.crud.exception.BusinessException;
|
||||
|
||||
/**
|
||||
* MyBatis Plus 元对象处理器配置(插入或修改时自动填充)
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/22 19:52
|
||||
*/
|
||||
public class MyBatisPlusMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
/** 创建人 */
|
||||
private static final String CREATE_USER = "createUser";
|
||||
/** 创建时间 */
|
||||
private static final String CREATE_TIME = "createTime";
|
||||
/** 修改人 */
|
||||
private static final String UPDATE_USER = "updateUser";
|
||||
/** 修改时间 */
|
||||
private static final String UPDATE_TIME = "updateTime";
|
||||
|
||||
/**
|
||||
* 插入数据时填充
|
||||
*
|
||||
* @param metaObject
|
||||
* 元对象
|
||||
*/
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
try {
|
||||
if (null == metaObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
Long createUser = LoginHelper.getUserId();
|
||||
LocalDateTime createTime = LocalDateTime.now();
|
||||
if (metaObject.getOriginalObject() instanceof BaseDO baseDO) {
|
||||
// 继承了 BaseDO 的类,填充创建信息
|
||||
baseDO.setCreateUser(ObjectUtil.defaultIfNull(baseDO.getCreateUser(), createUser));
|
||||
baseDO.setCreateTime(ObjectUtil.defaultIfNull(baseDO.getCreateTime(), createTime));
|
||||
} else {
|
||||
// 未继承 BaseDO 的类,如存在创建信息则进行填充
|
||||
this.fillFieldValue(metaObject, CREATE_USER, createUser, false);
|
||||
this.fillFieldValue(metaObject, CREATE_TIME, createTime, false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException("插入数据时自动填充异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据时填充
|
||||
*
|
||||
* @param metaObject
|
||||
* 元对象
|
||||
*/
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
try {
|
||||
if (null == metaObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
Long updateUser = LoginHelper.getUserId();
|
||||
LocalDateTime updateTime = LocalDateTime.now();
|
||||
if (metaObject.getOriginalObject() instanceof BaseDO baseDO) {
|
||||
// 继承了 BaseDO 的类,填充修改信息
|
||||
baseDO.setUpdateUser(updateUser);
|
||||
baseDO.setUpdateTime(updateTime);
|
||||
} else {
|
||||
// 未继承 BaseDO 的类,根据类中拥有的修改信息进行填充,不存在修改信息不进行填充
|
||||
this.fillFieldValue(metaObject, UPDATE_USER, updateUser, true);
|
||||
this.fillFieldValue(metaObject, UPDATE_TIME, updateTime, true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException("修改数据时自动填充异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充字段值
|
||||
*
|
||||
* @param metaObject
|
||||
* 元数据对象
|
||||
* @param fieldName
|
||||
* 要填充的字段名
|
||||
* @param fillFieldValue
|
||||
* 要填充的字段值
|
||||
* @param isOverride
|
||||
* 如果字段值不为空,是否覆盖(true 覆盖、false 不覆盖)
|
||||
*/
|
||||
private void fillFieldValue(MetaObject metaObject, String fieldName, Object fillFieldValue, boolean isOverride) {
|
||||
if (metaObject.hasSetter(fieldName)) {
|
||||
Object fieldValue = metaObject.getValue(fieldName);
|
||||
setFieldValByName(fieldName, null != fieldValue && !isOverride ? fieldValue : fillFieldValue, metaObject);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.mybatis;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
|
||||
/**
|
||||
* MyBatis Plus 配置
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/22 19:51
|
||||
*/
|
||||
@Configuration
|
||||
public class MybatisPlusConfiguration {
|
||||
|
||||
/**
|
||||
* 元对象处理器配置(插入或修改时自动填充)
|
||||
*/
|
||||
@Bean
|
||||
public MetaObjectHandler metaObjectHandler() {
|
||||
return new MyBatisPlusMetaObjectHandler();
|
||||
}
|
||||
}
|
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.properties;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.wf.captcha.*;
|
||||
|
||||
/**
|
||||
* 验证码配置属性
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/11 13:35
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "captcha")
|
||||
public class CaptchaProperties {
|
||||
|
||||
/**
|
||||
* 图形验证码过期时间
|
||||
*/
|
||||
@Value("${captcha.graphic.expirationInMinutes}")
|
||||
private long expirationInMinutes;
|
||||
|
||||
/**
|
||||
* 邮箱验证码配置
|
||||
*/
|
||||
private CaptchaMail mail;
|
||||
|
||||
/**
|
||||
* 短信验证码配置
|
||||
*/
|
||||
private CaptchaSms sms;
|
||||
|
||||
/**
|
||||
* 邮箱验证码配置
|
||||
*/
|
||||
@Data
|
||||
public static class CaptchaMail {
|
||||
/**
|
||||
* 内容长度
|
||||
*/
|
||||
private int length;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private long expirationInMinutes;
|
||||
|
||||
/**
|
||||
* 限制时间
|
||||
*/
|
||||
private long limitInSeconds;
|
||||
|
||||
/**
|
||||
* 模板路径
|
||||
*/
|
||||
private String templatePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信验证码配置
|
||||
*/
|
||||
@Data
|
||||
public static class CaptchaSms {
|
||||
/**
|
||||
* 内容长度
|
||||
*/
|
||||
private int length;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private long expirationInMinutes;
|
||||
|
||||
/**
|
||||
* 限制时间
|
||||
*/
|
||||
private long limitInSeconds;
|
||||
|
||||
/**
|
||||
* 模板 ID
|
||||
*/
|
||||
private String templateId;
|
||||
}
|
||||
}
|
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import cn.hutool.system.OsInfo;
|
||||
import cn.hutool.system.SystemUtil;
|
||||
|
||||
/**
|
||||
* 本地存储配置属性
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/2 19:43
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "local-storage")
|
||||
public class LocalStorageProperties {
|
||||
|
||||
/** 文件模式 */
|
||||
private String filePattern;
|
||||
|
||||
/** 头像模式 */
|
||||
private String avatarPattern;
|
||||
|
||||
/** 文件大小限制 */
|
||||
private Long maxSizeInMb;
|
||||
|
||||
/** 头像大小限制 */
|
||||
private Long avatarMaxSizeInMb;
|
||||
|
||||
/** Windows 系统本地存储路径 */
|
||||
private LocalStoragePath windows;
|
||||
|
||||
/** Linux 系统本地存储路径 */
|
||||
private LocalStoragePath linux;
|
||||
|
||||
/** MAC 系统本地存储路径 */
|
||||
private LocalStoragePath mac;
|
||||
|
||||
/**
|
||||
* 获取存储路径
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public LocalStoragePath getPath() {
|
||||
OsInfo osInfo = SystemUtil.getOsInfo();
|
||||
if (osInfo.isWindows()) {
|
||||
return windows;
|
||||
}
|
||||
if (osInfo.isMac()) {
|
||||
return mac;
|
||||
}
|
||||
return linux;
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地存储路径
|
||||
*/
|
||||
@Data
|
||||
public static class LocalStoragePath {
|
||||
|
||||
/** 文件存储路径 */
|
||||
private String file;
|
||||
|
||||
/** 头像存储路径 */
|
||||
private String avatar;
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.config.properties;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
|
||||
/**
|
||||
* RSA 配置属性
|
||||
*
|
||||
* @author Zheng Jie(ELADMIN)
|
||||
* @author Charles7c
|
||||
* @since 2022/12/21 20:21
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class RsaProperties {
|
||||
|
||||
/** 私钥 */
|
||||
public static final String PRIVATE_KEY;
|
||||
|
||||
static {
|
||||
PRIVATE_KEY = SpringUtil.getProperty("rsa.privateKey");
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.constant;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 缓存相关常量
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/22 19:30
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class CacheConstants {
|
||||
|
||||
/**
|
||||
* 登录用户键
|
||||
*/
|
||||
public static final String LOGIN_USER_KEY = "LOGIN_USER";
|
||||
|
||||
/**
|
||||
* 验证码键前缀
|
||||
*/
|
||||
public static final String CAPTCHA_KEY_PREFIX = "CAPTCHA";
|
||||
|
||||
/**
|
||||
* 限流键前缀
|
||||
*/
|
||||
public static final String LIMIT_KEY_PREFIX = "LIMIT";
|
||||
|
||||
/**
|
||||
* 用户缓存键前缀
|
||||
*/
|
||||
public static final String USER_KEY_PREFIX = "USER";
|
||||
|
||||
/**
|
||||
* 菜单缓存键前缀
|
||||
*/
|
||||
public static final String MENU_KEY_PREFIX = "MENU";
|
||||
|
||||
/**
|
||||
* 字典缓存键前缀
|
||||
*/
|
||||
public static final String DICT_KEY_PREFIX = "DICT";
|
||||
|
||||
/**
|
||||
* 参数缓存键前缀
|
||||
*/
|
||||
public static final String OPTION_KEY_PREFIX = "OPTION";
|
||||
|
||||
/**
|
||||
* 仪表盘缓存键前缀
|
||||
*/
|
||||
public static final String DASHBOARD_KEY_PREFIX = "DASHBOARD";
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.constant;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 文件相关常量
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/2 21:19
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class FileConstants {
|
||||
|
||||
/**
|
||||
* 头像支持的图片类型
|
||||
*/
|
||||
public static final String[] AVATAR_SUPPORTED_IMG_TYPES = {"jpg", "png", "gif", "jpeg"};
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.constant;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import cn.hutool.core.lang.RegexPool;
|
||||
|
||||
/**
|
||||
* 正则相关常量
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/10 20:06
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class RegexConstants implements RegexPool {
|
||||
|
||||
/**
|
||||
* 用户名正则(长度为 4 到 64 位,可以包含字母、数字,下划线,以字母开头)
|
||||
*/
|
||||
public static final String USERNAME = "^[a-zA-Z][a-zA-Z0-9_]{3,64}$";
|
||||
|
||||
/**
|
||||
* 密码正则(长度为 6 到 32 位,可以包含字母、数字、下划线,特殊字符,同时包含字母和数字)
|
||||
*/
|
||||
public static final String PASSWORD = "^(?=.*\\d)(?=.*[a-z]).{6,32}$";
|
||||
|
||||
/**
|
||||
* 通用编码正则(长度为 2 到 30 位,可以包含字母、数字,下划线,以字母开头)
|
||||
*/
|
||||
public static final String GENERAL_CODE = "^[a-zA-Z][a-zA-Z0-9_]{1,29}$";
|
||||
|
||||
/**
|
||||
* 通用名称正则(长度为 2 到 30 位,可以包含中文、字母、数字、下划线,短横线)
|
||||
*/
|
||||
public static final String GENERAL_NAME = "^[\\u4e00-\\u9fa5a-zA-Z0-9_-]{2,30}$";
|
||||
|
||||
/**
|
||||
* 包名正则(可以包含大小写字母、数字、下划线,每一级包名不能以数字开头)
|
||||
*/
|
||||
public static final String PACKAGE_NAME = "^(?:[a-zA-Z_][a-zA-Z0-9_]*\\.)*[a-zA-Z_][a-zA-Z0-9_]*$";
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.constant;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import top.charles7c.continew.starter.core.constant.StringConstants;
|
||||
|
||||
/**
|
||||
* 系统相关常量
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/9 22:11
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class SysConstants {
|
||||
|
||||
/**
|
||||
* 管理员角色编码
|
||||
*/
|
||||
public static final String ADMIN_ROLE_CODE = "admin";
|
||||
|
||||
/**
|
||||
* 顶级部门 ID
|
||||
*/
|
||||
public static final Long SUPER_DEPT_ID = 1L;
|
||||
|
||||
/**
|
||||
* 顶级父 ID
|
||||
*/
|
||||
public static final Long SUPER_PARENT_ID = 0L;
|
||||
|
||||
/**
|
||||
* 全部权限标识
|
||||
*/
|
||||
public static final String ALL_PERMISSION = StringConstants.ASTERISK;
|
||||
|
||||
/**
|
||||
* 默认密码
|
||||
*/
|
||||
public static final String DEFAULT_PASSWORD = "123456";
|
||||
|
||||
/**
|
||||
* 登录 URI
|
||||
*/
|
||||
public static final String LOGIN_URI = "/auth/login";
|
||||
|
||||
/**
|
||||
* 退出 URI
|
||||
*/
|
||||
public static final String LOGOUT_URI = "/auth/logout";
|
||||
|
||||
/**
|
||||
* 描述类字段后缀
|
||||
*/
|
||||
public static final String DESCRIPTION_FIELD_SUFFIX = "String";
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.constant;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* UI 相关常量
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/9/17 14:12
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class UIConstants {
|
||||
|
||||
/**
|
||||
* 主色(极致蓝)
|
||||
*/
|
||||
public static final String COLOR_PRIMARY = "arcoblue";
|
||||
|
||||
/**
|
||||
* 成功色(仙野绿)
|
||||
*/
|
||||
public static final String COLOR_SUCCESS = "green";
|
||||
|
||||
/**
|
||||
* 警告色(活力橙)
|
||||
*/
|
||||
public static final String COLOR_WARNING = "orangered";
|
||||
|
||||
/**
|
||||
* 错误色(浪漫红)
|
||||
*/
|
||||
public static final String COLOR_ERROR = "red";
|
||||
|
||||
/**
|
||||
* 默认色(中性灰)
|
||||
*/
|
||||
public static final String COLOR_DEFAULT = "gray";
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import top.charles7c.continew.starter.extension.crud.base.IBaseEnum;
|
||||
|
||||
/**
|
||||
* 数据权限枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/8 22:58
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum DataScopeEnum implements IBaseEnum<Integer> {
|
||||
|
||||
/** 全部数据权限 */
|
||||
ALL(1, "全部数据权限"),
|
||||
|
||||
/** 本部门及以下数据权限 */
|
||||
DEPT_AND_CHILD(2, "本部门及以下数据权限"),
|
||||
|
||||
/** 本部门数据权限 */
|
||||
DEPT(3, "本部门数据权限"),
|
||||
|
||||
/** 仅本人数据权限 */
|
||||
SELF(4, "仅本人数据权限"),
|
||||
|
||||
/** 自定义数据权限 */
|
||||
CUSTOM(5, "自定义数据权限"),;
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import top.charles7c.continew.admin.common.constant.UIConstants;
|
||||
import top.charles7c.continew.starter.extension.crud.base.IBaseEnum;
|
||||
|
||||
/**
|
||||
* 启用/禁用状态枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum DisEnableStatusEnum implements IBaseEnum<Integer> {
|
||||
|
||||
/** 启用 */
|
||||
ENABLE(1, "启用", UIConstants.COLOR_SUCCESS),
|
||||
|
||||
/** 禁用 */
|
||||
DISABLE(2, "禁用", UIConstants.COLOR_ERROR),;
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
private final String color;
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import top.charles7c.continew.starter.extension.crud.base.IBaseEnum;
|
||||
|
||||
/**
|
||||
* 性别枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 21:59
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum GenderEnum implements IBaseEnum<Integer> {
|
||||
|
||||
/** 未知 */
|
||||
UNKNOWN(0, "未知"),
|
||||
|
||||
/** 男 */
|
||||
MALE(1, "男"),
|
||||
|
||||
/** 女 */
|
||||
FEMALE(2, "女"),;
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import top.charles7c.continew.starter.extension.crud.base.IBaseEnum;
|
||||
|
||||
/**
|
||||
* 菜单类型枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/15 20:12
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum MenuTypeEnum implements IBaseEnum<Integer> {
|
||||
|
||||
/** 目录 */
|
||||
DIR(1, "目录"),
|
||||
|
||||
/** 菜单 */
|
||||
MENU(2, "菜单"),
|
||||
|
||||
/** 按钮 */
|
||||
BUTTON(3, "按钮"),;
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import top.charles7c.continew.admin.common.constant.UIConstants;
|
||||
import top.charles7c.continew.starter.extension.crud.base.IBaseEnum;
|
||||
|
||||
/**
|
||||
* 消息类型枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/11/2 20:08
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum MessageTypeEnum implements IBaseEnum<Integer> {
|
||||
|
||||
/** 系统消息 */
|
||||
SYSTEM(1, "系统消息", UIConstants.COLOR_PRIMARY),;
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
private final String color;
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* 第三方账号平台枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/10/19 21:22
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum SocialSourceEnum {
|
||||
|
||||
/** 码云 */
|
||||
GITEE("码云"),
|
||||
|
||||
/** GitHub */
|
||||
GITHUB("GitHub"),;
|
||||
|
||||
private final String description;
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import top.charles7c.continew.admin.common.constant.UIConstants;
|
||||
import top.charles7c.continew.starter.extension.crud.base.IBaseEnum;
|
||||
|
||||
/**
|
||||
* 成功/失败状态枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/26 21:35
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum SuccessFailureStatusEnum implements IBaseEnum<Integer> {
|
||||
|
||||
/** 成功 */
|
||||
SUCCESS(1, "成功", UIConstants.COLOR_SUCCESS),
|
||||
|
||||
/** 失败 */
|
||||
FAILURE(2, "失败", UIConstants.COLOR_ERROR),;
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
private final String color;
|
||||
}
|
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.handler;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
import org.springframework.web.multipart.MaxUploadSizeExceededException;
|
||||
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.exception.NotPermissionException;
|
||||
import cn.dev33.satoken.exception.NotRoleException;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import top.charles7c.continew.admin.common.util.StreamUtils;
|
||||
import top.charles7c.continew.admin.common.util.holder.LogContextHolder;
|
||||
import top.charles7c.continew.starter.core.util.ExceptionUtils;
|
||||
import top.charles7c.continew.starter.extension.crud.exception.BadRequestException;
|
||||
import top.charles7c.continew.starter.extension.crud.exception.BusinessException;
|
||||
import top.charles7c.continew.starter.extension.crud.model.resp.R;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*
|
||||
* @author Charles7c
|
||||
* @author Lion Li(<a href="https://gitee.com/dromara/RuoYi-Vue-Plus">RuoYi-Vue-Plus</a>)
|
||||
* @since 2022/12/21 21:01
|
||||
*/
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
/**
|
||||
* 拦截自定义验证异常-错误请求
|
||||
*/
|
||||
@ExceptionHandler(BadRequestException.class)
|
||||
public R handleBadRequestException(BadRequestException e, HttpServletRequest request) {
|
||||
log.warn("请求地址 [{}],自定义验证失败。", request.getRequestURI(), e);
|
||||
LogContextHolder.setErrorMsg(e.getMessage());
|
||||
return R.fail(HttpStatus.BAD_REQUEST.value(), e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截校验异常-违反约束异常
|
||||
*/
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public R constraintViolationException(ConstraintViolationException e, HttpServletRequest request) {
|
||||
log.warn("请求地址 [{}],参数验证失败。", request.getRequestURI(), e);
|
||||
String errorMsg = StreamUtils.join(e.getConstraintViolations(), ConstraintViolation::getMessage, ",");
|
||||
LogContextHolder.setErrorMsg(errorMsg);
|
||||
return R.fail(HttpStatus.BAD_REQUEST.value(), errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截校验异常-绑定异常
|
||||
*/
|
||||
@ExceptionHandler(BindException.class)
|
||||
public R handleBindException(BindException e, HttpServletRequest request) {
|
||||
log.warn("请求地址 [{}],参数验证失败。", request.getRequestURI(), e);
|
||||
String errorMsg = StreamUtils.join(e.getAllErrors(), DefaultMessageSourceResolvable::getDefaultMessage, ",");
|
||||
LogContextHolder.setErrorMsg(errorMsg);
|
||||
return R.fail(HttpStatus.BAD_REQUEST.value(), errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截校验异常-方法参数无效异常
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
|
||||
log.warn("请求地址 [{}],参数验证失败。", request.getRequestURI(), e);
|
||||
String errorMsg = ExceptionUtils
|
||||
.exToNull(() -> Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
|
||||
LogContextHolder.setErrorMsg(errorMsg);
|
||||
return R.fail(HttpStatus.BAD_REQUEST.value(), errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截校验异常-方法参数类型不匹配异常
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||
public R handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e,
|
||||
HttpServletRequest request) {
|
||||
String errorMsg = StrUtil.format("参数名:[{}],期望参数类型:[{}]", e.getName(), e.getParameter().getParameterType());
|
||||
log.warn("请求地址 [{}],参数转换失败,{}。", request.getRequestURI(), errorMsg, e);
|
||||
LogContextHolder.setErrorMsg(errorMsg);
|
||||
return R.fail(HttpStatus.BAD_REQUEST.value(), errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截文件上传异常-超过上传大小限制
|
||||
*/
|
||||
@ExceptionHandler(MaxUploadSizeExceededException.class)
|
||||
public R handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e, HttpServletRequest request) {
|
||||
log.warn("请求地址 [{}],上传文件失败,文件大小超过限制。", request.getRequestURI(), e);
|
||||
String sizeLimit = StrUtil.subBetween(e.getMessage(), "The maximum size ", " for");
|
||||
String errorMsg = String.format("请上传小于 %sMB 的文件", NumberUtil.parseLong(sizeLimit) / 1024 / 1024);
|
||||
LogContextHolder.setErrorMsg(errorMsg);
|
||||
return R.fail(HttpStatus.BAD_REQUEST.value(), errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证异常-登录认证
|
||||
*/
|
||||
@ExceptionHandler(NotLoginException.class)
|
||||
public R handleNotLoginException(NotLoginException e, HttpServletRequest request) {
|
||||
log.error("请求地址 [{}],认证失败,无法访问系统资源。", request.getRequestURI(), e);
|
||||
String errorMsg = switch (e.getType()) {
|
||||
case NotLoginException.KICK_OUT -> "您已被踢下线。";
|
||||
case NotLoginException.BE_REPLACED_MESSAGE -> "您已被顶下线。";
|
||||
default -> "您的登录状态已过期,请重新登录。";
|
||||
};
|
||||
LogContextHolder.setErrorMsg(errorMsg);
|
||||
return R.fail(HttpStatus.UNAUTHORIZED.value(), errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证异常-权限认证
|
||||
*/
|
||||
@ExceptionHandler(NotPermissionException.class)
|
||||
public R handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
|
||||
log.error("请求地址 [{}],权限码校验失败。", request.getRequestURI(), e);
|
||||
return R.fail(HttpStatus.FORBIDDEN.value(), "没有访问权限,请联系管理员授权");
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证异常-角色认证
|
||||
*/
|
||||
@ExceptionHandler(NotRoleException.class)
|
||||
public R handleNotRoleException(NotRoleException e, HttpServletRequest request) {
|
||||
log.error("请求地址 [{}],角色权限校验失败。", request.getRequestURI(), e);
|
||||
return R.fail(HttpStatus.FORBIDDEN.value(), "没有访问权限,请联系管理员授权");
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截校验异常-请求方式不支持异常
|
||||
*/
|
||||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
||||
public R handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
|
||||
LogContextHolder.setErrorMsg(e.getMessage());
|
||||
log.error("请求地址 [{}],不支持 [{}] 请求。", request.getRequestURI(), e.getMethod());
|
||||
return R.fail(HttpStatus.METHOD_NOT_ALLOWED.value(), e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截业务异常
|
||||
*/
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
public R handleServiceException(BusinessException e, HttpServletRequest request) {
|
||||
log.error("请求地址 [{}],发生业务异常。", request.getRequestURI(), e);
|
||||
LogContextHolder.setErrorMsg(e.getMessage());
|
||||
return R.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截未知的运行时异常
|
||||
*/
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public R handleRuntimeException(RuntimeException e, HttpServletRequest request) {
|
||||
log.error("请求地址 [{}],发生系统异常。", request.getRequestURI(), e);
|
||||
LogContextHolder.setException(e);
|
||||
return R.fail(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截未知的系统异常
|
||||
*/
|
||||
@ExceptionHandler(Throwable.class)
|
||||
public R handleException(Throwable e, HttpServletRequest request) {
|
||||
log.error("请求地址 [{}],发生未知异常。", request.getRequestURI(), e);
|
||||
LogContextHolder.setException(e);
|
||||
return R.fail(e.getMessage());
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.model.dto;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 系统日志上下文
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/25 8:59
|
||||
*/
|
||||
@Data
|
||||
public class LogContext implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private Long createUser;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String errorMsg;
|
||||
|
||||
/**
|
||||
* 异常信息
|
||||
*/
|
||||
private Throwable exception;
|
||||
}
|
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.model.dto;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
|
||||
import top.charles7c.continew.admin.common.constant.SysConstants;
|
||||
|
||||
/**
|
||||
* 登录用户信息
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/24 13:01
|
||||
*/
|
||||
@Data
|
||||
public class LoginUser implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 部门 ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 权限码集合
|
||||
*/
|
||||
private Set<String> permissions;
|
||||
|
||||
/**
|
||||
* 角色编码集合
|
||||
*/
|
||||
private Set<String> roleCodes;
|
||||
|
||||
/**
|
||||
* 角色集合
|
||||
*/
|
||||
private Set<RoleDTO> roles;
|
||||
|
||||
/**
|
||||
* 令牌
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 登录 IP
|
||||
*/
|
||||
private String clientIp;
|
||||
|
||||
/**
|
||||
* 登录地点
|
||||
*/
|
||||
private String location;
|
||||
|
||||
/**
|
||||
* 浏览器
|
||||
*/
|
||||
private String browser;
|
||||
|
||||
/**
|
||||
* 登录时间
|
||||
*/
|
||||
private LocalDateTime loginTime;
|
||||
|
||||
/**
|
||||
* 是否为管理员
|
||||
*
|
||||
* @return true:是;false:否
|
||||
*/
|
||||
public boolean isAdmin() {
|
||||
if (CollUtil.isEmpty(roleCodes)) {
|
||||
return false;
|
||||
}
|
||||
return roleCodes.contains(SysConstants.ADMIN_ROLE_CODE);
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.model.dto;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import top.charles7c.continew.admin.common.enums.DataScopeEnum;
|
||||
|
||||
/**
|
||||
* 角色信息
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/3/7 22:08
|
||||
*/
|
||||
@Data
|
||||
public class RoleDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 角色编码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 数据权限
|
||||
*/
|
||||
private DataScopeEnum dataScope;
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.model.req;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.charles7c.continew.admin.common.enums.DisEnableStatusEnum;
|
||||
|
||||
/**
|
||||
* 修改状态信息
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/24 19:51
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "修改状态信息")
|
||||
public class UpdateStatusReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
@Schema(description = "状态(1:启用;2:禁用)", type = "Integer", allowableValues = {"1", "2"}, example = "1")
|
||||
@NotNull(message = "状态非法")
|
||||
private DisEnableStatusEnum status;
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.model.resp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* 验证码信息
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/11 13:55
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@Schema(description = "验证码信息")
|
||||
public class CaptchaResp implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 验证码标识
|
||||
*/
|
||||
@Schema(description = "验证码标识", example = "090b9a2c-1691-4fca-99db-e4ed0cff362f")
|
||||
private String uuid;
|
||||
|
||||
/**
|
||||
* 验证码图片(Base64编码,带图片格式:data:image/gif;base64)
|
||||
*/
|
||||
@Schema(description = "验证码图片(Base64编码,带图片格式:data:image/gif;base64)",
|
||||
example = "data:image/png;base64,iVBORw0KGgoAAAAN...")
|
||||
private String img;
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.model.resp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
/**
|
||||
* 键值对信息
|
||||
*
|
||||
* @param <T>
|
||||
* @author Charles7c
|
||||
* @since 2023/2/24 22:02
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "键值对信息")
|
||||
public class LabelValueResp<T> implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
@Schema(description = "标签", example = "男")
|
||||
private String label;
|
||||
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
@Schema(description = "值", example = "1")
|
||||
private T value;
|
||||
|
||||
/**
|
||||
* 颜色
|
||||
*/
|
||||
@Schema(description = "颜色", example = "#165DFF")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String color;
|
||||
|
||||
public LabelValueResp(String label, T value) {
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public LabelValueResp(String label, T value, String color) {
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
this.color = color;
|
||||
}
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.file.FileNameUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
|
||||
/**
|
||||
* 文件工具类
|
||||
*
|
||||
* @author Zheng Jie(ELADMIN)
|
||||
* @author Charles7c
|
||||
* @since 2023/1/2 21:34
|
||||
*/
|
||||
@Slf4j
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class FileUtils {
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param multipartFile
|
||||
* 源文件对象
|
||||
* @param filePath
|
||||
* 文件路径
|
||||
* @param isKeepOriginalFilename
|
||||
* 是否保留原文件名
|
||||
* @return 目标文件对象
|
||||
*/
|
||||
public static File upload(MultipartFile multipartFile, String filePath, boolean isKeepOriginalFilename) {
|
||||
String originalFilename = multipartFile.getOriginalFilename();
|
||||
String extensionName = FileNameUtil.extName(originalFilename);
|
||||
|
||||
String fileName;
|
||||
if (isKeepOriginalFilename) {
|
||||
fileName = String.format("%s-%s.%s", FileNameUtil.getPrefix(originalFilename),
|
||||
DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_MS_PATTERN), extensionName);
|
||||
} else {
|
||||
fileName = String.format("%s.%s", IdUtil.fastSimpleUUID(), extensionName);
|
||||
}
|
||||
|
||||
try {
|
||||
String pathname = filePath + fileName;
|
||||
File dest = new File(pathname).getCanonicalFile();
|
||||
// 如果父路径不存在,自动创建
|
||||
if (!dest.getParentFile().exists()) {
|
||||
if (!dest.getParentFile().mkdirs()) {
|
||||
log.error("Create upload file parent path failed.");
|
||||
}
|
||||
}
|
||||
// 文件写入
|
||||
multipartFile.transferTo(dest);
|
||||
return dest;
|
||||
} catch (Exception e) {
|
||||
log.error("Upload file occurred an error: {}. fileName: {}.", e.getMessage(), fileName, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.util;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.asymmetric.KeyType;
|
||||
|
||||
import top.charles7c.continew.admin.common.config.properties.RsaProperties;
|
||||
import top.charles7c.continew.starter.extension.crud.util.validate.ValidationUtils;
|
||||
|
||||
/**
|
||||
* 加密/解密工具类
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/21 21:41
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class SecureUtils {
|
||||
|
||||
/**
|
||||
* 公钥加密
|
||||
*
|
||||
* @param data
|
||||
* 要加密的内容
|
||||
* @param publicKey
|
||||
* 公钥
|
||||
* @return 公钥加密并 Base64 加密后的内容
|
||||
*/
|
||||
public static String encryptByRsaPublicKey(String data, String publicKey) {
|
||||
return Base64.encode(SecureUtil.rsa(null, publicKey).encrypt(data, KeyType.PublicKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*
|
||||
* @param data
|
||||
* 要解密的内容(Base64 加密过)
|
||||
* @return 解密后的内容
|
||||
*/
|
||||
public static String decryptByRsaPrivateKey(String data) {
|
||||
String privateKey = RsaProperties.PRIVATE_KEY;
|
||||
ValidationUtils.throwIfBlank(privateKey, "请配置 RSA 私钥");
|
||||
return decryptByRsaPrivateKey(data, privateKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*
|
||||
* @param data
|
||||
* 要解密的内容(Base64 加密过)
|
||||
* @param privateKey
|
||||
* 私钥
|
||||
* @return 解密后的内容
|
||||
*/
|
||||
public static String decryptByRsaPrivateKey(String data, String privateKey) {
|
||||
return new String(SecureUtil.rsa(privateKey, null).decrypt(Base64.decode(data), KeyType.PrivateKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* MD5 加密
|
||||
*
|
||||
* @param data
|
||||
* 要加密的内容
|
||||
* @param salt
|
||||
* 盐
|
||||
* @return 加密后的内容
|
||||
*/
|
||||
public static String md5Salt(String data, String salt) {
|
||||
return SecureUtil.md5(SecureUtil.md5(data) + salt);
|
||||
}
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.util;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import cn.hutool.http.useragent.UserAgent;
|
||||
import cn.hutool.http.useragent.UserAgentUtil;
|
||||
|
||||
/**
|
||||
* Servlet 工具类
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/23 20:00
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class ServletUtils {
|
||||
|
||||
/**
|
||||
* 获取请求对象
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public static HttpServletRequest getRequest() {
|
||||
return getServletRequestAttributes().getRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取响应对象
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public static HttpServletResponse getResponse() {
|
||||
return getServletRequestAttributes().getResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览器及其版本信息
|
||||
*
|
||||
* @param request
|
||||
* 请求对象
|
||||
* @return 浏览器及其版本信息
|
||||
*/
|
||||
public static String getBrowser(HttpServletRequest request) {
|
||||
if (null == request) {
|
||||
return null;
|
||||
}
|
||||
UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
||||
return userAgent.getBrowser().getName() + " " + userAgent.getVersion();
|
||||
}
|
||||
|
||||
private static ServletRequestAttributes getServletRequestAttributes() {
|
||||
return (ServletRequestAttributes)Objects.requireNonNull(RequestContextHolder.getRequestAttributes());
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
|
||||
import top.charles7c.continew.starter.core.constant.StringConstants;
|
||||
|
||||
/**
|
||||
* Stream 工具类
|
||||
*
|
||||
* @author Lion Li(<a href="https://gitee.com/dromara/RuoYi-Vue-Plus">RuoYi-Vue-Plus</a>)
|
||||
* @author Charles7c
|
||||
* @since 2022/12/22 19:51
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class StreamUtils {
|
||||
|
||||
/**
|
||||
* 将集合中的指定字段使用分隔符拼接成字符串
|
||||
*
|
||||
* @param collection
|
||||
* 集合
|
||||
* @param function
|
||||
* 字段方法
|
||||
* @param delimiter
|
||||
* 分隔符
|
||||
* @param <E>
|
||||
* /
|
||||
* @return 拼接结果
|
||||
*/
|
||||
public static <E> String join(Collection<E> collection, Function<E, String> function, CharSequence delimiter) {
|
||||
if (CollUtil.isEmpty(collection)) {
|
||||
return StringConstants.EMPTY;
|
||||
}
|
||||
return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter));
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.util;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import cn.hutool.extra.template.Template;
|
||||
import cn.hutool.extra.template.TemplateConfig;
|
||||
import cn.hutool.extra.template.TemplateEngine;
|
||||
import cn.hutool.extra.template.TemplateUtil;
|
||||
|
||||
/**
|
||||
* 模板工具类
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/13 20:37
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class TemplateUtils {
|
||||
|
||||
private static final String TEMPLATE_PARENT_PATH = "templates";
|
||||
|
||||
/**
|
||||
* 将模板与绑定参数融合后返回为字符串
|
||||
*
|
||||
* @param bindingMap
|
||||
* 绑定的参数,此Map中的参数会替换模板中的变量
|
||||
* @return 融合后的内容
|
||||
*/
|
||||
public static String render(String templatePath, Map<?, ?> bindingMap) {
|
||||
TemplateEngine engine =
|
||||
TemplateUtil.createEngine(new TemplateConfig(TEMPLATE_PARENT_PATH, TemplateConfig.ResourceMode.CLASSPATH));
|
||||
Template template = engine.getTemplate(templatePath);
|
||||
return template.render(bindingMap);
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.util;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
|
||||
/**
|
||||
* URL(Uniform Resource Locator)统一资源定位符相关工具类
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/3/20 21:27
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class URLUtils {
|
||||
|
||||
/**
|
||||
* 提供的 URL 是否为 HTTP URL(协议包括:"http","https")
|
||||
*
|
||||
* @param url
|
||||
* URL
|
||||
* @return 是否为 HTTP URL
|
||||
*/
|
||||
public static boolean isHttpUrl(String url) {
|
||||
return HttpUtil.isHttp(url) || HttpUtil.isHttps(url);
|
||||
}
|
||||
}
|
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.util.helper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.extra.servlet.JakartaServletUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
|
||||
import top.charles7c.continew.admin.common.constant.CacheConstants;
|
||||
import top.charles7c.continew.admin.common.model.dto.LogContext;
|
||||
import top.charles7c.continew.admin.common.model.dto.LoginUser;
|
||||
import top.charles7c.continew.admin.common.util.ServletUtils;
|
||||
import top.charles7c.continew.admin.common.util.holder.LogContextHolder;
|
||||
import top.charles7c.continew.starter.core.util.ExceptionUtils;
|
||||
import top.charles7c.continew.starter.core.util.IpUtils;
|
||||
import top.charles7c.continew.starter.extension.crud.base.CommonUserService;
|
||||
|
||||
/**
|
||||
* 登录助手
|
||||
*
|
||||
* @author Charles7c
|
||||
* @author Lion Li(<a href="https://gitee.com/dromara/RuoYi-Vue-Plus">RuoYi-Vue-Plus</a>)
|
||||
* @since 2022/12/24 12:58
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class LoginHelper {
|
||||
|
||||
/**
|
||||
* 用户登录并缓存用户信息
|
||||
*
|
||||
* @param loginUser
|
||||
* 登录用户信息
|
||||
* @return 令牌
|
||||
*/
|
||||
public static String login(LoginUser loginUser) {
|
||||
// 记录登录信息
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
loginUser.setClientIp(JakartaServletUtil.getClientIP(request));
|
||||
loginUser.setLocation(IpUtils.getCityInfo(loginUser.getClientIp()));
|
||||
loginUser.setBrowser(ServletUtils.getBrowser(request));
|
||||
LogContext logContext = LogContextHolder.get();
|
||||
loginUser.setLoginTime(null != logContext ? logContext.getCreateTime() : LocalDateTime.now());
|
||||
// 登录并缓存用户信息
|
||||
StpUtil.login(loginUser.getId());
|
||||
SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
|
||||
String tokenValue = StpUtil.getTokenValue();
|
||||
loginUser.setToken(tokenValue);
|
||||
StpUtil.getTokenSession().set(CacheConstants.LOGIN_USER_KEY, loginUser);
|
||||
return tokenValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户信息
|
||||
*
|
||||
* @return 登录用户信息(获取 TokenSession 时如未登录,会抛出异常)
|
||||
*/
|
||||
public static LoginUser getLoginUser() {
|
||||
LoginUser loginUser = (LoginUser)SaHolder.getStorage().get(CacheConstants.LOGIN_USER_KEY);
|
||||
if (null != loginUser) {
|
||||
return loginUser;
|
||||
}
|
||||
SaSession tokenSession = StpUtil.getTokenSession();
|
||||
if (null == tokenSession) {
|
||||
return null;
|
||||
}
|
||||
loginUser = (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
|
||||
SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Token 获取登录用户信息
|
||||
*
|
||||
* @param token
|
||||
* 用户 Token
|
||||
* @return 登录用户信息
|
||||
*/
|
||||
public static LoginUser getLoginUser(String token) {
|
||||
SaSession tokenSession = StpUtil.getTokenSessionByToken(token);
|
||||
if (null == tokenSession) {
|
||||
return null;
|
||||
}
|
||||
return (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户 ID
|
||||
*
|
||||
* @return 登录用户 ID
|
||||
*/
|
||||
public static Long getUserId() {
|
||||
return ExceptionUtils.exToNull(() -> getLoginUser().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户名
|
||||
*
|
||||
* @return 登录用户名
|
||||
*/
|
||||
public static String getUsername() {
|
||||
return ExceptionUtils.exToNull(() -> getLoginUser().getUsername());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户昵称
|
||||
*
|
||||
* @return 登录用户昵称
|
||||
*/
|
||||
public static String getNickname() {
|
||||
return getNickname(getUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户昵称
|
||||
*
|
||||
* @param userId
|
||||
* 登录用户 ID
|
||||
* @return 登录用户昵称
|
||||
*/
|
||||
public static String getNickname(Long userId) {
|
||||
return ExceptionUtils.exToNull(() -> SpringUtil.getBean(CommonUserService.class).getNicknameById(userId));
|
||||
}
|
||||
}
|
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.charles7c.continew.admin.common.util.holder;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import top.charles7c.continew.admin.common.model.dto.LogContext;
|
||||
|
||||
/**
|
||||
* 系统日志上下文持有者
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/25 8:55
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class LogContextHolder {
|
||||
|
||||
private static final ThreadLocal<LogContext> LOG_THREAD_LOCAL = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* 存储系统日志上下文
|
||||
*
|
||||
* @param logContext
|
||||
* 系统日志上下文信息
|
||||
*/
|
||||
public static void set(LogContext logContext) {
|
||||
LOG_THREAD_LOCAL.set(logContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统日志上下文
|
||||
*
|
||||
* @return 系统日志上下文信息
|
||||
*/
|
||||
public static LogContext get() {
|
||||
return LOG_THREAD_LOCAL.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除系统日志上下文
|
||||
*/
|
||||
public static void remove() {
|
||||
LOG_THREAD_LOCAL.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* 在系统日志上下文中保存异常信息
|
||||
*
|
||||
* @param e
|
||||
* 异常信息
|
||||
*/
|
||||
public static void setException(Throwable e) {
|
||||
LogContext logContext = get();
|
||||
if (null != logContext) {
|
||||
logContext.setErrorMsg(e.getMessage());
|
||||
logContext.setException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在系统日志上下文中保存错误信息(非未知异常不记录异常信息,只记录错误信息)
|
||||
*
|
||||
* @param errorMsg
|
||||
* 错误信息
|
||||
*/
|
||||
public static void setErrorMsg(String errorMsg) {
|
||||
LogContext logContext = get();
|
||||
if (null != logContext) {
|
||||
logContext.setErrorMsg(errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user