diff --git a/weblog-springboot-082/pom.xml b/weblog-springboot-082/pom.xml
new file mode 100644
index 0000000..9996a10
--- /dev/null
+++ b/weblog-springboot-082/pom.xml
@@ -0,0 +1,174 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+
+ 2.6.3
+
+
+
+ com.quanxiaoha
+ weblog-springboot
+ ${revision}
+ weblog-springboot
+
+ 前后端分离博客 Weblog By 犬小哈
+
+
+ pom
+
+
+
+
+ weblog-web
+
+ weblog-module-admin
+
+ weblog-module-common
+
+ weblog-module-jwt
+
+
+
+
+
+
+ 0.0.1-SNAPSHOT
+ 1.8
+ UTF-8
+
+ ${java.version}
+ ${java.version}
+
+
+ 1.18.28
+ 31.1-jre
+ 3.12.0
+ 2.15.2
+ 4.3.0
+ 3.5.2
+ 3.9.1
+ 0.11.2
+
+
+
+
+
+
+ com.quanxiaoha
+ weblog-module-admin
+ ${revision}
+
+
+
+ com.quanxiaoha
+ weblog-module-common
+ ${revision}
+
+
+
+ com.quanxiaoha
+ weblog-module-jwt
+ ${revision}
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ ${jackson.version}
+
+
+
+
+
+ com.github.xiaoymin
+ knife4j-openapi2-spring-boot-starter
+ ${knife4j.version}
+
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ ${mybatis-plus.version}
+
+
+
+ p6spy
+ p6spy
+ ${p6spy.version}
+
+
+
+
+ io.jsonwebtoken
+ jjwt-api
+ ${jjwt.version}
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ ${jjwt.version}
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ ${jjwt.version}
+
+
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
+
+
+
+ aliyunmaven
+ aliyun
+ https://maven.aliyun.com/repository/public
+
+
+
diff --git a/weblog-springboot-082/weblog-module-admin/.gitignore b/weblog-springboot-082/weblog-module-admin/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/weblog-springboot-082/weblog-module-admin/pom.xml b/weblog-springboot-082/weblog-module-admin/pom.xml
new file mode 100644
index 0000000..517b8f3
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/pom.xml
@@ -0,0 +1,67 @@
+
+
+ 4.0.0
+
+
+ com.quanxiaoha
+ weblog-springboot
+ ${revision}
+
+
+ com.quanxiaoha
+ weblog-module-admin
+ weblog-module-admin
+ weblog-admin (负责管理后台相关功能)
+
+
+
+ com.quanxiaoha
+ weblog-module-common
+
+
+
+ com.quanxiaoha
+ weblog-module-jwt
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ com.github.xiaoymin
+ knife4j-openapi2-spring-boot-starter
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+
+ jakarta.validation
+ jakarta.validation-api
+
+
+ org.hibernate.validator
+ hibernate-validator
+
+
+
+
+
+
\ No newline at end of file
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/Knife4jAdminConfig.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/Knife4jAdminConfig.java
new file mode 100644
index 0000000..3c2b2da
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/Knife4jAdminConfig.java
@@ -0,0 +1,53 @@
+package com.quanxiaoha.weblog.admin.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-08-16 7:53
+ * @description: Knife4j 配置
+ **/
+@Configuration
+@EnableSwagger2WebMvc
+@Profile("dev") // 只在 dev 环境中开启
+public class Knife4jAdminConfig {
+
+ @Bean("adminApi")
+ public Docket createApiDoc() {
+ Docket docket = new Docket(DocumentationType.SWAGGER_2)
+ .apiInfo(buildApiInfo())
+ // 分组名称
+ .groupName("Admin 后台接口")
+ .select()
+ // 这里指定 Controller 扫描包路径
+ .apis(RequestHandlerSelectors.basePackage("com.quanxiaoha.weblog.admin.controller"))
+ .paths(PathSelectors.any())
+ .build();
+ return docket;
+ }
+
+ /**
+ * 构建 API 信息
+ * @return
+ */
+ private ApiInfo buildApiInfo() {
+ return new ApiInfoBuilder()
+ .title("Weblog 博客 Admin 后台接口文档") // 标题
+ .description("Weblog 是一款由 Spring Boot + Vue 3.2 + Vite 4.3 开发的前后端分离博客。") // 描述
+ .termsOfServiceUrl("https://www.quanxiaoha.com/") // API 服务条款
+ .contact(new Contact("犬小哈", "https://www.quanxiaoha.com", "871361652@qq.com")) // 联系人
+ .version("1.0") // 版本号
+ .build();
+ }
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/WebSecurityConfig.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/WebSecurityConfig.java
new file mode 100644
index 0000000..f5fbac2
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/WebSecurityConfig.java
@@ -0,0 +1,65 @@
+package com.quanxiaoha.weblog.admin.config;
+
+import com.quanxiaoha.weblog.jwt.config.JwtAuthenticationSecurityConfig;
+import com.quanxiaoha.weblog.jwt.filter.TokenAuthenticationFilter;
+import com.quanxiaoha.weblog.jwt.handler.RestAccessDeniedHandler;
+import com.quanxiaoha.weblog.jwt.handler.RestAuthenticationEntryPoint;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-08-23 15:48
+ * @description: Spring Security 配置类
+ **/
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Autowired
+ private JwtAuthenticationSecurityConfig jwtAuthenticationSecurityConfig;
+ @Autowired
+ private RestAuthenticationEntryPoint authEntryPoint;
+ @Autowired
+ private RestAccessDeniedHandler deniedHandler;
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.csrf().disable(). // 禁用 csrf
+ formLogin().disable() // 禁用表单登录
+ .apply(jwtAuthenticationSecurityConfig) // 设置用户登录认证相关配置
+ .and()
+ .authorizeHttpRequests()
+ .mvcMatchers("/admin/**").authenticated() // 认证所有以 /admin 为前缀的 URL 资源
+ .anyRequest().permitAll() // 其他都需要放行,无需认证
+ .and()
+ .httpBasic().authenticationEntryPoint(authEntryPoint) // 处理用户未登录访问受保护的资源的情况
+ .and()
+ .exceptionHandling().accessDeniedHandler(deniedHandler) // 处理登录成功后访问受保护的资源,但是权限不够的情况
+ .and()
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 前后端分离,无需创建会话
+ .and()
+ .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) // 将 Token 校验过滤器添加到用户认证过滤器之前
+ ;
+ }
+
+ /**
+ * Token 校验过滤器
+ * @return
+ */
+ @Bean
+ public TokenAuthenticationFilter tokenAuthenticationFilter() {
+ return new TokenAuthenticationFilter();
+ }
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminCategoryController.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminCategoryController.java
new file mode 100644
index 0000000..6f8ea6d
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminCategoryController.java
@@ -0,0 +1,67 @@
+package com.quanxiaoha.weblog.admin.controller;
+
+import com.quanxiaoha.weblog.admin.model.vo.category.AddCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.DeleteCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO;
+import com.quanxiaoha.weblog.admin.service.AdminCategoryService;
+import com.quanxiaoha.weblog.admin.service.AdminUserService;
+import com.quanxiaoha.weblog.common.aspect.ApiOperationLog;
+import com.quanxiaoha.weblog.common.utils.PageResponse;
+import com.quanxiaoha.weblog.common.utils.Response;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:01
+ * @description: 分类
+ **/
+@RestController
+@RequestMapping("/admin")
+@Api(tags = "Admin 分类模块")
+public class AdminCategoryController {
+
+ @Autowired
+ private AdminCategoryService categoryService;
+
+ @PostMapping("/category/add")
+ @ApiOperation(value = "添加分类")
+ @ApiOperationLog(description = "添加分类")
+ @PreAuthorize("hasRole('ROLE_ADMIN')")
+ public Response addCategory(@RequestBody @Validated AddCategoryReqVO addCategoryReqVO) {
+ return categoryService.addCategory(addCategoryReqVO);
+ }
+
+ @PostMapping("/category/list")
+ @ApiOperation(value = "分类分页数据获取")
+ @ApiOperationLog(description = "分类分页数据获取")
+ public PageResponse findCategoryList(@RequestBody @Validated FindCategoryPageListReqVO findCategoryPageListReqVO) {
+ return categoryService.findCategoryList(findCategoryPageListReqVO);
+ }
+
+ @PostMapping("/category/delete")
+ @ApiOperation(value = "删除分类")
+ @ApiOperationLog(description = "删除分类")
+ @PreAuthorize("hasRole('ROLE_ADMIN')")
+ public Response deleteCategory(@RequestBody @Validated DeleteCategoryReqVO deleteCategoryReqVO) {
+ return categoryService.deleteCategory(deleteCategoryReqVO);
+ }
+
+ @PostMapping("/category/select/list")
+ @ApiOperation(value = "分类 Select 下拉列表数据获取")
+ @ApiOperationLog(description = "分类 Select 下拉列表数据获取")
+ public Response findCategorySelectList() {
+ return categoryService.findCategorySelectList();
+ }
+
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminTagController.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminTagController.java
new file mode 100644
index 0000000..e235f35
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminTagController.java
@@ -0,0 +1,66 @@
+package com.quanxiaoha.weblog.admin.controller;
+
+import com.quanxiaoha.weblog.admin.model.vo.category.AddCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.DeleteCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.tag.AddTagReqVO;
+import com.quanxiaoha.weblog.admin.service.AdminCategoryService;
+import com.quanxiaoha.weblog.admin.service.AdminTagService;
+import com.quanxiaoha.weblog.common.aspect.ApiOperationLog;
+import com.quanxiaoha.weblog.common.utils.PageResponse;
+import com.quanxiaoha.weblog.common.utils.Response;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:01
+ * @description: 标签模块
+ **/
+@RestController
+@RequestMapping("/admin")
+@Api(tags = "Admin 标签模块")
+public class AdminTagController {
+
+ @Autowired
+ private AdminTagService tagService;
+
+ @PostMapping("/tag/add")
+ @ApiOperation(value = "添加标签")
+ @ApiOperationLog(description = "添加标签")
+ public Response addTags(@RequestBody @Validated AddTagReqVO addTagReqVO) {
+ return tagService.addTags(addTagReqVO);
+ }
+
+ // @PostMapping("/category/list")
+ // @ApiOperation(value = "分类分页数据获取")
+ // @ApiOperationLog(description = "分类分页数据获取")
+ // public PageResponse findCategoryList(@RequestBody @Validated FindCategoryPageListReqVO findCategoryPageListReqVO) {
+ // return categoryService.findCategoryList(findCategoryPageListReqVO);
+ // }
+ //
+ // @PostMapping("/category/delete")
+ // @ApiOperation(value = "删除分类")
+ // @ApiOperationLog(description = "删除分类")
+ // @PreAuthorize("hasRole('ROLE_ADMIN')")
+ // public Response deleteCategory(@RequestBody @Validated DeleteCategoryReqVO deleteCategoryReqVO) {
+ // return categoryService.deleteCategory(deleteCategoryReqVO);
+ // }
+ //
+ // @PostMapping("/category/select/list")
+ // @ApiOperation(value = "分类 Select 下拉列表数据获取")
+ // @ApiOperationLog(description = "分类 Select 下拉列表数据获取")
+ // public Response findCategorySelectList() {
+ // return categoryService.findCategorySelectList();
+ // }
+
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminUserController.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminUserController.java
new file mode 100644
index 0000000..65d49ac
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminUserController.java
@@ -0,0 +1,46 @@
+package com.quanxiaoha.weblog.admin.controller;
+
+import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO;
+import com.quanxiaoha.weblog.admin.service.AdminUserService;
+import com.quanxiaoha.weblog.common.aspect.ApiOperationLog;
+import com.quanxiaoha.weblog.common.utils.Response;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:01
+ * @description: 用户
+ **/
+@RestController
+@RequestMapping("/admin")
+@Api(tags = "Admin 用户模块")
+public class AdminUserController {
+
+ @Autowired
+ private AdminUserService userService;
+
+ @PostMapping("/password/update")
+ @ApiOperation(value = "修改用户密码")
+ @ApiOperationLog(description = "修改用户密码")
+ @PreAuthorize("hasRole('ROLE_ADMIN')")
+ public Response updatePassword(@RequestBody @Validated UpdateAdminUserPasswordReqVO updateAdminUserPasswordReqVO) {
+ return userService.updatePassword(updateAdminUserPasswordReqVO);
+ }
+
+ @PostMapping("/user/info")
+ @ApiOperation(value = "获取用户信息")
+ @ApiOperationLog(description = "获取用户信息")
+ public Response findUserInfo() {
+ return userService.findUserInfo();
+ }
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/package-info.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/package-info.java
new file mode 100644
index 0000000..e84aac5
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:07
+ * @description: TODO
+ **/
+package com.quanxiaoha.weblog.admin.model;
\ No newline at end of file
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/AddCategoryReqVO.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/AddCategoryReqVO.java
new file mode 100644
index 0000000..ff250e1
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/AddCategoryReqVO.java
@@ -0,0 +1,30 @@
+package com.quanxiaoha.weblog.admin.model.vo.category;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:07
+ * @description: 分类新增
+ **/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "添加分类 VO")
+public class AddCategoryReqVO {
+
+ @NotBlank(message = "分类名称不能为空")
+ @Length(min = 1, max = 20, message = "分类名称字数限制 1 ~ 20 之间")
+ private String name;
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/DeleteCategoryReqVO.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/DeleteCategoryReqVO.java
new file mode 100644
index 0000000..26e55a1
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/DeleteCategoryReqVO.java
@@ -0,0 +1,29 @@
+package com.quanxiaoha.weblog.admin.model.vo.category;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:07
+ * @description: 删除分类
+ **/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "删除分类 VO")
+public class DeleteCategoryReqVO {
+
+ @NotNull(message = "分类 ID 不能为空")
+ private Long id;
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListReqVO.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListReqVO.java
new file mode 100644
index 0000000..3a26532
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListReqVO.java
@@ -0,0 +1,43 @@
+package com.quanxiaoha.weblog.admin.model.vo.category;
+
+import com.quanxiaoha.weblog.common.model.BasePageQuery;
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:07
+ * @description: 分类分页
+ **/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "查询分类分页数据入参 VO")
+public class FindCategoryPageListReqVO extends BasePageQuery {
+
+ /**
+ * 分类名称
+ */
+ private String name;
+
+ /**
+ * 创建的起始日期
+ */
+ private LocalDate startDate;
+
+ /**
+ * 创建的结束日期
+ */
+ private LocalDate endDate;
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListRspVO.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListRspVO.java
new file mode 100644
index 0000000..b49b5a0
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListRspVO.java
@@ -0,0 +1,40 @@
+package com.quanxiaoha.weblog.admin.model.vo.category;
+
+import com.quanxiaoha.weblog.common.model.BasePageQuery;
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:07
+ * @description: 分类分页
+ **/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class FindCategoryPageListRspVO {
+
+ /**
+ * 分类 ID
+ */
+ private Long id;
+
+ /**
+ * 分类名称
+ */
+ private String name;
+
+ /**
+ * 创建时间
+ */
+ private LocalDateTime createTime;
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/AddTagReqVO.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/AddTagReqVO.java
new file mode 100644
index 0000000..36d0a48
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/AddTagReqVO.java
@@ -0,0 +1,30 @@
+package com.quanxiaoha.weblog.admin.model.vo.tag;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:07
+ * @description: 标签新增
+ **/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "添加标签 VO")
+public class AddTagReqVO {
+
+ @NotEmpty(message = "标签集合不能为空")
+ private List tags;
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/FindUserInfoRspVO.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/FindUserInfoRspVO.java
new file mode 100644
index 0000000..13fcb86
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/FindUserInfoRspVO.java
@@ -0,0 +1,28 @@
+package com.quanxiaoha.weblog.admin.model.vo.user;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:07
+ * @description: 查询用户信息
+ **/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class FindUserInfoRspVO {
+ /**
+ * 用户名
+ */
+ private String username;
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/UpdateAdminUserPasswordReqVO.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/UpdateAdminUserPasswordReqVO.java
new file mode 100644
index 0000000..1107969
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/UpdateAdminUserPasswordReqVO.java
@@ -0,0 +1,31 @@
+package com.quanxiaoha.weblog.admin.model.vo.user;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import javax.validation.constraints.*;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:07
+ * @description: TODO
+ **/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "修改用户密码 VO")
+public class UpdateAdminUserPasswordReqVO {
+
+ @NotBlank(message = "用户名不能为空")
+ @ApiModelProperty(value = "用户名")
+ private String username;
+
+ @NotBlank(message = "密码不能为空")
+ @ApiModelProperty(value = "密码")
+ private String password;
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/package-info.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/package-info.java
new file mode 100644
index 0000000..8a825e4
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-08-16 9:28
+ * @description: TODO
+ **/
+package com.quanxiaoha.weblog.admin;
\ No newline at end of file
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminCategoryService.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminCategoryService.java
new file mode 100644
index 0000000..1a06d0d
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminCategoryService.java
@@ -0,0 +1,45 @@
+package com.quanxiaoha.weblog.admin.service;
+
+import com.quanxiaoha.weblog.admin.model.vo.category.AddCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.DeleteCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.tag.AddTagReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO;
+import com.quanxiaoha.weblog.common.utils.PageResponse;
+import com.quanxiaoha.weblog.common.utils.Response;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:03
+ * @description: TODO
+ **/
+public interface AdminCategoryService {
+ /**
+ * 添加分类
+ * @param addCategoryReqVO
+ * @return
+ */
+ Response addCategory(AddCategoryReqVO addCategoryReqVO);
+
+ /**
+ * 分类分页数据查询
+ * @param findCategoryPageListReqVO
+ * @return
+ */
+ PageResponse findCategoryList(FindCategoryPageListReqVO findCategoryPageListReqVO);
+
+ /**
+ * 删除分类
+ * @param deleteCategoryReqVO
+ * @return
+ */
+ Response deleteCategory(DeleteCategoryReqVO deleteCategoryReqVO);
+
+ /**
+ * 获取文章分类的 Select 列表数据
+ * @return
+ */
+ Response findCategorySelectList();
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminTagService.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminTagService.java
new file mode 100644
index 0000000..fa5dd21
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminTagService.java
@@ -0,0 +1,24 @@
+package com.quanxiaoha.weblog.admin.service;
+
+import com.quanxiaoha.weblog.admin.model.vo.category.AddCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.DeleteCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.tag.AddTagReqVO;
+import com.quanxiaoha.weblog.common.utils.PageResponse;
+import com.quanxiaoha.weblog.common.utils.Response;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:03
+ * @description: TODO
+ **/
+public interface AdminTagService {
+
+ /**
+ * 添加标签集合
+ * @param addTagReqVO
+ * @return
+ */
+ Response addTags(AddTagReqVO addTagReqVO);
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminUserService.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminUserService.java
new file mode 100644
index 0000000..53a26fe
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminUserService.java
@@ -0,0 +1,25 @@
+package com.quanxiaoha.weblog.admin.service;
+
+import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO;
+import com.quanxiaoha.weblog.common.utils.Response;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:03
+ * @description: TODO
+ **/
+public interface AdminUserService {
+ /**
+ * 修改密码
+ * @param updateAdminUserPasswordReqVO
+ * @return
+ */
+ Response updatePassword(UpdateAdminUserPasswordReqVO updateAdminUserPasswordReqVO);
+
+ /**
+ * 获取当前登录用户信息
+ * @return
+ */
+ Response findUserInfo();
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminCategoryServiceImpl.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminCategoryServiceImpl.java
new file mode 100644
index 0000000..b893174
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminCategoryServiceImpl.java
@@ -0,0 +1,170 @@
+package com.quanxiaoha.weblog.admin.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.injector.methods.SelectPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.quanxiaoha.weblog.admin.model.vo.category.AddCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.DeleteCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListRspVO;
+import com.quanxiaoha.weblog.admin.model.vo.user.FindUserInfoRspVO;
+import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO;
+import com.quanxiaoha.weblog.admin.service.AdminCategoryService;
+import com.quanxiaoha.weblog.admin.service.AdminUserService;
+import com.quanxiaoha.weblog.common.domain.dos.CategoryDO;
+import com.quanxiaoha.weblog.common.domain.mapper.CategoryMapper;
+import com.quanxiaoha.weblog.common.domain.mapper.UserMapper;
+import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum;
+import com.quanxiaoha.weblog.common.exception.BizException;
+import com.quanxiaoha.weblog.common.model.vo.SelectRspVO;
+import com.quanxiaoha.weblog.common.utils.PageResponse;
+import com.quanxiaoha.weblog.common.utils.Response;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:03
+ * @description: TODO
+ **/
+@Service
+@Slf4j
+public class AdminCategoryServiceImpl implements AdminCategoryService {
+
+ @Autowired
+ private CategoryMapper categoryMapper;
+
+ /**
+ * 添加分类
+ *
+ * @param addCategoryReqVO
+ * @return
+ */
+ @Override
+ public Response addCategory(AddCategoryReqVO addCategoryReqVO) {
+ String categoryName = addCategoryReqVO.getName();
+
+ // 先判断该分类是否已经存在
+ CategoryDO categoryDO = categoryMapper.selectByName(categoryName);
+
+ if (Objects.nonNull(categoryDO)) {
+ log.warn("分类名称: {}, 此已存在", categoryName);
+ throw new BizException(ResponseCodeEnum.CATEGORY_NAME_IS_EXISTED);
+ }
+
+ // 构建 DO 类
+ CategoryDO insertCategoryDO = CategoryDO.builder()
+ .name(addCategoryReqVO.getName().trim())
+ .build();
+
+ // 执行 insert
+ categoryMapper.insert(insertCategoryDO);
+
+ return Response.success();
+ }
+
+ /**
+ * 分类分页数据查询
+ *
+ * @param findCategoryPageListReqVO
+ * @return
+ */
+ @Override
+ public PageResponse findCategoryList(FindCategoryPageListReqVO findCategoryPageListReqVO) {
+ // 获取当前页、以及每页需要展示的数据数量
+ Long current = findCategoryPageListReqVO.getCurrent();
+ Long size = findCategoryPageListReqVO.getSize();
+
+ // 分页对象(查询第几页、每页多少数据)
+ Page page = new Page<>(current, size);
+
+ // 构建查询条件
+ LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
+
+ String name = findCategoryPageListReqVO.getName();
+ LocalDate startDate = findCategoryPageListReqVO.getStartDate();
+ LocalDate endDate = findCategoryPageListReqVO.getEndDate();
+
+ wrapper
+ .like(StringUtils.isNotBlank(name), CategoryDO::getName, name.trim()) // like 模块查询
+ .ge(Objects.nonNull(startDate), CategoryDO::getCreateTime, startDate) // 大于等于 startDate
+ .le(Objects.nonNull(endDate), CategoryDO::getCreateTime, endDate) // 小于等于 endDate
+ .orderByDesc(CategoryDO::getCreateTime); // 按创建时间倒叙
+
+ // 执行分页查询
+ Page categoryDOPage = categoryMapper.selectPage(page, wrapper);
+
+ List categoryDOS = categoryDOPage.getRecords();
+
+ // DO 转 VO
+ List vos = null;
+ if (!CollectionUtils.isEmpty(categoryDOS)) {
+ vos = categoryDOS.stream()
+ .map(categoryDO -> FindCategoryPageListRspVO.builder()
+ .id(categoryDO.getId())
+ .name(categoryDO.getName())
+ .createTime(categoryDO.getCreateTime())
+ .build())
+ .collect(Collectors.toList());
+ }
+
+ return PageResponse.success(categoryDOPage, vos);
+ }
+
+ /**
+ * 删除分类
+ *
+ * @param deleteCategoryReqVO
+ * @return
+ */
+ @Override
+ public Response deleteCategory(DeleteCategoryReqVO deleteCategoryReqVO) {
+ // 分类 ID
+ Long categoryId = deleteCategoryReqVO.getId();
+
+ // 删除分类
+ categoryMapper.deleteById(categoryId);
+
+ return Response.success();
+ }
+
+ /**
+ * 获取文章分类的 Select 列表数据
+ *
+ * @return
+ */
+ @Override
+ public Response findCategorySelectList() {
+ // 查询所有分类
+ List categoryDOS = categoryMapper.selectList(null);
+
+ // DO 转 VO
+ List selectRspVOS = null;
+ // 如果分类数据不为空
+ if (!CollectionUtils.isEmpty(categoryDOS)) {
+ // 将分类 ID 作为 Value 值,将分类名称作为 label 展示
+ selectRspVOS = categoryDOS.stream()
+ .map(categoryDO -> SelectRspVO.builder()
+ .label(categoryDO.getName())
+ .value(categoryDO.getId())
+ .build())
+ .collect(Collectors.toList());
+ }
+
+ return Response.success(selectRspVOS);
+ }
+
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminTagServiceImpl.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminTagServiceImpl.java
new file mode 100644
index 0000000..41ddefc
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminTagServiceImpl.java
@@ -0,0 +1,74 @@
+package com.quanxiaoha.weblog.admin.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.quanxiaoha.weblog.admin.model.vo.category.AddCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.DeleteCategoryReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListReqVO;
+import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListRspVO;
+import com.quanxiaoha.weblog.admin.model.vo.tag.AddTagReqVO;
+import com.quanxiaoha.weblog.admin.service.AdminCategoryService;
+import com.quanxiaoha.weblog.admin.service.AdminTagService;
+import com.quanxiaoha.weblog.common.domain.dos.CategoryDO;
+import com.quanxiaoha.weblog.common.domain.dos.TagDO;
+import com.quanxiaoha.weblog.common.domain.mapper.CategoryMapper;
+import com.quanxiaoha.weblog.common.domain.mapper.TagMapper;
+import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum;
+import com.quanxiaoha.weblog.common.exception.BizException;
+import com.quanxiaoha.weblog.common.model.vo.SelectRspVO;
+import com.quanxiaoha.weblog.common.utils.PageResponse;
+import com.quanxiaoha.weblog.common.utils.Response;
+import com.sun.xml.internal.fastinfoset.stax.events.StAXEventAllocatorBase;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:03
+ * @description: TODO
+ **/
+@Service
+@Slf4j
+public class AdminTagServiceImpl extends ServiceImpl implements AdminTagService {
+
+ @Autowired
+ private TagMapper tagMapper;
+
+ /**
+ * 添加标签集合
+ *
+ * @param addTagReqVO
+ * @return
+ */
+ @Override
+ public Response addTags(AddTagReqVO addTagReqVO) {
+ // vo 转 do
+ List tagDOS = addTagReqVO.getTags().stream()
+ .map(tagName -> TagDO.builder()
+ .name(tagName.trim()) // 去掉前后空格
+ .createTime(LocalDateTime.now())
+ .updateTime(LocalDateTime.now())
+ .build())
+ .collect(Collectors.toList());
+
+ // 批量插入
+ try {
+ saveBatch(tagDOS);
+ } catch (Exception e) {
+ log.warn("该标签已存在", e);
+ }
+
+ return Response.success();
+ }
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminUserServiceImpl.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminUserServiceImpl.java
new file mode 100644
index 0000000..5bf44ff
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/impl/AdminUserServiceImpl.java
@@ -0,0 +1,62 @@
+package com.quanxiaoha.weblog.admin.service.impl;
+
+import com.quanxiaoha.weblog.admin.model.vo.user.FindUserInfoRspVO;
+import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO;
+import com.quanxiaoha.weblog.admin.service.AdminUserService;
+import com.quanxiaoha.weblog.common.domain.mapper.UserMapper;
+import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum;
+import com.quanxiaoha.weblog.common.utils.Response;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:03
+ * @description: TODO
+ **/
+@Service
+public class AdminUserServiceImpl implements AdminUserService {
+
+ @Autowired
+ private UserMapper userMapper;
+ @Autowired
+ private PasswordEncoder passwordEncoder;
+
+ /**
+ * 修改密码
+ * @param updateAdminUserPasswordReqVO
+ * @return
+ */
+ @Override
+ public Response updatePassword(UpdateAdminUserPasswordReqVO updateAdminUserPasswordReqVO) {
+ // 拿到用户名、密码
+ String username = updateAdminUserPasswordReqVO.getUsername();
+ String password = updateAdminUserPasswordReqVO.getPassword();
+
+ // 加密密码
+ String encodePassword = passwordEncoder.encode(password);
+
+ // 更新到数据库
+ int count = userMapper.updatePasswordByUsername(username, encodePassword);
+
+ return count == 1 ? Response.success() : Response.fail(ResponseCodeEnum.USERNAME_NOT_FOUND);
+ }
+
+ /**
+ * 获取当前登录用户信息
+ * @return
+ */
+ @Override
+ public Response findUserInfo() {
+ // 获取存储在 ThreadLocal 中的用户信息
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ // 拿到用户名
+ String username = authentication.getName();
+
+ return Response.success(FindUserInfoRspVO.builder().username(username).build());
+ }
+}
diff --git a/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/package-info.java b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/package-info.java
new file mode 100644
index 0000000..25284f5
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * @author: 犬小哈
+ * @url: www.quanxiaoha.com
+ * @date: 2023-09-15 14:02
+ * @description: TODO
+ **/
+package com.quanxiaoha.weblog.admin.service;
\ No newline at end of file
diff --git a/weblog-springboot-082/weblog-module-admin/src/test/java/com/quanxiaoha/weblog/admin/WeblogModuleAdminApplicationTests.java b/weblog-springboot-082/weblog-module-admin/src/test/java/com/quanxiaoha/weblog/admin/WeblogModuleAdminApplicationTests.java
new file mode 100644
index 0000000..1b6daf7
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-admin/src/test/java/com/quanxiaoha/weblog/admin/WeblogModuleAdminApplicationTests.java
@@ -0,0 +1,25 @@
+package com.quanxiaoha.weblog.admin;
+
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
+import com.quanxiaoha.weblog.common.domain.dos.UserDO;
+import com.quanxiaoha.weblog.common.domain.mapper.UserMapper;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+
+import java.time.LocalDateTime;
+
+@SpringBootTest(classes = WeblogModuleAdminApplicationTests.Application.class)
+class WeblogModuleAdminApplicationTests {
+ // @Import({
+ // DataSourceAutoConfiguration.class, // Spring DB 自动配置类
+ // DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
+ // MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
+ // })
+ public static class Application {
+ }
+
+}
diff --git a/weblog-springboot-082/weblog-module-common/.gitignore b/weblog-springboot-082/weblog-module-common/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-common/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/weblog-springboot-082/weblog-module-common/pom.xml b/weblog-springboot-082/weblog-module-common/pom.xml
new file mode 100644
index 0000000..9a3a67f
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-common/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+ com.quanxiaoha
+ weblog-springboot
+ ${revision}
+
+
+ com.quanxiaoha
+ weblog-module-common
+ weblog-module-common
+ weblog-module-common (此模块用于存放一些通用的功能)
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ p6spy
+ p6spy
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+
+
+
+
+
+
diff --git a/weblog-springboot-082/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLog.java b/weblog-springboot-082/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLog.java
new file mode 100644
index 0000000..38eeb0f
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLog.java
@@ -0,0 +1,17 @@
+package com.quanxiaoha.weblog.common.aspect;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+@Documented
+public @interface ApiOperationLog {
+ /**
+ * API 功能描述
+ *
+ * @return
+ */
+ String description() default "";
+
+}
+
diff --git a/weblog-springboot-082/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLogAspect.java b/weblog-springboot-082/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLogAspect.java
new file mode 100644
index 0000000..ef199b4
--- /dev/null
+++ b/weblog-springboot-082/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLogAspect.java
@@ -0,0 +1,102 @@
+
+package com.quanxiaoha.weblog.common.aspect;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.quanxiaoha.weblog.common.utils.JsonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.*;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.MDC;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Aspect
+@Component
+@Slf4j
+public class ApiOperationLogAspect {
+
+ /** 以自定义 @ApiOperationLog 注解为切点,凡是添加 @ApiOperationLog 的方法,都会执行环绕中的代码 */
+ @Pointcut("@annotation(com.quanxiaoha.weblog.common.aspect.ApiOperationLog)")
+ public void apiOperationLog() {}
+
+ /**
+ * 环绕
+ * @param joinPoint
+ * @return
+ * @throws Throwable
+ */
+ @Around("apiOperationLog()")
+ public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
+ try {
+ // 请求开始时间
+ long startTime = System.currentTimeMillis();
+
+ // MDC
+ MDC.put("traceId", UUID.randomUUID().toString());
+
+ // 获取被请求的类和方法
+ String className = joinPoint.getTarget().getClass().getSimpleName();
+ String methodName = joinPoint.getSignature().getName();
+
+ // 请求入参
+ Object[] args = joinPoint.getArgs();
+ // 入参转 JSON 字符串
+ String argsJsonStr = Arrays.stream(args).map(toJsonStr()).collect(Collectors.joining(", "));
+
+ // 功能描述信息
+ String description = getApiOperationLogDescription(joinPoint);
+
+ // 打印请求相关参数
+ log.info("====== 请求开始: [{}], 入参: {}, 请求类: {}, 请求方法: {} =================================== ",
+ description, argsJsonStr, className, methodName);
+
+ // 执行切点方法
+ Object result = joinPoint.proceed();
+
+ // 执行耗时
+ long executionTime = System.currentTimeMillis() - startTime;
+
+ // 打印出参等相关信息
+ log.info("====== 请求结束: [{}], 耗时: {}ms, 出参: {} =================================== ",
+ description, executionTime, JsonUtil.toJsonString(result));
+
+ return result;
+ } finally {
+ MDC.clear();
+ }
+ }
+
+ /**
+ * 获取注解的描述信息
+ * @param joinPoint
+ * @return
+ */
+ private String getApiOperationLogDescription(ProceedingJoinPoint joinPoint) {
+ // 1. 从 ProceedingJoinPoint 获取 MethodSignature
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+
+ // 2. 使用 MethodSignature 获取当前被注解的 Method
+ Method method = signature.getMethod();
+
+ // 3. 从 Method 中提取 LogExecution 注解
+ ApiOperationLog apiOperationLog = method.getAnnotation(ApiOperationLog.class);
+
+ // 4. 从 LogExecution 注解中获取 description 属性
+ return apiOperationLog.description();
+ }
+
+ /**
+ * 转 JSON 字符串
+ * @return
+ */
+ private Function