Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
查尔斯-BUG万象集
Continew Admin
提交
76fb698a
Continew Admin
项目概览
查尔斯-BUG万象集
/
Continew Admin
11 个月 前同步成功
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
分析
仓库
DevOps
项目成员
Pages
Continew Admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
76fb698a
编写于
1月 09, 2023
作者:
查尔斯-BUG万象集
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
新增:新增修改基础信息 API(优化 Jackson 针对通用枚举接口 IEnum 的序列化和反序列化)
上级
5252c54c
变更
21
隐藏空白更改
内联
并排
Showing
21 changed file
with
442 addition
and
140 deletion
+442
-140
README.md
README.md
+1
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/BigNumberSerializer.java
...7c/cnadmin/common/config/jackson/BigNumberSerializer.java
+3
-3
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/IEnumDeserializer.java
...es7c/cnadmin/common/config/jackson/IEnumDeserializer.java
+76
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/IEnumSerializer.java
...rles7c/cnadmin/common/config/jackson/IEnumSerializer.java
+43
-0
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/JacksonConfiguration.java
...c/cnadmin/common/config/jackson/JacksonConfiguration.java
+23
-16
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/SimpleDeserializersWrapper.java
...min/common/config/jackson/SimpleDeserializersWrapper.java
+68
-0
continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/UserInfoVO.java
.../java/top/charles7c/cnadmin/auth/model/vo/UserInfoVO.java
+1
-1
continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/UpdateBasicInfoRequest.java
.../cnadmin/system/model/request/UpdateBasicInfoRequest.java
+57
-0
continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/UserService.java
...ava/top/charles7c/cnadmin/system/service/UserService.java
+15
-4
continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/UserServiceImpl.java
...harles7c/cnadmin/system/service/impl/UserServiceImpl.java
+49
-2
continew-admin-ui/src/api/interceptor.ts
continew-admin-ui/src/api/interceptor.ts
+5
-1
continew-admin-ui/src/api/system/user-center.ts
continew-admin-ui/src/api/system/user-center.ts
+6
-2
continew-admin-ui/src/views/login/components/login-form.vue
continew-admin-ui/src/views/login/components/login-form.vue
+6
-1
continew-admin-ui/src/views/login/locale/en-US.ts
continew-admin-ui/src/views/login/locale/en-US.ts
+12
-11
continew-admin-ui/src/views/login/locale/zh-CN.ts
continew-admin-ui/src/views/login/locale/zh-CN.ts
+10
-9
continew-admin-ui/src/views/system/user/center/components/basic-information.vue
...views/system/user/center/components/basic-information.vue
+22
-6
continew-admin-ui/src/views/system/user/center/components/user-panel.vue
...ui/src/views/system/user/center/components/user-panel.vue
+15
-42
continew-admin-ui/src/views/system/user/center/locale/en-US.ts
...new-admin-ui/src/views/system/user/center/locale/en-US.ts
+5
-5
continew-admin-ui/src/views/system/user/center/locale/zh-CN.ts
...new-admin-ui/src/views/system/user/center/locale/zh-CN.ts
+7
-7
continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/system/UserCenterController.java
...nadmin/webapi/controller/system/UserCenterController.java
+16
-28
continew-admin-webapi/src/main/resources/application.yml
continew-admin-webapi/src/main/resources/application.yml
+2
-2
未找到文件。
README.md
浏览文件 @
76fb698a
...
...
@@ -155,6 +155,7 @@ continew-admin # 全局通用项目配置及依赖版本管理
│ │ ├─ mapper
# 系统管理相关 Mapper
│ │ ├─ model
# 系统管理相关模型
│ │ │ ├─ entity
# 系统管理相关实体对象
│ │ │ ├─ request
# 系统管理相关请求对象
│ │ │ └─ vo
# 系统管理相关 VO(View Object)
│ │ └─ service
# 系统管理相关业务接口及实现类
│ │ └─ impl
# 系统管理相关业务实现类
...
...
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/BigNumberSerializer.java
浏览文件 @
76fb698a
...
...
@@ -44,12 +44,12 @@ public class BigNumberSerializer extends NumberSerializer {
}
@Override
public
void
serialize
(
Number
value
,
JsonGenerator
gen
,
SerializerProvider
provider
)
throws
IOException
{
public
void
serialize
(
Number
value
,
JsonGenerator
gen
erator
,
SerializerProvider
provider
)
throws
IOException
{
// 序列化为字符串
if
(
value
.
longValue
()
>
MIN_SAFE_INTEGER
&&
value
.
longValue
()
<
MAX_SAFE_INTEGER
)
{
super
.
serialize
(
value
,
gen
,
provider
);
super
.
serialize
(
value
,
gen
erator
,
provider
);
}
else
{
gen
.
writeString
(
value
.
toString
());
gen
erator
.
writeString
(
value
.
toString
());
}
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/IEnumDeserializer.java
0 → 100644
浏览文件 @
76fb698a
/*
* 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.cnadmin.common.config.jackson
;
import
java.io.IOException
;
import
java.lang.reflect.Field
;
import
com.baomidou.mybatisplus.annotation.IEnum
;
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
;
/**
* 通用枚举接口 IEnum 反序列化器
*
* @author Charles7c
* @since 2023/1/8 13:56
*/
@JacksonStdImpl
public
class
IEnumDeserializer
extends
JsonDeserializer
<
IEnum
>
{
/** 静态实例 */
public
static
final
IEnumDeserializer
SERIALIZER_INSTANCE
=
new
IEnumDeserializer
();
@Override
public
IEnum
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}
*/
public
IEnum
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
(
IEnum
.
class
,
fieldTypeClass
))
{
IEnum
iEnum
=
(
IEnum
)
enumConstant
;
if
(
iEnum
.
getValue
().
equals
(
Integer
.
valueOf
(
value
)))
{
return
iEnum
;
}
}
}
return
null
;
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/IEnumSerializer.java
0 → 100644
浏览文件 @
76fb698a
/*
* 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.cnadmin.common.config.jackson
;
import
java.io.IOException
;
import
com.baomidou.mybatisplus.annotation.IEnum
;
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
;
/**
* 通用枚举接口 IEnum 序列化器
*
* @author Charles7c
* @since 2023/1/8 13:56
*/
@JacksonStdImpl
public
class
IEnumSerializer
extends
JsonSerializer
<
IEnum
>
{
/** 静态实例 */
public
static
final
IEnumSerializer
SERIALIZER_INSTANCE
=
new
IEnumSerializer
();
@Override
public
void
serialize
(
IEnum
value
,
JsonGenerator
generator
,
SerializerProvider
serializers
)
throws
IOException
{
generator
.
writeObject
(
value
.
getValue
());
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/JacksonConfiguration.java
浏览文件 @
76fb698a
...
...
@@ -16,7 +16,6 @@
package
top.charles7c.cnadmin.common.config.jackson
;
import
java.io.IOException
;
import
java.math.BigDecimal
;
import
java.math.BigInteger
;
import
java.time.LocalDate
;
...
...
@@ -30,11 +29,11 @@ import lombok.extern.slf4j.Slf4j;
import
org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.http.converter.json.Jackson2ObjectMapperBuilder
;
import
com.baomidou.mybatisplus.annotation.IEnum
;
import
com.fasterxml.jackson.core.JsonGenerator
;
import
com.fasterxml.jackson.databind.JsonSerializer
;
import
com.fasterxml.jackson.databind.SerializerProvider
;
import
com.fasterxml.jackson.databind.*
;
import
com.fasterxml.jackson.databind.module.SimpleModule
;
import
com.fasterxml.jackson.databind.ser.std.ToStringSerializer
;
import
com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
;
import
com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer
;
...
...
@@ -55,7 +54,7 @@ import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
public
class
JacksonConfiguration
{
/**
*
全局配置序列化返回 JSON 处理
*
针对数值类型:Long、BigInteger、BigDecimal,时间类型:LocalDateTime、LocalDate、LocalTime 的序列化和反序列化
*/
@Bean
public
Jackson2ObjectMapperBuilderCustomizer
customizer
()
{
...
...
@@ -64,23 +63,14 @@ public class JacksonConfiguration {
String
timeFormatPattern
=
"HH:mm:ss"
;
return
builder
->
{
// 针对通用枚举 IEnum 的转换
builder
.
serializerByType
(
IEnum
.
class
,
new
JsonSerializer
<
IEnum
<
Integer
>>()
{
@Override
public
void
serialize
(
IEnum
<
Integer
>
value
,
JsonGenerator
gen
,
SerializerProvider
serializers
)
throws
IOException
{
gen
.
writeNumber
(
value
.
getValue
());
}
});
// 针对 Long、BigInteger、BigDecimal 的转换
// 针对数值类型:Long、BigInteger、BigDecimal 的序列化和反序列化
JavaTimeModule
javaTimeModule
=
new
JavaTimeModule
();
javaTimeModule
.
addSerializer
(
Long
.
class
,
BigNumberSerializer
.
SERIALIZER_INSTANCE
);
javaTimeModule
.
addSerializer
(
Long
.
TYPE
,
BigNumberSerializer
.
SERIALIZER_INSTANCE
);
javaTimeModule
.
addSerializer
(
BigInteger
.
class
,
BigNumberSerializer
.
SERIALIZER_INSTANCE
);
javaTimeModule
.
addSerializer
(
BigDecimal
.
class
,
ToStringSerializer
.
instance
);
// 针对
LocalDateTime、LocalDate、LocalTime 的转换
// 针对
时间类型:LocalDateTime、LocalDate、LocalTime 的序列化和反序列化
DateTimeFormatter
dateTimeFormatter
=
DateTimeFormatter
.
ofPattern
(
dateTimeFormatPattern
);
javaTimeModule
.
addSerializer
(
LocalDateTime
.
class
,
new
LocalDateTimeSerializer
(
dateTimeFormatter
));
javaTimeModule
.
addDeserializer
(
LocalDateTime
.
class
,
new
LocalDateTimeDeserializer
(
dateTimeFormatter
));
...
...
@@ -97,4 +87,21 @@ public class JacksonConfiguration {
log
.
info
(
">>>初始化 Jackson 配置<<<"
);
};
}
/**
* 针对通用枚举接口 IEnum 的序列化和反序列化
*/
@Bean
public
ObjectMapper
objectMapper
(
Jackson2ObjectMapperBuilder
builder
)
{
SimpleModule
simpleModule
=
new
SimpleModule
();
simpleModule
.
addSerializer
(
IEnum
.
class
,
IEnumSerializer
.
SERIALIZER_INSTANCE
);
SimpleDeserializersWrapper
deserializers
=
new
SimpleDeserializersWrapper
();
deserializers
.
addDeserializer
(
IEnum
.
class
,
IEnumDeserializer
.
SERIALIZER_INSTANCE
);
simpleModule
.
setDeserializers
(
deserializers
);
ObjectMapper
objectMapper
=
builder
.
createXmlMapper
(
false
).
build
();
objectMapper
.
registerModule
(
simpleModule
);
return
objectMapper
;
}
}
continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/jackson/SimpleDeserializersWrapper.java
0 → 100644
浏览文件 @
76fb698a
/*
* 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.cnadmin.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 枚举类型,则是找它的接口 IEnum 的反序列化器);<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
(
deser
!=
null
)
{
return
deser
;
}
// 重写增强:开始查找指定枚举类型的接口的反序列化器(例如:GenderEnum 枚举类型,则是找它的接口 IEnum 的反序列化器)
for
(
Class
<?>
typeInterface
:
type
.
getInterfaces
())
{
deser
=
this
.
_classMappings
.
get
(
new
ClassKey
(
typeInterface
));
if
(
deser
!=
null
)
{
return
deser
;
}
}
return
null
;
}
}
continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/UserInfoVO.java
浏览文件 @
76fb698a
...
...
@@ -65,7 +65,7 @@ public class UserInfoVO implements Serializable {
/**
* 性别(0未知 1男 2女)
*/
@Schema
(
description
=
"性别(0未知 1男 2女)"
)
@Schema
(
description
=
"性别(0未知 1男 2女)"
,
type
=
"Integer"
,
allowableValues
=
{
"0"
,
"1"
,
"2"
}
)
private
GenderEnum
gender
;
/**
...
...
continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/UpdateBasicInfoRequest.java
0 → 100644
浏览文件 @
76fb698a
/*
* 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.cnadmin.system.model.request
;
import
java.io.Serializable
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.NotNull
;
import
javax.validation.constraints.Size
;
import
lombok.Data
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
top.charles7c.cnadmin.common.enums.GenderEnum
;
/**
* 修改基础信息
*
* @author Charles7c
* @since 2023/1/7 23:08
*/
@Data
@Schema
(
description
=
"修改基础信息"
)
public
class
UpdateBasicInfoRequest
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 昵称
*/
@Schema
(
description
=
"昵称"
)
@NotBlank
(
message
=
"昵称不能为空"
)
@Size
(
max
=
32
,
message
=
"昵称长度不能超过 32 个字符"
)
private
String
nickname
;
/**
* 性别(0未知 1男 2女)
*/
@Schema
(
description
=
"性别(0未知 1男 2女)"
,
type
=
"Integer"
,
allowableValues
=
{
"0"
,
"1"
,
"2"
})
@NotNull
(
message
=
"非法性别"
)
private
GenderEnum
gender
;
}
continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/UserService.java
浏览文件 @
76fb698a
...
...
@@ -16,6 +16,8 @@
package
top.charles7c.cnadmin.system.service
;
import
org.springframework.web.multipart.MultipartFile
;
import
top.charles7c.cnadmin.system.model.entity.SysUser
;
/**
...
...
@@ -36,12 +38,21 @@ public interface UserService {
SysUser
getByUsername
(
String
username
);
/**
*
修改
头像
*
上传
头像
*
* @param avatar
* 头像
路径
* 头像
文件
* @param userId
* 用户ID
* 用户 ID
* @return 新头像路径
*/
String
uploadAvatar
(
MultipartFile
avatar
,
Long
userId
);
/**
* 修改信息
*
* @param user
* 用户信息
*/
void
update
Avatar
(
String
avatar
,
Long
userId
);
void
update
(
SysUser
user
);
}
continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/UserServiceImpl.java
浏览文件 @
76fb698a
...
...
@@ -16,13 +16,26 @@
package
top.charles7c.cnadmin.system.service.impl
;
import
java.io.File
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.multipart.MultipartFile
;
import
com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.io.FileUtil
;
import
cn.hutool.core.util.StrUtil
;
import
top.charles7c.cnadmin.common.config.properties.LocalStorageProperties
;
import
top.charles7c.cnadmin.common.model.dto.LoginUser
;
import
top.charles7c.cnadmin.common.util.FileUtils
;
import
top.charles7c.cnadmin.common.util.helper.LoginHelper
;
import
top.charles7c.cnadmin.common.util.validate.CheckUtils
;
import
top.charles7c.cnadmin.system.mapper.UserMapper
;
import
top.charles7c.cnadmin.system.model.entity.SysUser
;
import
top.charles7c.cnadmin.system.service.UserService
;
...
...
@@ -38,6 +51,7 @@ import top.charles7c.cnadmin.system.service.UserService;
public
class
UserServiceImpl
implements
UserService
{
private
final
UserMapper
userMapper
;
private
final
LocalStorageProperties
localStorageProperties
;
@Override
public
SysUser
getByUsername
(
String
username
)
{
...
...
@@ -45,8 +59,41 @@ public class UserServiceImpl implements UserService {
}
@Override
public
void
updateAvatar
(
String
avatar
,
Long
userId
)
{
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
String
uploadAvatar
(
MultipartFile
avatarFile
,
Long
userId
)
{
// 上传新头像
String
avatarPath
=
localStorageProperties
.
getPath
().
getAvatar
();
File
newAvatarFile
=
FileUtils
.
upload
(
avatarFile
,
avatarPath
,
false
);
CheckUtils
.
exIfNull
(
newAvatarFile
,
"上传头像失败"
);
assert
newAvatarFile
!=
null
;
// 更新用户头像
String
newAvatar
=
newAvatarFile
.
getName
();
userMapper
.
update
(
null
,
new
LambdaUpdateWrapper
<
SysUser
>().
set
(
SysUser:
:
getAvatar
,
avatar
).
eq
(
SysUser:
:
getUserId
,
userId
));
new
LambdaUpdateWrapper
<
SysUser
>().
set
(
SysUser:
:
getAvatar
,
newAvatar
).
eq
(
SysUser:
:
getUserId
,
userId
));
// 删除原头像
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
String
oldAvatar
=
loginUser
.
getAvatar
();
if
(
StrUtil
.
isNotBlank
(
loginUser
.
getAvatar
()))
{
FileUtil
.
del
(
avatarPath
+
oldAvatar
);
}
// 更新登录用户信息
loginUser
.
setAvatar
(
newAvatar
);
LoginHelper
.
updateLoginUser
(
loginUser
);
return
newAvatar
;
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
void
update
(
SysUser
user
)
{
userMapper
.
updateById
(
user
);
// 更新登录用户信息
SysUser
sysUser
=
userMapper
.
selectById
(
user
.
getUserId
());
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
BeanUtil
.
copyProperties
(
sysUser
,
loginUser
);
LoginHelper
.
updateLoginUser
(
loginUser
);
}
}
continew-admin-ui/src/api/interceptor.ts
浏览文件 @
76fb698a
...
...
@@ -38,7 +38,11 @@ axios.interceptors.request.use(
// add response interceptors
axios
.
interceptors
.
response
.
use
(
(
response
:
AxiosResponse
<
HttpResponse
>
)
=>
{
return
response
.
data
;
const
res
=
response
.
data
;
if
(
!
res
.
success
)
{
Message
.
error
(
res
.
msg
);
}
return
res
;
},
(
error
)
=>
{
const
res
=
error
.
response
.
data
;
...
...
continew-admin-ui/src/api/system/user-center.ts
浏览文件 @
76fb698a
...
...
@@ -13,6 +13,10 @@ export function uploadAvatar(data: FormData) {
return
axios
.
post
<
AvatarRes
>
(
'
/system/user/center/avatar
'
,
data
);
}
export
function
saveUserInfo
()
{
return
axios
.
get
(
'
/api/user/save-info
'
);
export
interface
UpdateBasicInfoReq
{
nickname
:
string
;
gender
:
number
;
}
export
function
updateBasicInfo
(
req
:
UpdateBasicInfoReq
)
{
return
axios
.
patch
(
'
/system/user/center/basic/info
'
,
req
);
}
\ No newline at end of file
continew-admin-ui/src/views/login/components/login-form.vue
浏览文件 @
76fb698a
...
...
@@ -19,6 +19,8 @@
<a-input
v-model=
"loginForm.username"
:placeholder=
"$t('login.form.username.placeholder')"
size=
"large"
max-length=
"50"
>
<template
#prefix
>
<icon-user
/>
...
...
@@ -34,7 +36,9 @@
<a-input-password
v-model=
"loginForm.password"
:placeholder=
"$t('login.form.password.placeholder')"
size=
"large"
allow-clear
max-length=
"50"
>
<
template
#prefix
>
<icon-lock
/>
...
...
@@ -51,6 +55,7 @@
<a-input
v-model=
"loginForm.captcha"
:placeholder=
"$t('login.form.captcha.placeholder')"
size=
"large"
style=
"width: 63%"
allow-clear
>
...
...
@@ -70,7 +75,7 @@
{{ $t('login.form.rememberMe') }}
</a-checkbox>
</div>
<a-button
type=
"primary"
html-type=
"submit"
long
:loading=
"loading"
>
<a-button
type=
"primary"
size=
"large"
html-type=
"submit"
long
:loading=
"loading"
>
{{ $t('login.form.login') }}
</a-button>
</a-space>
...
...
continew-admin-ui/src/views/login/locale/en-US.ts
浏览文件 @
76fb698a
export
default
{
'
login.form.title
'
:
'
Login to ContiNew Admin
'
,
'
login.form.subTitle
'
:
'
Continue to build the latest popular technology stack in the background management framework
'
,
'
login.form.username.
errMsg
'
:
'
Username cannot be empty
'
,
'
login.form.
password.errMsg
'
:
'
Password cannot be empty
'
,
'
login.form.
captcha.errMsg
'
:
'
Captcha cannot be empty
'
,
'
login.form.
login.errMsg
'
:
'
Login error, refresh and try again
'
,
'
login.form.
login.success
'
:
'
welcome to use
'
,
'
login.form.
username.placeholder
'
:
'
Username
'
,
'
login.form.
password.placeholder
'
:
'
Password
'
,
'
login.form.
captcha.placeholder
'
:
'
Captcha
'
,
'
login.form.re
memberMe
'
:
'
Remember Me
'
,
'
login.form.username.
placeholder
'
:
'
Please enter username
'
,
'
login.form.
username.errMsg
'
:
'
Please enter username
'
,
'
login.form.
password.placeholder
'
:
'
Please enter password
'
,
'
login.form.
password.errMsg
'
:
'
Please enter password
'
,
'
login.form.
captcha.placeholder
'
:
'
Please enter captcha
'
,
'
login.form.
captcha.errMsg
'
:
'
Please enter captcha
'
,
'
login.form.
rememberMe
'
:
'
Remember me
'
,
'
login.form.
login
'
:
'
Login
'
,
'
login.form.re
gister
'
:
'
Register account
'
,
'
login.form.forgetPassword
'
:
'
Forgot password
'
,
'
login.form.login
'
:
'
login
'
,
'
login.form.register
'
:
'
register account
'
,
'
login.form.login.success
'
:
'
Welcome to use
'
,
'
login.form.login.errMsg
'
:
'
Login error, refresh and try again
'
,
'
login.banner.slogan1
'
:
'
Out-of-the-box high-quality template
'
,
'
login.banner.subSlogan1
'
:
'
Rich page templates, covering most typical business scenarios
'
,
...
...
continew-admin-ui/src/views/login/locale/zh-CN.ts
浏览文件 @
76fb698a
export
default
{
'
login.form.title
'
:
'
登录 ContiNew Admin
'
,
'
login.form.subTitle
'
:
'
持续以最新流行技术栈构建的中后台管理框架
'
,
'
login.form.username.errMsg
'
:
'
用户名不能为空
'
,
'
login.form.password.errMsg
'
:
'
密码不能为空
'
,
'
login.form.captcha.errMsg
'
:
'
验证码不能为空
'
,
'
login.form.login.errMsg
'
:
'
登录出错,请刷新重试
'
,
'
login.form.login.success
'
:
'
欢迎使用
'
,
'
login.form.username.placeholder
'
:
'
用户名
'
,
'
login.form.password.placeholder
'
:
'
密码
'
,
'
login.form.captcha.placeholder
'
:
'
验证码
'
,
'
login.form.username.placeholder
'
:
'
请输入用户名
'
,
'
login.form.username.errMsg
'
:
'
请输入用户名
'
,
'
login.form.password.placeholder
'
:
'
请输入密码
'
,
'
login.form.password.errMsg
'
:
'
请输入密码
'
,
'
login.form.captcha.placeholder
'
:
'
请输入验证码
'
,
'
login.form.captcha.errMsg
'
:
'
请输入验证码
'
,
'
login.form.rememberMe
'
:
'
记住我
'
,
'
login.form.forgetPassword
'
:
'
忘记密码
'
,
'
login.form.login
'
:
'
登录
'
,
'
login.form.register
'
:
'
注册账号
'
,
'
login.form.forgetPassword
'
:
'
忘记密码
'
,
'
login.form.login.success
'
:
'
欢迎使用
'
,
'
login.form.login.errMsg
'
:
'
登录出错,请刷新重试
'
,
'
login.banner.slogan1
'
:
'
中后台管理框架
'
,
'
login.banner.subSlogan1
'
:
'
Continue New Admin,持续以最新流行技术栈构建
'
,
'
login.banner.slogan2
'
:
'
内置了常见问题的解决方案
'
,
...
...
continew-admin-ui/src/views/system/user/center/components/basic-information.vue
浏览文件 @
76fb698a
...
...
@@ -19,6 +19,7 @@
<a-input
v-model=
"formData.username"
:placeholder=
"$t('userCenter.basicInfo.placeholder.username')"
max-length=
"50"
/>
</a-form-item>
<a-form-item
...
...
@@ -34,6 +35,7 @@
<a-input
v-model=
"formData.nickname"
:placeholder=
"$t('userCenter.basicInfo.placeholder.nickname')"
max-length=
"32"
/>
</a-form-item>
<a-form-item
...
...
@@ -48,7 +50,7 @@
</a-form-item>
<a-form-item>
<a-space>
<a-button
type=
"primary"
@
click=
"validat
e"
>
<a-button
type=
"primary"
:loading=
"loading"
@
click=
"sav
e"
>
{{
$t
(
'
userCenter.save
'
)
}}
</a-button>
<a-button
type=
"secondary"
@
click=
"reset"
>
...
...
@@ -62,9 +64,13 @@
<
script
lang=
"ts"
setup
>
import
{
ref
}
from
'
vue
'
;
import
{
useLoginStore
}
from
'
@/store
'
;
import
{
updateBasicInfo
}
from
'
@/api/system/user-center
'
;
import
useLoading
from
'
@/hooks/loading
'
;
import
{
FormInstance
}
from
'
@arco-design/web-vue/es/form
'
;
import
{
BasicInfoModel
}
from
'
@/api/system/user-center
'
;
import
{
Message
}
from
"
@arco-design/web-vue
"
;
const
{
loading
,
setLoading
}
=
useLoading
();
const
loginStore
=
useLoginStore
();
const
formRef
=
ref
<
FormInstance
>
();
const
formData
=
ref
<
BasicInfoModel
>
({
...
...
@@ -74,11 +80,21 @@
});
// 保存
const
validate
=
async
()
=>
{
const
res
=
await
formRef
.
value
?.
validate
();
if
(
!
res
)
{
// do some thing
// you also can use html-type to submit
const
save
=
async
()
=>
{
const
errors
=
await
formRef
.
value
?.
validate
();
if
(
loading
.
value
)
return
;
if
(
!
errors
)
{
setLoading
(
true
);
try
{
const
res
=
await
updateBasicInfo
({
nickname
:
formData
.
value
.
nickname
,
gender
:
formData
.
value
.
gender
,
});
await
loginStore
.
getInfo
();
if
(
res
.
success
)
Message
.
success
(
res
.
msg
);
}
finally
{
setLoading
(
false
);
}
}
};
...
...
continew-admin-ui/src/views/system/user/center/components/user-panel.vue
浏览文件 @
76fb698a
...
...
@@ -19,7 +19,6 @@
</template>
</a-upload>
<a-descriptions
:data=
"renderData"
:column=
"2"
align=
"right"
layout=
"inline-horizontal"
...
...
@@ -34,21 +33,21 @@
textAlign: 'left',
}"
>
<
template
#label=
"{ label }"
>
{{
$t
(
label
)
}}
:
</
template
>
<
template
#value=
"{ value, data }"
>
<div
v-if=
"data.label === 'userCenter.label.gender'"
>
<div
v-if=
"loginStore.gender === 1"
>
男
<icon-man
style=
"color: #19BBF1"
/>
</div>
<div
v-else-if=
"loginStore.gender === 2"
>
女
<icon-woman
style=
"color: #FA7FA9"
/>
</div>
<div
v-else
>
未知
</div>
<a-descriptions-item
:label=
"$t('userCenter.label.nickname')"
>
{{ loginStore.nickname }}
</a-descriptions-item>
<a-descriptions-item
:label=
"$t('userCenter.label.gender')"
>
<div
v-if=
"loginStore.gender === 1"
>
男
<icon-man
style=
"color: #19BBF1"
/>
</div>
<span
v-else
>
{{
value
}}
</span>
</
template
>
<div
v-else-if=
"loginStore.gender === 2"
>
女
<icon-woman
style=
"color: #FA7FA9"
/>
</div>
<div
v-else
>
未知
</div>
</a-descriptions-item>
<a-descriptions-item
:label=
"$t('userCenter.label.phone')"
>
{{ loginStore.phone }}
</a-descriptions-item>
<a-descriptions-item
:label=
"$t('userCenter.label.email')"
>
{{ loginStore.email }}
</a-descriptions-item>
<a-descriptions-item
:label=
"$t('userCenter.label.registrationDate')"
>
{{ loginStore.registrationDate }}
</a-descriptions-item>
</a-descriptions>
</a-space>
</a-card>
...
...
@@ -62,7 +61,6 @@
}
from
'
@arco-design/web-vue/es/upload/interfaces
'
;
import
{
useLoginStore
}
from
'
@/store
'
;
import
{
uploadAvatar
}
from
'
@/api/system/user-center
'
;
import
type
{
DescData
}
from
'
@arco-design/web-vue/es/descriptions/interface
'
;
import
getAvatar
from
"
@/utils/avatar
"
;
import
{
Message
}
from
"
@arco-design/web-vue
"
;
...
...
@@ -72,28 +70,6 @@
name
:
'
avatar.png
'
,
url
:
getAvatar
(
loginStore
),
};
const
renderData
=
[
{
label
:
'
userCenter.label.nickname
'
,
value
:
loginStore
.
nickname
,
},
{
label
:
'
userCenter.label.gender
'
,
value
:
loginStore
.
gender
,
},
{
label
:
'
userCenter.label.phone
'
,
value
:
loginStore
.
phone
,
},
{
label
:
'
userCenter.label.email
'
,
value
:
loginStore
.
email
,
},
{
label
:
'
userCenter.label.registrationDate
'
,
value
:
loginStore
.
registrationDate
,
},
]
as
DescData
[];
const
avatarList
=
ref
<
FileItem
[]
>
([
avatar
]);
// 切换头像
...
...
@@ -118,10 +94,7 @@
try
{
const
res
=
await
uploadAvatar
(
formData
);
onSuccess
(
res
);
Message
.
success
({
content
:
res
.
msg
||
'
网络错误
'
,
duration
:
3
*
1000
,
});
if
(
res
.
success
)
Message
.
success
(
res
.
msg
);
// 更换头像
loginStore
.
avatar
=
res
.
data
.
avatar
;
}
catch
(
error
)
{
...
...
continew-admin-ui/src/views/system/user/center/locale/en-US.ts
浏览文件 @
76fb698a
export
default
{
'
menu.user.center
'
:
'
User Center
'
,
'
userCenter.label.nickname
'
:
'
Nick Name
'
,
'
userCenter.label.gender
'
:
'
Gender
'
,
'
userCenter.label.phone
'
:
'
Phone
'
,
'
userCenter.label.email
'
:
'
Email
'
,
'
userCenter.label.registrationDate
'
:
'
Registration Date
'
,
'
userCenter.label.nickname
'
:
'
Nick Name
:
'
,
'
userCenter.label.gender
'
:
'
Gender
:
'
,
'
userCenter.label.phone
'
:
'
Phone
:
'
,
'
userCenter.label.email
'
:
'
Email
:
'
,
'
userCenter.label.registrationDate
'
:
'
Registration Date
:
'
,
'
userCenter.tab.basicInformation
'
:
'
Basic Information
'
,
'
userCenter.basicInfo.form.label.username
'
:
'
Username
'
,
...
...
continew-admin-ui/src/views/system/user/center/locale/zh-CN.ts
浏览文件 @
76fb698a
export
default
{
'
menu.user.center
'
:
'
个人中心
'
,
'
userCenter.label.nickname
'
:
'
昵称
'
,
'
userCenter.label.gender
'
:
'
性别
'
,
'
userCenter.label.phone
'
:
'
手机号码
'
,
'
userCenter.label.email
'
:
'
邮箱
'
,
'
userCenter.label.registrationDate
'
:
'
注册日期
'
,
'
userCenter.label.nickname
'
:
'
昵称
:
'
,
'
userCenter.label.gender
'
:
'
性别
:
'
,
'
userCenter.label.phone
'
:
'
手机号码
:
'
,
'
userCenter.label.email
'
:
'
邮箱
:
'
,
'
userCenter.label.registrationDate
'
:
'
注册日期
:
'
,
'
userCenter.tab.basicInformation
'
:
'
基础信息
'
,
'
userCenter.basicInfo.form.label.username
'
:
'
用户名
'
,
'
userCenter.basicInfo.placeholder.username
'
:
'
请输入
您的
用户名
'
,
'
userCenter.basicInfo.placeholder.username
'
:
'
请输入用户名
'
,
'
userCenter.form.error.username.required
'
:
'
请输入用户名
'
,
'
userCenter.basicInfo.form.label.nickname
'
:
'
昵称
'
,
'
userCenter.basicInfo.placeholder.nickname
'
:
'
请输入
您的
昵称
'
,
'
userCenter.basicInfo.placeholder.nickname
'
:
'
请输入昵称
'
,
'
userCenter.form.error.nickname.required
'
:
'
请输入昵称
'
,
'
userCenter.basicInfo.form.label.gender
'
:
'
性别
'
,
'
userCenter.save
'
:
'
保存
'
,
...
...
continew-admin-webapi/src/main/java/top/charles7c/cnadmin/webapi/controller/system/UserCenterController.java
浏览文件 @
76fb698a
...
...
@@ -16,8 +16,6 @@
package
top.charles7c.cnadmin.webapi.controller.system
;
import
java.io.File
;
import
javax.validation.constraints.NotNull
;
import
lombok.RequiredArgsConstructor
;
...
...
@@ -27,23 +25,20 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import
org.springframework.http.MediaType
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
import
cn.hutool.core.
io.File
Util
;
import
cn.hutool.core.
bean.Bean
Util
;
import
cn.hutool.core.io.file.FileNameUtil
;
import
cn.hutool.core.util.StrUtil
;
import
top.charles7c.cnadmin.common.config.properties.LocalStorageProperties
;
import
top.charles7c.cnadmin.common.consts.FileConstants
;
import
top.charles7c.cnadmin.common.model.dto.LoginUser
;
import
top.charles7c.cnadmin.common.model.vo.R
;
import
top.charles7c.cnadmin.common.util.FileUtils
;
import
top.charles7c.cnadmin.common.util.helper.LoginHelper
;
import
top.charles7c.cnadmin.common.util.validate.CheckUtils
;
import
top.charles7c.cnadmin.common.util.validate.ValidationUtils
;
import
top.charles7c.cnadmin.system.model.entity.SysUser
;
import
top.charles7c.cnadmin.system.model.request.UpdateBasicInfoRequest
;
import
top.charles7c.cnadmin.system.model.vo.AvatarVO
;
import
top.charles7c.cnadmin.system.service.UserService
;
...
...
@@ -76,25 +71,18 @@ public class UserCenterController {
ValidationUtils
.
exIfCondition
(()
->
!
StrUtil
.
equalsAnyIgnoreCase
(
avatarImageType
,
avatarSupportImgTypes
),
String
.
format
(
"头像仅支持 %s 格式的图片"
,
String
.
join
(
","
,
avatarSupportImgTypes
)));
// 上传新头像
String
avatarPath
=
localStorageProperties
.
getPath
().
getAvatar
();
File
newAvatarFile
=
FileUtils
.
upload
(
avatarFile
,
avatarPath
,
false
);
CheckUtils
.
exIfNull
(
newAvatarFile
,
"上传头像失败"
);
// 更新用户头像
LoginUser
loginUser
=
LoginHelper
.
getLoginUser
();
String
newAvatar
=
newAvatarFile
.
getName
();
userService
.
updateAvatar
(
newAvatar
,
loginUser
.
getUserId
());
// 删除原头像
String
oldAvatar
=
loginUser
.
getAvatar
();
if
(
StrUtil
.
isNotBlank
(
loginUser
.
getAvatar
()))
{
FileUtil
.
del
(
avatarPath
+
oldAvatar
);
}
// 更新登录用户信息
loginUser
.
setAvatar
(
newAvatar
);
LoginHelper
.
updateLoginUser
(
loginUser
);
// 上传头像
String
newAvatar
=
userService
.
uploadAvatar
(
avatarFile
,
LoginHelper
.
getUserId
());
return
R
.
ok
(
"上传成功"
,
new
AvatarVO
().
setAvatar
(
newAvatar
));
}
@Operation
(
summary
=
"修改基础信息"
,
description
=
"修改用户基础信息"
)
@PatchMapping
(
"/basic/info"
)
public
R
updateBasicInfo
(
@Validated
@RequestBody
UpdateBasicInfoRequest
updateBasicInfoRequest
)
{
SysUser
user
=
new
SysUser
();
user
.
setUserId
(
LoginHelper
.
getUserId
());
BeanUtil
.
copyProperties
(
updateBasicInfoRequest
,
user
);
userService
.
update
(
user
);
return
R
.
ok
(
"修改成功"
);
}
}
continew-admin-webapi/src/main/resources/application.yml
浏览文件 @
76fb698a
...
...
@@ -167,11 +167,11 @@ spring:
# 序列化配置(Bean -> JSON)
serialization
:
# 允许序列化无属性的 Bean
fail_on_empty_beans
:
false
FAIL_ON_EMPTY_BEANS
:
false
# 反序列化配置(JSON -> Bean)
deserialization
:
# 允许反序列化不存在的属性
fail_on_unknown_properties
:
false
FAIL_ON_UNKNOWN_PROPERTIES
:
false
---
### 线程池配置
thread-pool
:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录