diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 1671f3f7..98af0ded 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -49,6 +49,7 @@ jobs:
script: |
cd /docker
docker-compose up --force-recreate --build -d continew-admin-server
+ docker images | grep none | awk '{print $3}' | xargs docker rmi
# 部署前端
deploy-web:
diff --git a/README.md b/README.md
index b0e72aca..14d15996 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# ContiNew-Admin 中后台管理框架
+# ContiNew Admin 中后台管理框架
[](https://github.com/Charles7c/continew-admin/blob/dev/LICENSE)

@@ -7,7 +7,7 @@
## 简介
-ContiNew-Admin (incubating) 中后台管理框架,Continue New Admin,持续以最新流行技术栈构建。当前阶段采用的技术栈:Vue3、TypeScript、Arco Design Pro Vue、Spring Boot、Undertow、Sa-Token、JWT、MariaDB、MyBatis Plus、Redis、Redisson、Hutool 等。
+ContiNew Admin 中后台管理框架(孵化中),Continue New Admin,持续以最新流行技术栈构建。当前阶段采用的技术栈:Vue3、TypeScript、Arco Design Pro Vue、Spring Boot、Undertow、Sa-Token、JWT、MariaDB、MyBatis Plus、Redis、Redisson、Hutool 等。
## 开始
@@ -21,11 +21,11 @@ git clone https://github.com/Charles7c/continew-admin.git
# 2.在 IDE(IntelliJ IDEA/Eclipse)中打开本项目
-# 3.修改配置文件中的 Redis 配置信息
+# 3.修改配置文件中的数据源配置信息、Redis 配置信息、邮件配置信息等
# [3.也可以在 IntelliJ IDEA 中直接配置程序启动环境变量(DB_HOST、DB_PORT、DB_USER、DB_PWD、DB_NAME;REDIS_HOST、REDIS_PORT、REDIS_PWD、REDIS_DB)]
# 4.启动程序
-# 4.1 启动成功:访问 http://localhost:8000/,页面输出:ContiNew-Admin backend service started successfully.
+# 4.1 启动成功:访问 http://localhost:8000/,页面输出:ContiNew Admin backend service started successfully.
# 4.2 接口文档:http://localhost:8000/doc.html
# 5.部署
@@ -72,7 +72,7 @@ yarn dev
| :----------------------------------------------------------- | :----------- | :----------------------------------------------------------- |
| [Vue](https://cn.vuejs.org/) | 3.2.45 | 渐进式 JavaScript 框架,易学易用,性能出色,适用场景丰富的 Web 前端框架。 |
| [TypeScript](https://www.typescriptlang.org/zh/) | 4.9.4 | TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。 |
-| [Arco Design Pro Vue](http://pro.arco.design/) | 2.5.15 | 基于 Arco Design Vue 组件库的开箱即用的中后台前端解决方案。 |
+| [Arco Design Pro Vue](http://pro.arco.design/) | 2.6.0 | 基于 Arco Design Vue 组件库的开箱即用的中后台前端解决方案。 |
| [Spring Boot](https://spring.io/projects/spring-boot) | 2.7.7 | 简化新 Spring 应用的初始搭建以及开发过程。 |
| [Undertow](https://undertow.io/) | 2.2.22.Final | 采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。 |
| [Sa-Token + JWT](https://sa-token.dev33.cn/) | 1.33.0 | 轻量级 Java 权限认证框架,让鉴权变得简单、优雅。 |
@@ -110,10 +110,14 @@ continew-admin # 全局通用项目配置及依赖版本管理
│ │ ├─ webapi
│ │ │ └─ controller
│ │ │ ├─ auth # 认证相关 API
+ │ │ │ ├─ common # 公共相关 API(例如:验证码 API 等)
│ │ │ └─ system # 系统管理相关 API
│ │ └─ ContinewAdminApplication.java # 启动入口
│ └─ resources # 工程配置目录
- │ └─ db.changelog.v0.0.1 # 数据库脚本文件
+ │ ├─ db.changelog # 数据库脚本文件
+ │ │ └─ v0.0.1 # v0.0.1 版本数据库脚本文件
+ │ └─ templates # 模板文件
+ │ └─ mail # 邮件模板
├─ continew-admin-monitor # 系统监控模块(存放系统监控模块相关功能,例如:日志管理、服务监控等)
│ └─ src
│ └─ main
@@ -144,8 +148,7 @@ continew-admin # 全局通用项目配置及依赖版本管理
│ │ └─ cnadmin
│ │ ├─ auth # 系统认证相关业务及配置
│ │ │ ├─ config # 系统认证相关配置
- │ │ │ │ ├─ satoken # Sa-Token 配置
- │ │ │ │ └─ properties # 系统认证相关配置属性
+ │ │ │ │ └─ satoken # Sa-Token 配置
│ │ │ ├─ model # 系统认证相关模型
│ │ │ │ ├─ request # 系统认证相关请求对象
│ │ │ │ └─ vo # 系统认证相关 VO(View Object)
@@ -197,6 +200,7 @@ continew-admin
├─ src
│ ├─ api # 请求接口
│ │ ├─ auth # 认证模块
+ │ │ ├─ common # 公共模块
│ │ └─ system # 系统管理模块
│ ├─ assets # 静态资源
│ │ ├─ images # 图片资源
diff --git a/continew-admin-common/pom.xml b/continew-admin-common/pom.xml
index 565242f9..8a0b50c8 100644
--- a/continew-admin-common/pom.xml
+++ b/continew-admin-common/pom.xml
@@ -59,6 +59,17 @@ limitations under the License.
+
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+
+ org.freemarker
+ freemarker
+
+
org.springframework.boot
@@ -126,5 +137,11 @@ limitations under the License.
org.redisson
redisson-spring-boot-starter
+
+
+
+ com.github.whvcse
+ easy-captcha
+
\ No newline at end of file
diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/config/properties/CaptchaProperties.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/properties/CaptchaProperties.java
similarity index 51%
rename from continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/config/properties/CaptchaProperties.java
rename to continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/properties/CaptchaProperties.java
index 5123ea89..e9e40ae3 100644
--- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/config/properties/CaptchaProperties.java
+++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/config/properties/CaptchaProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package top.charles7c.cnadmin.auth.config.properties;
+package top.charles7c.cnadmin.common.config.properties;
import java.awt.*;
@@ -43,65 +43,102 @@ import cn.hutool.core.util.StrUtil;
public class CaptchaProperties {
/**
- * 类型
+ * 图片验证码配置
*/
- private CaptchaTypeEnum type;
+ private CaptchaImage image;
/**
- * 缓存键的前缀
+ * 邮箱验证码配置
*/
- private String keyPrefix;
+ private CaptchaMail mail;
/**
- * 过期时间
+ * 图片验证码配置
*/
- private Long expirationInMinutes = 2L;
+ @Data
+ public static class CaptchaImage {
+ /**
+ * 类型
+ */
+ private CaptchaImageTypeEnum type;
- /**
- * 内容长度
- */
- private int length = 4;
+ /**
+ * 内容长度
+ */
+ private int length;
- /**
- * 宽度
- */
- private int width = 111;
+ /**
+ * 过期时间
+ */
+ private long expirationInMinutes;
- /**
- * 高度
- */
- private int height = 36;
+ /**
+ * 宽度
+ */
+ private int width = 111;
- /**
- * 字体
- */
- private String fontName;
+ /**
+ * 高度
+ */
+ private int height = 36;
- /**
- * 字体大小
- */
- private int fontSize = 25;
+ /**
+ * 字体
+ */
+ private String fontName;
- /**
- * 获取验证码对象
- *
- * @return 验证码对象
- */
- public Captcha getCaptcha() {
- Captcha captcha = ReflectUtil.newInstance(type.getClazz(), this.width, this.height);
- captcha.setLen(length);
- if (StrUtil.isNotBlank(this.fontName)) {
- captcha.setFont(new Font(this.fontName, Font.PLAIN, this.fontSize));
+ /**
+ * 字体大小
+ */
+ private int fontSize = 25;
+
+ /**
+ * 获取图片验证码对象
+ *
+ * @return 验证码对象
+ */
+ public Captcha getCaptcha() {
+ Captcha captcha = ReflectUtil.newInstance(type.getClazz(), this.width, this.height);
+ captcha.setLen(length);
+ if (StrUtil.isNotBlank(this.fontName)) {
+ captcha.setFont(new Font(this.fontName, Font.PLAIN, this.fontSize));
+ }
+ return captcha;
}
- return captcha;
}
/**
- * 验证码类型枚举
+ * 邮箱验证码配置
+ */
+ @Data
+ public static class CaptchaMail {
+ /**
+ * 内容长度
+ */
+ private int length;
+
+ /**
+ * 过期时间
+ */
+ private long expirationInMinutes;
+
+ /**
+ * 限制时间
+ */
+ private long limitInSeconds;
+
+ /**
+ * 模板路径
+ */
+ private String templatePath;
+ }
+
+ /**
+ * 图片验证码类型枚举
*/
@Getter
@RequiredArgsConstructor
- public enum CaptchaTypeEnum {
+ private enum CaptchaImageTypeEnum {
/**
* 算术
diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/consts/CacheConstants.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/consts/CacheConstants.java
index fe47bc03..6583d9df 100644
--- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/consts/CacheConstants.java
+++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/consts/CacheConstants.java
@@ -33,4 +33,14 @@ public class CacheConstants {
*/
public static final String LOGIN_USER_CACHE_KEY = "LOGIN_USER";
+ /**
+ * 验证码缓存键
+ */
+ public static final String CAPTCHA_CACHE_KEY = "CAPTCHA";
+
+ /**
+ * 限流缓存键
+ */
+ public static final String LIMIT_CACHE_KEY = "LIMIT";
+
}
diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java
index ac647e5d..b2b7a103 100644
--- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java
+++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java
@@ -162,8 +162,8 @@ public class GlobalExceptionHandler {
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(NotLoginException.class)
public R handleNotLoginException(NotLoginException e, HttpServletRequest request) {
- log.error("请求地址'{}',认证失败'{}',无法访问系统资源", request.getRequestURI(), e.getMessage());
- return R.fail(HttpStatus.UNAUTHORIZED.value(), "认证失败,无法访问系统资源");
+ log.error("请求地址'{}',认证失败,无法访问系统资源", request.getRequestURI(), e);
+ return R.fail(HttpStatus.UNAUTHORIZED.value(), "登录状态已过期,请重新登录");
}
/**
diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/CaptchaVO.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/CaptchaVO.java
similarity index 96%
rename from continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/CaptchaVO.java
rename to continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/CaptchaVO.java
index ac406707..7b80583c 100644
--- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/model/vo/CaptchaVO.java
+++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/CaptchaVO.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package top.charles7c.cnadmin.auth.model.vo;
+package top.charles7c.cnadmin.common.model.vo;
import java.io.Serializable;
diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/MailUtils.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/MailUtils.java
new file mode 100644
index 00000000..50de3499
--- /dev/null
+++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/MailUtils.java
@@ -0,0 +1,244 @@
+/*
+ * 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.util;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.List;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import lombok.AccessLevel;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.CharUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
+
+import top.charles7c.cnadmin.common.util.validate.CheckUtils;
+
+/**
+ * 邮件工具类
+ *
+ * @author Charles7c
+ * @since 2023/1/12 23:25
+ */
+@Data
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class MailUtils {
+
+ private static final JavaMailSender MAIL_SENDER = SpringUtil.getBean(JavaMailSender.class);
+
+ /**
+ * 发送文本邮件给单个人
+ *
+ * @param subject
+ * 主题
+ * @param content
+ * 内容
+ * @param to
+ * 收件人
+ * @throws MessagingException
+ * /
+ */
+ public static void sendText(String to, String subject, String content) throws MessagingException {
+ send(splitAddress(to), null, null, subject, content, false);
+ }
+
+ /**
+ * 发送 HTML 邮件给单个人
+ *
+ * @param subject
+ * 主题
+ * @param content
+ * 内容
+ * @param to
+ * 收件人
+ * @throws MessagingException
+ * /
+ */
+ public static void sendHtml(String to, String subject, String content) throws MessagingException {
+ send(splitAddress(to), null, null, subject, content, true);
+ }
+
+ /**
+ * 发送 HTML 邮件给单个人
+ *
+ * @param subject
+ * 主题
+ * @param content
+ * 内容
+ * @param to
+ * 收件人
+ * @param files
+ * 附件列表
+ * @throws MessagingException
+ * /
+ */
+ public static void sendHtml(String to, String subject, String content, File... files) throws MessagingException {
+ send(splitAddress(to), null, null, subject, content, true, files);
+ }
+
+ /**
+ * 发送 HTML 邮件给多个人
+ *
+ * @param subject
+ * 主题
+ * @param content
+ * 内容
+ * @param tos
+ * 收件人列表
+ * @param files
+ * 附件列表
+ * @throws MessagingException
+ * /
+ */
+ public static void sendHtml(Collection tos, String subject, String content, File... files)
+ throws MessagingException {
+ send(tos, null, null, subject, content, true, files);
+ }
+
+ /**
+ * 发送 HTML 邮件给多个人
+ *
+ * @param subject
+ * 主题
+ * @param content
+ * 内容
+ * @param tos
+ * 收件人列表
+ * @param ccs
+ * 抄送人列表
+ * @param files
+ * 附件列表
+ * @throws MessagingException
+ * /
+ */
+ public static void sendHtml(Collection tos, Collection ccs, String subject, String content,
+ File... files) throws MessagingException {
+ send(tos, ccs, null, subject, content, true, files);
+ }
+
+ /**
+ * 发送 HTML 邮件给多个人
+ *
+ * @param subject
+ * 主题
+ * @param content
+ * 内容
+ * @param tos
+ * 收件人列表
+ * @param ccs
+ * 抄送人列表
+ * @param bccs
+ * 密送人列表
+ * @param files
+ * 附件列表
+ * @throws MessagingException
+ * /
+ */
+ public static void sendHtml(Collection tos, Collection ccs, Collection bccs, String subject,
+ String content, File... files) throws MessagingException {
+ send(tos, ccs, bccs, subject, content, true, files);
+ }
+
+ /**
+ * 发送邮件给多个人
+ *
+ * @param tos
+ * 收件人列表
+ * @param ccs
+ * 抄送人列表
+ * @param bccs
+ * 密送人列表
+ * @param subject
+ * 主题
+ * @param content
+ * 内容
+ * @param isHtml
+ * 是否是 HTML
+ * @param files
+ * 附件列表
+ * @throws MessagingException
+ * /
+ */
+ public static void send(Collection tos, Collection ccs, Collection bccs, String subject,
+ String content, boolean isHtml, File... files) throws MessagingException {
+ CheckUtils.exIfCondition(() -> CollUtil.isEmpty(tos), "请至少指定一名收件人");
+ MimeMessage mimeMessage = MAIL_SENDER.createMimeMessage();
+ MimeMessageHelper messageHelper =
+ new MimeMessageHelper(mimeMessage, true, StandardCharsets.UTF_8.displayName());
+
+ // 设置基本信息
+ messageHelper.setFrom(SpringUtil.getProperty("spring.mail.username"));
+ messageHelper.setSubject(subject);
+ messageHelper.setText(content, isHtml);
+
+ // 设置收信人
+ // 抄送人
+ if (CollUtil.isNotEmpty(ccs)) {
+ messageHelper.setCc(ccs.toArray(new String[0]));
+ }
+ // 密送人
+ if (CollUtil.isNotEmpty(bccs)) {
+ messageHelper.setBcc(bccs.toArray(new String[0]));
+ }
+ // 收件人
+ messageHelper.setTo(tos.toArray(new String[0]));
+
+ // 设置附件
+ if (ArrayUtil.isNotEmpty(files)) {
+ for (File file : files) {
+ messageHelper.addAttachment(file.getName(), file);
+ }
+ }
+
+ // 发送邮件
+ MAIL_SENDER.send(mimeMessage);
+ }
+
+ /**
+ * 将多个联系人转为列表,分隔符为逗号或者分号
+ *
+ * @param addresses
+ * 多个联系人,如果为空返回null
+ * @return 联系人列表
+ */
+ private static List splitAddress(String addresses) {
+ if (StrUtil.isBlank(addresses)) {
+ return null;
+ }
+
+ List result;
+ if (StrUtil.contains(addresses, CharUtil.COMMA)) {
+ result = StrUtil.splitTrim(addresses, CharUtil.COMMA);
+ } else if (StrUtil.contains(addresses, ';')) {
+ result = StrUtil.splitTrim(addresses, ';');
+ } else {
+ result = CollUtil.newArrayList(addresses);
+ }
+ return result;
+ }
+}
diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/TemplateUtils.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/TemplateUtils.java
new file mode 100644
index 00000000..5197fee9
--- /dev/null
+++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/TemplateUtils.java
@@ -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.cnadmin.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);
+ }
+}
diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/CheckUtils.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/CheckUtils.java
index a94b6ad9..02cfb549 100644
--- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/CheckUtils.java
+++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/CheckUtils.java
@@ -35,18 +35,6 @@ public class CheckUtils extends Validator {
private static final Class EXCEPTION_TYPE = ServiceException.class;
- /**
- * 如果为空,抛出异常
- *
- * @param obj
- * 被检测的对象
- * @param message
- * 错误信息
- */
- public static void exIfNull(Object obj, String message) {
- exIfNull(obj, message, EXCEPTION_TYPE);
- }
-
/**
* 如果为空,抛出异常
*
@@ -59,6 +47,18 @@ public class CheckUtils extends Validator {
exIfBlank(str, message, EXCEPTION_TYPE);
}
+ /**
+ * 如果不为空,抛出异常
+ *
+ * @param str
+ * 被检测的字符串
+ * @param message
+ * 错误信息
+ */
+ public static void exIfNotBlank(CharSequence str, String message) {
+ exIfNotBlank(str, message, EXCEPTION_TYPE);
+ }
+
/**
* 如果相同,抛出异常
*
@@ -87,6 +87,58 @@ public class CheckUtils extends Validator {
exIfNotEqual(obj1, obj2, message, EXCEPTION_TYPE);
}
+ /**
+ * 如果相同,抛出异常(不区分大小写)
+ *
+ * @param str1
+ * 要比较的字符串1
+ * @param str2
+ * 要比较的字符串2
+ * @param message
+ * 错误信息
+ */
+ public static void exIfEqualIgnoreCase(CharSequence str1, CharSequence str2, String message) {
+ exIfEqualIgnoreCase(str1, str2, message, EXCEPTION_TYPE);
+ }
+
+ /**
+ * 如果不相同,抛出异常(不区分大小写)
+ *
+ * @param str1
+ * 要比较的字符串1
+ * @param str2
+ * 要比较的字符串2
+ * @param message
+ * 错误信息
+ */
+ public static void exIfNotEqualIgnoreCase(CharSequence str1, CharSequence str2, String message) {
+ exIfNotEqualIgnoreCase(str1, str2, message, EXCEPTION_TYPE);
+ }
+
+ /**
+ * 如果为空,抛出异常
+ *
+ * @param obj
+ * 被检测的对象
+ * @param message
+ * 错误信息
+ */
+ public static void exIfNull(Object obj, String message) {
+ exIfNull(obj, message, EXCEPTION_TYPE);
+ }
+
+ /**
+ * 如果不为空,抛出异常
+ *
+ * @param obj
+ * 被检测的对象
+ * @param message
+ * 错误信息
+ */
+ public static void exIfNotNull(Object obj, String message) {
+ exIfNotNull(obj, message, EXCEPTION_TYPE);
+ }
+
/**
* 如果条件成立,抛出异常
*
diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/ValidationUtils.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/ValidationUtils.java
index 9451405c..7f26d3c4 100644
--- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/ValidationUtils.java
+++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/ValidationUtils.java
@@ -35,18 +35,6 @@ public class ValidationUtils extends Validator {
private static final Class EXCEPTION_TYPE = BadRequestException.class;
- /**
- * 如果为空,抛出异常
- *
- * @param obj
- * 被检测的对象
- * @param message
- * 错误信息
- */
- public static void exIfNull(Object obj, String message) {
- exIfNull(obj, message, EXCEPTION_TYPE);
- }
-
/**
* 如果为空,抛出异常
*
@@ -59,6 +47,18 @@ public class ValidationUtils extends Validator {
exIfBlank(str, message, EXCEPTION_TYPE);
}
+ /**
+ * 如果不为空,抛出异常
+ *
+ * @param str
+ * 被检测的字符串
+ * @param message
+ * 错误信息
+ */
+ public static void exIfNotBlank(CharSequence str, String message) {
+ exIfNotBlank(str, message, EXCEPTION_TYPE);
+ }
+
/**
* 如果相同,抛出异常
*
@@ -87,6 +87,58 @@ public class ValidationUtils extends Validator {
exIfNotEqual(obj1, obj2, message, EXCEPTION_TYPE);
}
+ /**
+ * 如果相同,抛出异常(不区分大小写)
+ *
+ * @param str1
+ * 要比较的字符串1
+ * @param str2
+ * 要比较的字符串2
+ * @param message
+ * 错误信息
+ */
+ public static void exIfEqualIgnoreCase(CharSequence str1, CharSequence str2, String message) {
+ exIfEqualIgnoreCase(str1, str2, message, EXCEPTION_TYPE);
+ }
+
+ /**
+ * 如果不相同,抛出异常(不区分大小写)
+ *
+ * @param str1
+ * 要比较的字符串1
+ * @param str2
+ * 要比较的字符串2
+ * @param message
+ * 错误信息
+ */
+ public static void exIfNotEqualIgnoreCase(CharSequence str1, CharSequence str2, String message) {
+ exIfNotEqualIgnoreCase(str1, str2, message, EXCEPTION_TYPE);
+ }
+
+ /**
+ * 如果为空,抛出异常
+ *
+ * @param obj
+ * 被检测的对象
+ * @param message
+ * 错误信息
+ */
+ public static void exIfNull(Object obj, String message) {
+ exIfNull(obj, message, EXCEPTION_TYPE);
+ }
+
+ /**
+ * 如果不为空,抛出异常
+ *
+ * @param obj
+ * 被检测的对象
+ * @param message
+ * 错误信息
+ */
+ public static void exIfNotNull(Object obj, String message) {
+ exIfNotNull(obj, message, EXCEPTION_TYPE);
+ }
+
/**
* 如果条件成立,抛出异常
*
diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/Validator.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/Validator.java
index 613cec33..6ee21521 100644
--- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/Validator.java
+++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/util/validate/Validator.java
@@ -25,6 +25,8 @@ import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
/**
+ * 校验器
+ *
* @author Charles7c
* @since 2023/1/2 22:12
*/
@@ -32,23 +34,6 @@ import cn.hutool.core.util.StrUtil;
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Validator {
- /**
- * 如果为空,抛出异常
- *
- * @param obj
- * 被检测的对象
- * @param message
- * 错误信息
- * @param exceptionType
- * 异常类型
- */
- protected static void exIfNull(Object obj, String message, Class extends RuntimeException> exceptionType) {
- if (obj == null) {
- log.error(message);
- throw ReflectUtil.newInstance(exceptionType, message);
- }
- }
-
/**
* 如果为空,抛出异常
*
@@ -59,11 +44,23 @@ public class Validator {
* @param exceptionType
* 异常类型
*/
- public static void exIfBlank(CharSequence str, String message, Class extends RuntimeException> exceptionType) {
- if (StrUtil.isBlank(str)) {
- log.error(message);
- throw ReflectUtil.newInstance(exceptionType, message);
- }
+ protected static void exIfBlank(CharSequence str, String message, Class extends RuntimeException> exceptionType) {
+ exIfCondition(() -> StrUtil.isBlank(str), message, exceptionType);
+ }
+
+ /**
+ * 如果不为空,抛出异常
+ *
+ * @param str
+ * 被检测的字符串
+ * @param message
+ * 错误信息
+ * @param exceptionType
+ * 异常类型
+ */
+ protected static void exIfNotBlank(CharSequence str, String message,
+ Class extends RuntimeException> exceptionType) {
+ exIfCondition(() -> StrUtil.isNotBlank(str), message, exceptionType);
}
/**
@@ -78,12 +75,9 @@ public class Validator {
* @param exceptionType
* 异常类型
*/
- public static void exIfEqual(Object obj1, Object obj2, String message,
+ protected static void exIfEqual(Object obj1, Object obj2, String message,
Class extends RuntimeException> exceptionType) {
- if (ObjectUtil.equals(obj1, obj2)) {
- log.error(message);
- throw ReflectUtil.newInstance(exceptionType, message);
- }
+ exIfCondition(() -> ObjectUtil.equal(obj1, obj2), message, exceptionType);
}
/**
@@ -98,12 +92,71 @@ public class Validator {
* @param exceptionType
* 异常类型
*/
- public static void exIfNotEqual(Object obj1, Object obj2, String message,
+ protected static void exIfNotEqual(Object obj1, Object obj2, String message,
Class extends RuntimeException> exceptionType) {
- if (ObjectUtil.notEqual(obj1, obj2)) {
- log.error(message);
- throw ReflectUtil.newInstance(exceptionType, message);
- }
+ exIfCondition(() -> ObjectUtil.notEqual(obj1, obj2), message, exceptionType);
+ }
+
+ /**
+ * 如果相同,抛出异常(不区分大小写)
+ *
+ * @param str1
+ * 要比较的字符串1
+ * @param str2
+ * 要比较的字符串2
+ * @param message
+ * 错误信息
+ * @param exceptionType
+ * 异常类型
+ */
+ protected static void exIfEqualIgnoreCase(CharSequence str1, CharSequence str2, String message,
+ Class extends RuntimeException> exceptionType) {
+ exIfCondition(() -> StrUtil.equalsIgnoreCase(str1, str2), message, exceptionType);
+ }
+
+ /**
+ * 如果不相同,抛出异常(不区分大小写)
+ *
+ * @param str1
+ * 要比较的字符串1
+ * @param str2
+ * 要比较的字符串2
+ * @param message
+ * 错误信息
+ * @param exceptionType
+ * 异常类型
+ */
+ protected static void exIfNotEqualIgnoreCase(CharSequence str1, CharSequence str2, String message,
+ Class extends RuntimeException> exceptionType) {
+ exIfCondition(() -> !StrUtil.equalsIgnoreCase(str1, str2), message, exceptionType);
+ }
+
+ /**
+ * 如果为空,抛出异常
+ *
+ * @param obj
+ * 被检测的对象
+ * @param message
+ * 错误信息
+ * @param exceptionType
+ * 异常类型
+ */
+ protected static void exIfNull(Object obj, String message, Class extends RuntimeException> exceptionType) {
+ exIfCondition(() -> obj == null, message, exceptionType);
+ }
+
+ /**
+ * 如果不为空,抛出异常
+ *
+ * @param obj
+ * 被检测的对象
+ * @param message
+ * 错误信息
+ * @param exceptionType
+ * 异常类型
+ */
+ protected static void exIfNotNull(Object obj, String message, Class extends RuntimeException> exceptionType) {
+ exIfCondition(() -> obj != null, message, exceptionType);
}
/**
@@ -116,7 +169,7 @@ public class Validator {
* @param exceptionType
* 异常类型
*/
- public static void exIfCondition(java.util.function.BooleanSupplier conditionSupplier, String message,
+ protected static void exIfCondition(java.util.function.BooleanSupplier conditionSupplier, String message,
Class extends RuntimeException> exceptionType) {
if (conditionSupplier != null && conditionSupplier.getAsBoolean()) {
log.error(message);
diff --git a/continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/interceptor/LogInterceptor.java b/continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/interceptor/LogInterceptor.java
index 7aaec9f2..d777f27b 100644
--- a/continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/interceptor/LogInterceptor.java
+++ b/continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/interceptor/LogInterceptor.java
@@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
@@ -65,20 +66,21 @@ import top.charles7c.cnadmin.monitor.model.entity.SysLog;
public class LogInterceptor implements HandlerInterceptor {
private final LogProperties operationLogProperties;
+ private static final String ENCRYPT_SYMBOL = "****************";
@Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
- if (!checkIsNeedRecord(handler, request)) {
- return true;
+ public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response,
+ @NonNull Object handler) {
+ if (checkIsNeedRecord(handler, request)) {
+ // 记录操作时间
+ this.logCreateTime();
}
-
- // 记录操作时间
- this.logCreateTime();
return true;
}
@Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
+ public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response,
+ @NonNull Object handler, Exception e) {
// 记录请求耗时及异常信息
SysLog sysLog = this.logElapsedTimeAndException();
if (sysLog == null) {
@@ -203,6 +205,7 @@ public class LogInterceptor implements HandlerInterceptor {
* 待脱敏数据
* @return 脱敏后的 JSON 字符串数据
*/
+ @SuppressWarnings("unchecked")
private String desensitize(Map waitDesensitizeData) {
String desensitizeDataStr = JSONUtil.toJsonStr(waitDesensitizeData);
try {
@@ -211,9 +214,9 @@ public class LogInterceptor implements HandlerInterceptor {
}
for (String desensitizeProperty : operationLogProperties.getDesensitize()) {
- waitDesensitizeData.computeIfPresent(desensitizeProperty, (k, v) -> "****************");
- waitDesensitizeData.computeIfPresent(desensitizeProperty.toLowerCase(), (k, v) -> "****************");
- waitDesensitizeData.computeIfPresent(desensitizeProperty.toUpperCase(), (k, v) -> "****************");
+ waitDesensitizeData.computeIfPresent(desensitizeProperty, (k, v) -> ENCRYPT_SYMBOL);
+ waitDesensitizeData.computeIfPresent(desensitizeProperty.toLowerCase(), (k, v) -> ENCRYPT_SYMBOL);
+ waitDesensitizeData.computeIfPresent(desensitizeProperty.toUpperCase(), (k, v) -> ENCRYPT_SYMBOL);
}
return JSONUtil.toJsonStr(waitDesensitizeData);
} catch (Exception ignored) {
diff --git a/continew-admin-system/pom.xml b/continew-admin-system/pom.xml
index 116d21d4..f33e7e55 100644
--- a/continew-admin-system/pom.xml
+++ b/continew-admin-system/pom.xml
@@ -32,12 +32,6 @@ limitations under the License.
系统管理模块(存放系统管理模块相关功能,例如:部门管理、角色管理、用户管理等)
-
-
- com.github.whvcse
- easy-captcha
-
-
top.charles7c
diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java
index 21d14d40..e3211a46 100644
--- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java
+++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/auth/service/impl/LoginServiceImpl.java
@@ -52,7 +52,7 @@ public class LoginServiceImpl implements LoginService {
// 校验
ValidationUtils.exIfNull(sysUser, "用户名或密码错误");
Long userId = sysUser.getUserId();
- ValidationUtils.exIfNotEqual(sysUser.getPassword(), SecureUtils.md5Salt(password, userId.toString()),
+ ValidationUtils.exIfNotEqual(SecureUtils.md5Salt(password, userId.toString()), sysUser.getPassword(),
"用户名或密码错误");
ValidationUtils.exIfEqual(DisEnableStatusEnum.DISABLE, sysUser.getStatus(), "此账号已被禁用,如有疑问,请联系管理员");
diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/UpdateBasicInfoRequest.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/UpdateBasicInfoRequest.java
index 9bb5569e..d746b828 100644
--- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/UpdateBasicInfoRequest.java
+++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/UpdateBasicInfoRequest.java
@@ -52,6 +52,6 @@ public class UpdateBasicInfoRequest implements Serializable {
* 性别(0未知 1男 2女)
*/
@Schema(description = "性别(0未知 1男 2女)", type = "Integer", allowableValues = {"0", "1", "2"})
- @NotNull(message = "非法性别")
+ @NotNull(message = "性别非法")
private GenderEnum gender;
}
diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/UpdateEmailRequest.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/UpdateEmailRequest.java
new file mode 100644
index 00000000..ee0b1132
--- /dev/null
+++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/model/request/UpdateEmailRequest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.Pattern;
+
+import lombok.Data;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import org.hibernate.validator.constraints.Length;
+
+import cn.hutool.core.lang.RegexPool;
+
+/**
+ * 修改邮箱信息
+ *
+ * @author Charles7c
+ * @since 2023/1/12 20:18
+ */
+@Data
+@Schema(description = "修改邮箱信息")
+public class UpdateEmailRequest implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 新邮箱
+ */
+ @Schema(description = "新邮箱")
+ @NotBlank(message = "新邮箱不能为空")
+ @Pattern(regexp = RegexPool.EMAIL, message = "邮箱格式错误")
+ private String newEmail;
+
+ /**
+ * 验证码
+ */
+ @Schema(description = "验证码")
+ @NotBlank(message = "验证码不能为空")
+ @Length(max = 6, message = "验证码非法")
+ private String captcha;
+
+ /**
+ * 当前密码(加密后)
+ */
+ @Schema(description = "当前密码(加密后)")
+ @NotBlank(message = "当前密码不能为空")
+ private String currentPassword;
+}
diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/UserService.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/UserService.java
index ce4afa9c..35062b6a 100644
--- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/UserService.java
+++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/UserService.java
@@ -67,4 +67,16 @@ public interface UserService {
* 用户 ID
*/
void updatePassword(String oldPassword, String newPassword, Long userId);
+
+ /**
+ * 修改邮箱
+ *
+ * @param newEmail
+ * 新邮箱
+ * @param currentPassword
+ * 当前密码
+ * @param userId
+ * 用户ID
+ */
+ void updateEmail(String newEmail, String currentPassword, Long userId);
}
diff --git a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/UserServiceImpl.java b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/UserServiceImpl.java
index 5aabfca5..1600a032 100644
--- a/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/UserServiceImpl.java
+++ b/continew-admin-system/src/main/java/top/charles7c/cnadmin/system/service/impl/UserServiceImpl.java
@@ -104,7 +104,7 @@ public class UserServiceImpl implements UserService {
@Transactional(rollbackFor = Exception.class)
public void updatePassword(String oldPassword, String newPassword, Long userId) {
SysUser sysUser = this.getById(userId);
- ValidationUtils.exIfNotEqual(sysUser.getPassword(), SecureUtils.md5Salt(oldPassword, userId.toString()),
+ ValidationUtils.exIfNotEqual(SecureUtils.md5Salt(oldPassword, userId.toString()), sysUser.getPassword(),
"当前密码错误");
// 更新密码和密码重置时间
@@ -120,6 +120,27 @@ public class UserServiceImpl implements UserService {
LoginHelper.updateLoginUser(loginUser);
}
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void updateEmail(String newEmail, String currentPassword, Long userId) {
+ // 校验
+ SysUser sysUser = this.getById(userId);
+ ValidationUtils.exIfNotEqual(SecureUtils.md5Salt(currentPassword, userId.toString()), sysUser.getPassword(),
+ "当前密码错误");
+ Long count = userMapper.selectCount(Wrappers.lambdaQuery().eq(SysUser::getEmail, newEmail));
+ ValidationUtils.exIfCondition(() -> count > 0, "邮箱已绑定其他账号,请更换其他邮箱");
+ ValidationUtils.exIfEqual(newEmail, sysUser.getEmail(), "新邮箱不能与当前邮箱相同");
+
+ // 更新邮箱
+ userMapper.update(null,
+ new LambdaUpdateWrapper().set(SysUser::getEmail, newEmail).eq(SysUser::getUserId, userId));
+
+ // 更新登录用户信息
+ LoginUser loginUser = LoginHelper.getLoginUser();
+ loginUser.setEmail(newEmail);
+ LoginHelper.updateLoginUser(loginUser);
+ }
+
/**
* 根据 ID 查询
*
diff --git a/continew-admin-ui/package.json b/continew-admin-ui/package.json
index b4d5de7f..76dec468 100644
--- a/continew-admin-ui/package.json
+++ b/continew-admin-ui/package.json
@@ -1,6 +1,6 @@
{
"name": "continew-admin-ui",
- "description": "ContiNew-Admin (incubating) 中后台管理框架,Continue New Admin,持续以最新流行技术栈构建。",
+ "description": "ContiNew Admin 中后台管理框架(孵化中),Continue New Admin,持续以最新流行技术栈构建。",
"version": "0.0.1-SNAPSHOT",
"private": true,
"author": "Charles7c",
diff --git a/continew-admin-ui/src/api/auth/login.ts b/continew-admin-ui/src/api/auth/login.ts
index 86e2cc05..4a9533d8 100644
--- a/continew-admin-ui/src/api/auth/login.ts
+++ b/continew-admin-ui/src/api/auth/login.ts
@@ -2,14 +2,6 @@ import axios from 'axios';
import type { RouteRecordNormalized } from 'vue-router';
import { UserState } from '@/store/modules/login/types';
-export interface ImageCaptchaRes {
- uuid: string;
- img: string;
-}
-export function getImageCaptcha() {
- return axios.get('/captcha/img');
-}
-
export interface LoginReq {
username: string;
password: string;
diff --git a/continew-admin-ui/src/api/common/captcha.ts b/continew-admin-ui/src/api/common/captcha.ts
new file mode 100644
index 00000000..5ae9c560
--- /dev/null
+++ b/continew-admin-ui/src/api/common/captcha.ts
@@ -0,0 +1,22 @@
+import axios from 'axios';
+import qs from 'query-string';
+
+export interface ImageCaptchaRes {
+ uuid: string;
+ img: string;
+}
+export function getImageCaptcha() {
+ return axios.get('/common/captcha/img');
+}
+
+export interface MailCaptchaReq {
+ email: string;
+}
+export function getMailCaptcha(params: MailCaptchaReq) {
+ return axios.get('/common/captcha/mail', {
+ params,
+ paramsSerializer: (obj) => {
+ return qs.stringify(obj);
+ },
+ });
+}
diff --git a/continew-admin-ui/src/api/system/user-center.ts b/continew-admin-ui/src/api/system/user-center.ts
index 4e68ddf9..e4af5473 100644
--- a/continew-admin-ui/src/api/system/user-center.ts
+++ b/continew-admin-ui/src/api/system/user-center.ts
@@ -27,4 +27,13 @@ export interface UpdatePasswordReq {
}
export function updatePassword(req: UpdatePasswordReq) {
return axios.patch('/system/user/center/password', req);
+}
+
+export interface UpdateEmailReq {
+ newEmail: string;
+ captcha: string;
+ currentPassword: string;
+}
+export function updateEmail(req: UpdateEmailReq) {
+ return axios.patch('/system/user/center/email', req);
}
\ No newline at end of file
diff --git a/continew-admin-ui/src/components/footer/index.vue b/continew-admin-ui/src/components/footer/index.vue
index 02a70984..215e8aff 100644
--- a/continew-admin-ui/src/components/footer/index.vue
+++ b/continew-admin-ui/src/components/footer/index.vue
@@ -2,6 +2,8 @@
diff --git a/continew-admin-ui/src/components/navbar/index.vue b/continew-admin-ui/src/components/navbar/index.vue
index 7077f234..120385fb 100644
--- a/continew-admin-ui/src/components/navbar/index.vue
+++ b/continew-admin-ui/src/components/navbar/index.vue
@@ -190,7 +190,7 @@
import useLocale from '@/hooks/locale';
import useUser from '@/hooks/user';
import Menu from '@/components/menu/index.vue';
- import getAvatar from "@/utils/avatar";
+ import getAvatar from '@/utils/avatar';
import MessageBox from '../message-box/index.vue';
const appStore = useAppStore();
diff --git a/continew-admin-ui/src/hooks/axios.d.ts b/continew-admin-ui/src/hooks/axios.d.ts
index 0a982b49..64e4b08a 100644
--- a/continew-admin-ui/src/hooks/axios.d.ts
+++ b/continew-admin-ui/src/hooks/axios.d.ts
@@ -1,4 +1,4 @@
-import axios, { Axios, AxiosResponse, AxiosRequestConfig } from "axios";
+import axios, { Axios, AxiosResponse, AxiosRequestConfig } from 'axios';
declare module "axios" {
interface AxiosResponse {
diff --git a/continew-admin-ui/src/hooks/user.ts b/continew-admin-ui/src/hooks/user.ts
index 84fa75f8..11939604 100644
--- a/continew-admin-ui/src/hooks/user.ts
+++ b/continew-admin-ui/src/hooks/user.ts
@@ -1,5 +1,5 @@
import { useRouter } from 'vue-router';
-import { useI18n } from "vue-i18n";
+import { useI18n } from 'vue-i18n';
import { Message } from '@arco-design/web-vue';
import { useLoginStore } from '@/store';
diff --git a/continew-admin-ui/src/store/modules/login/index.ts b/continew-admin-ui/src/store/modules/login/index.ts
index 30ffd0fb..41c77d0c 100644
--- a/continew-admin-ui/src/store/modules/login/index.ts
+++ b/continew-admin-ui/src/store/modules/login/index.ts
@@ -1,11 +1,11 @@
import { defineStore } from 'pinia';
import {
- getImageCaptcha as getCaptcha,
login as userLogin,
logout as userLogout,
getUserInfo,
LoginReq,
} from '@/api/auth/login';
+import { getImageCaptcha as getCaptcha } from '@/api/common/captcha';
import { setToken, clearToken } from '@/utils/auth';
import { removeRouteListener } from '@/utils/route-listener';
import { UserState } from './types';
diff --git a/continew-admin-ui/src/views/dashboard/monitor/components/studio.vue b/continew-admin-ui/src/views/dashboard/monitor/components/studio.vue
index a356bdcc..31f683c1 100644
--- a/continew-admin-ui/src/views/dashboard/monitor/components/studio.vue
+++ b/continew-admin-ui/src/views/dashboard/monitor/components/studio.vue
@@ -29,7 +29,7 @@
diff --git a/continew-admin-ui/src/views/login/components/login-form.vue b/continew-admin-ui/src/views/login/components/login-form.vue
index 632f7a6e..ab1899be 100644
--- a/continew-admin-ui/src/views/login/components/login-form.vue
+++ b/continew-admin-ui/src/views/login/components/login-form.vue
@@ -37,7 +37,7 @@
:placeholder="$t('login.form.placeholder.password')"
size="large"
allow-clear
- max-length="50"
+ max-length="32"
>
@@ -82,13 +82,13 @@
-
+
diff --git a/continew-admin-ui/src/views/system/user/center/components/security-settings/update-pwd.vue b/continew-admin-ui/src/views/system/user/center/components/security-settings/update-pwd.vue
index 1ac27dbe..61bf017b 100644
--- a/continew-admin-ui/src/views/system/user/center/components/security-settings/update-pwd.vue
+++ b/continew-admin-ui/src/views/system/user/center/components/security-settings/update-pwd.vue
@@ -22,12 +22,14 @@
-
-
+
+
@@ -52,7 +54,7 @@
:placeholder="$t('userCenter.securitySettings.updatePwd.form.placeholder.newPassword')"
size="large"
allow-clear
- max-length="50"
+ max-length="32"
>
@@ -66,7 +68,7 @@
:placeholder="$t('userCenter.securitySettings.updatePwd.form.placeholder.rePassword')"
size="large"
allow-clear
- max-length="50"
+ max-length="32"
>
@@ -75,14 +77,14 @@