txw/docs/superpowers/plans/2026-04-28-修改密码功能实现计划.md

368 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 修改密码功能实现计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 为碳信网平台添加普通用户自助修改密码功能txw-sso后端 + txw-mhzc-web前端
**Architecture:**
- 后端SSO服务新增 `POST /sso/auth/changePassword` 接口,用户通过 authenticate 验证旧密码,通过 mhzc-service 的 Feign 接口更新用户密码
- 前端mhzc-web 新增修改密码页面(账号管理),工作台增加快捷入口,用户中心左侧菜单增加"账号管理"菜单项
**Tech Stack:** Java Spring Boot / Vue 2 / TDesign / Feign
---
## 涉及的变更文件
### 后端txw-sso
| 文件 | 改动 |
|------|------|
| `AuthService.java` | 新增 `changePassword` 接口声明 |
| `AuthServiceImpl.java` | 实现 `changePassword` 逻辑 |
| `AuthController.java` | 新增 `/auth/changePassword` 路由 |
| `ChangePasswordReqVO.java` | 新建请求 VO |
| `ChangePasswordRespVO.java` | 新建响应 VO |
| `YhxxApi.java` (txw-sso-api) | 新增 Feign 方法 `updatePassword` |
| `TxwMhzcYhxxbService.java` (txw-mhzc) | 新增 `updatePassword` 方法声明 |
| `TxwMhzcYhxxbServiceImpl.java` (txw-mhzc) | 实现 `updatePassword` |
| `TxwMhzcYhxxbMapper.xml` | 新增 updatePassword SQL |
| `ISsoApi.java` | FeignClient name 常量需确认mhzc服务名 |
### 前端txw-mhzc-web
| 文件 | 改动 |
|------|------|
| `views/gzt/index.vue` | 新增修改密码快捷入口按钮 |
| `views/yhzx/zhanghugl/index.vue` | 新建修改密码页面 |
| `router/routes.js` | 新增 `zhanghugl` 路由 |
| `views/glxtSy/config.js` | 菜单配置新增"账号管理" |
| `api/sso.js` | 新建,封装 changePassword API |
---
## 后端任务拆分
### Task 1: 后端 - 新建 ChangePasswordReqVO
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/pojo/vo/ChangePasswordReqVO.java`
- [ ] **Step 1: 创建文件**
```java
package com.css.txw.sso.pojo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
@Schema(description = "修改密码 Request VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ChangePasswordReqVO {
@Schema(description = "旧密码MD5加密", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "旧密码不能为空")
private String oldPassword;
@Schema(description = "新密码MD5加密", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "新密码不能为空")
private String newPassword;
@Schema(description = "确认密码MD5加密", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "确认密码不能为空")
private String confirmPassword;
}
```
---
### Task 2: 后端 - AuthService 新增 changePassword 接口声明
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/service/auth/AuthService.java`
在接口末尾添加:
```java
/**
* 修改密码
*
* @param reqVO 修改密码请求
* @return 成功返回 null
*/
void changePassword(ChangePasswordReqVO reqVO);
```
引入 import
```java
import com.css.txw.sso.pojo.vo.ChangePasswordReqVO;
```
---
### Task 3: 后端 - AuthServiceImpl 实现 changePassword
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/service/auth/impl/AuthServiceImpl.java`
在类末尾添加实现方法:
```java
@Override
public void changePassword(ChangePasswordReqVO reqVO) {
// 1. 校验新密码与确认密码一致性
if (!reqVO.getNewPassword().equals(reqVO.getConfirmPassword())) {
throw exception(AUTH_PASSWORD_CONFIRM_MISMATCH);
}
// 2. 密码复杂度校验6-20位字母+数字)
if (!isValidPasswordComplexity(reqVO.getNewPassword())) {
throw exception(AUTH_PASSWORD_COMPLEXITY_INVALID);
}
// 3. 获取当前登录用户
String userId = SecurityFrameworkUtils.getLoginUserId();
YhxxbDTO yhxx = yhxxService.getYhxx(userId);
// 4. 校验新旧密码不能相同
if (reqVO.getOldPassword().equals(reqVO.getNewPassword())) {
throw exception(AUTH_PASSWORD_SAME_AS_OLD);
}
// 5. 旧密码正确性校验
authenticate(yhxx.getDlzh(), reqVO.getOldPassword());
// 6. 更新密码
yhxxService.updatePassword(userId, reqVO.getNewPassword());
}
private boolean isValidPasswordComplexity(String password) {
if (password == null || password.length() < 6 || password.length() > 20) {
return false;
}
boolean hasLetter = password.matches(".*[A-Za-z]+.*");
boolean hasDigit = password.matches(".*[0-9]+.*");
return hasLetter && hasDigit;
}
```
新增引入:
```java
import com.css.txw.sso.pojo.vo.ChangePasswordReqVO;
import com.css.txw.sso.util.SecurityFrameworkUtils;
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_PASSWORD_CONFIRM_MISMATCH;
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_PASSWORD_COMPLEXITY_INVALID;
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_PASSWORD_SAME_AS_OLD;
```
---
### Task 4: 后端 - ErrorCodeConstants 新增错误码
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/constants/ErrorCodeConstants.java`
新增三个错误码:
```java
AUTH_PASSWORD_CONFIRM_MISMATCH(400, "两次输入的新密码不一致"),
AUTH_PASSWORD_COMPLEXITY_INVALID(400, "密码长度6-20位需包含字母和数字"),
AUTH_PASSWORD_SAME_AS_OLD(400, "新密码不能与原密码相同"),
```
---
### Task 5: 后端 - AuthController 新增路由
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/controller/auth/AuthController.java`
在类末尾添加:
```java
@PostMapping("/changePassword")
@Operation(summary = "修改密码")
public CommonResult<Void> changePassword(@RequestBody @Valid ChangePasswordReqVO reqVO) {
authService.changePassword(reqVO);
return success(null);
}
```
新增引入:
```java
import com.css.txw.sso.pojo.vo.ChangePasswordReqVO;
```
---
### Task 6: 后端 - YhxxService 新增 updatePassword 方法
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/service/yhxx/YhxxService.java`
末尾新增方法声明:
```java
void updatePassword(String yhUuid, String newPassword);
```
---
### Task 7: 后端 - YhxxServiceImpl 实现 updatePasswordFeign调用mhzc
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/service/yhxx/impl/YhxxServiceImpl.java`
首先需要确认 mhzc 服务的 Feign 接口存在。如果 YhxxApi 不支持更新密码,则需要在 txw-sso-api 中新增 Feign 方法指向 mhzc 的更新密码接口。
步骤:
1.`txw-sso-api``YhxxApi.java` 中新增 `updatePassword` Feign 方法
2.`txw-mhzc``TxwMhzcYhxxbService` 新增 `updatePassword` 方法
3.`TxwMhzcYhxxbServiceImpl` 实现该方法
4. 在 mapper XML 中新增 update SQL
5.`YhxxServiceImpl` 中调用该 Feign 接口
**YhxxApi.java (txw-sso-api) 新增:**
```java
@PostMapping("/mhzc/user/updatePassword")
@Operation(summary = "更新用户密码")
CommonResult<String> updatePassword(@RequestParam("yhUuid") String yhUuid, @RequestParam("dlmm") String dlmm);
```
**TxwMhzcYhxxbService.java 新增:**
```java
String updatePassword(String yhUuid, String dlmm);
```
**TxwMhzcYhxxbServiceImpl.java 新增:**
```java
@Override
public String updatePassword(String yhUuid, String dlmm) {
TxwMhzcYhxxbDO yhxxbDO = new TxwMhzcYhxxbDO();
yhxxbDO.setYhUuid(yhUuid);
yhxxbDO.setDlmm(dlmm);
this.updateById(yhxxbDO);
return "success";
}
```
**TxwMhzcYhxxbMapper.xml 新增:**
```xml
<update id="updatePassword">
UPDATE txw_mhzc_yhxxb SET dlmm = #{dlmm} WHERE yh_uuid = #{yhUuid}
</update>
```
**YhxxServiceImpl.java 实现:**
```java
@Resource
private YhxxApi yhxxApi;
@Override
public void updatePassword(String yhUuid, String newPassword) {
yhxxApi.updatePassword(yhUuid, newPassword);
}
```
---
## 前端任务拆分txw-mhzc-web
### Task 8: 前端 - 新建 api/sso.js
**文件:** `txw-mhzc-web/src/pages/index/api/sso.js`
```js
import { fetchSso } from '@/core/request';
export const changePassword = (params) => {
return fetchSso({
url: '/sso/auth/changePassword',
data: JSON.stringify(params),
method: 'post',
loading: true,
});
};
```
---
### Task 9: 前端 - 新建修改密码页面
**文件:** `txw-mhzc-web/src/pages/index/views/yhzx/zhanghugl/index.vue`
页面元素:
- 三个密码输入框(旧密码、新密码、确认密码)
- 确认按钮
- 密码格式提示文字
校验逻辑:
1. 旧密码、新密码、确认密码不能为空
2. 新密码长度6-20位需包含字母和数字提示密码长度6-20位需包含字母和数字
3. 新密码与确认密码一致性(提示:两次输入的新密码不一致)
4. 提交后调用 changePassword API
5. 成功提示"密码修改成功",可跳转回工作台
样式参考现有的登录页面,使用 TDesign 组件库。
---
### Task 10: 前端 - 路由配置新增 zhanghugl
**文件:** `txw-mhzc-web/src/pages/index/router/routes.js`
`yhzx` 的 children 数组中新增:
```js
{ path: 'zhanghugl', component: zhanghugl, name: 'zhanghugl', meta: { title: '账号管理' } }
```
新增 zhanghugl 路由函数:
```js
function zhanghugl() {
return import('@/pages/index/views/yhzx/zhanghugl/index.vue');
}
```
---
### Task 11: 前端 - 菜单配置新增"账号管理"
**文件:** `txw-mhzc-web/src/pages/index/views/glxtSy/config.js`
`menuList` 数组中新增一项:
```js
{
value: 'zhanghugl',
title: '账号管理',
icon: 'password',
}
```
---
### Task 12: 前端 - 工作台新增修改密码快捷入口
**文件:** `txw-mhzc-web/src/pages/index/views/gzt/index.vue`
在快捷操作区域新增按钮:
```html
<t-button theme="primary" variant="outline" @click="$router.push('/yhzx/zhanghugl')">
修改密码
</t-button>
```
---
## 任务执行顺序
建议按以下顺序执行:
1. Task 1 - 新建 ChangePasswordReqVO
2. Task 4 - 新增错误码
3. Task 6 - YhxxService 新增 updatePassword
4. Task 7 - YhxxServiceImpl + Feign + MHZC 实现
5. Task 2 - AuthService 新增 changePassword
6. Task 3 - AuthServiceImpl 实现
7. Task 5 - AuthController 新增路由
8. Task 8 - 前端 API 新建
9. Task 9 - 前端页面新建
10. Task 10 - 路由配置
11. Task 11 - 菜单配置
12. Task 12 - 工作台入口