Files
everything-is-suitable/docs/plans/2026-03-09-product-launch-readiness-fix.md
张翔 08ea5fbe98 feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
2026-03-28 14:37:29 +08:00

750 lines
16 KiB
Markdown

# 产品上线准备修复计划
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** 系统性解决所有阻塞上线的问题,使产品达到上线标准
**Architecture:** 采用三阶段修复策略:先解决P0阻塞性问题(服务启动),再提升P1质量问题(测试稳定性),最后优化P2技术债务(测试覆盖率)
**Tech Stack:** Spring Boot 4.0.1, Vue 3 + Vite, Uniapp, Playwright, Vitest, pytest, Woodpecker CI
---
## 阶段一:P0问题修复(预计1-2天)
### Task 1: 修复API服务JacksonConfig配置冲突
**问题**: `io.destiny.base.config.JacksonConfig``io.destiny.common.config.JacksonConfig` 冲突导致Spring Boot无法启动
**Files:**
- Modify: `everything-is-suitable-api/everything-is-suitable-base/src/main/java/io/destiny/base/config/JacksonConfig.java`
- Modify: `everything-is-suitable-api/everything-is-suitable-common/src/main/java/io/destiny/common/config/JacksonConfig.java` (如果存在)
- Test: 启动API服务验证
**Step 1: 检查是否存在重复的JacksonConfig**
```bash
cd /Users/zhangxiang/Codes/Gitee/everything-is-suitable
find everything-is-suitable-api -name "JacksonConfig.java" -type f
```
Expected: 找到重复的配置文件
**Step 2: 分析JacksonConfig内容**
```bash
# 检查base模块的JacksonConfig
cat everything-is-suitable-api/everything-is-suitable-base/src/main/java/io/destiny/base/config/JacksonConfig.java
# 检查common模块的JacksonConfig(如果存在)
find everything-is-suitable-api/everything-is-suitable-common -name "JacksonConfig.java" -exec cat {} \;
```
Expected: 确认配置内容和功能
**Step 3: 删除或合并重复配置**
策略:保留一个JacksonConfig,删除另一个
```bash
# 如果base模块的JacksonConfig更完整,删除common模块的
# 或者合并两个配置到一个文件中
rm everything-is-suitable-api/everything-is-suitable-common/src/main/java/io/destiny/common/config/JacksonConfig.java
```
**Step 4: 验证API服务启动**
```bash
cd everything-is-suitable-api/everything-is-suitable-app
mvn spring-boot:run
```
Expected: 服务成功启动,无配置冲突错误
**Step 5: 提交修复**
```bash
git add .
git commit -m "fix: resolve JacksonConfig conflict in API service"
```
---
### Task 2: 恢复Uniapp项目package.json配置
**问题**: Uniapp项目缺少package.json,无法执行npm命令
**Files:**
- Create: `everything-is-suitable-uniapp/package.json`
- Test: 验证npm命令可执行
**Step 1: 检查Uniapp项目结构**
```bash
cd /Users/zhangxiang/Codes/Gitee/everything-is-suitable/everything-is-suitable-uniapp
ls -la | grep -E "package|manifest"
```
Expected: 确认缺少package.json
**Step 2: 创建package.json**
```json
{
"name": "everything-is-suitable-uniapp",
"version": "1.0.0",
"description": "Uniapp移动端应用",
"scripts": {
"dev:h5": "uni -p h5",
"build:h5": "uni build -p h5",
"dev:mp-weixin": "uni -p mp-weixin",
"build:mp-weixin": "uni build -p mp-weixin",
"test": "vitest",
"test:e2e": "playwright test"
},
"dependencies": {
"vue": "^3.5.26",
"vue-router": "^4.6.4",
"pinia": "^3.0.4",
"lunar-javascript": "^1.6.12"
},
"devDependencies": {
"@dcloudio/uni-cli-shared": "^3.0.0",
"@dcloudio/vite-plugin-uni": "^3.0.0",
"@playwright/test": "^1.40.1",
"vitest": "^4.0.16",
"typescript": "^5.9.3",
"vite": "^7.3.1"
}
}
```
**Step 3: 安装依赖**
```bash
npm install
```
Expected: 依赖安装成功
**Step 4: 验证Uniapp服务启动**
```bash
npm run dev:h5
```
Expected: H5开发服务器成功启动
**Step 5: 提交修复**
```bash
git add package.json package-lock.json
git commit -m "fix: restore package.json for uniapp project"
```
---
### Task 3: 验证所有服务启动状态
**Files:**
- Test: 验证三个服务均可正常启动
**Step 1: 启动API服务**
```bash
cd /Users/zhangxiang/Codes/Gitee/everything-is-suitable/everything-is-suitable-api/everything-is-suitable-app
mvn spring-boot:run &
```
Expected: API服务在8080端口启动成功
**Step 2: 启动Admin服务**
```bash
cd /Users/zhangxiang/Codes/Gitee/everything-is-suitable/everything-is-suitable-admin
npm run dev:local &
```
Expected: Admin服务在5173端口启动成功
**Step 3: 启动Uniapp服务**
```bash
cd /Users/zhangxiang/Codes/Gitee/everything-is-suitable/everything-is-suitable-uniapp
npm run dev:h5 &
```
Expected: Uniapp H5服务启动成功
**Step 4: 验证服务健康状态**
```bash
# 检查API健康
curl http://localhost:8080/actuator/health
# 检查Admin服务
curl http://localhost:5173
# 检查Uniapp服务(根据实际端口)
curl http://localhost:5174
```
Expected: 所有服务返回正常响应
**Step 5: 记录验证结果**
```bash
echo "✅ P0问题修复完成 - 所有服务正常启动" >> /Users/zhangxiang/Codes/Gitee/everything-is-suitable/docs/reports/p0-fix-report.md
```
---
## 阶段二:测试质量提升(预计3-5天)
### Task 4: 创建测试数据工厂
**问题**: 测试数据重复导致"duplicate key error"
**Files:**
- Create: `everything-is-suitable-admin/src/test/utils/test-data-factory.ts`
- Modify: `everything-is-suitable-admin/src/services/__tests__/user.service.management.test.ts`
**Step 1: 创建测试数据工厂**
```typescript
// everything-is-suitable-admin/src/test/utils/test-data-factory.ts
export class TestDataFactory {
private static counter = 0;
static generateUniqueUsername(): string {
return `test_user_${Date.now()}_${++this.counter}`;
}
static generateUniqueEmail(): string {
return `test_${Date.now()}_${++this.counter}@example.com`;
}
static createUserData(overrides: Partial<any> = {}) {
return {
username: this.generateUniqueUsername(),
email: this.generateUniqueEmail(),
password: 'Test@123456',
...overrides
};
}
static reset() {
this.counter = 0;
}
}
```
**Step 2: 重构用户服务测试使用数据工厂**
```typescript
// everything-is-suitable-admin/src/services/__tests__/user.service.management.test.ts
import { TestDataFactory } from '@/test/utils/test-data-factory';
describe('UserService', () => {
beforeEach(() => {
TestDataFactory.reset();
});
it('should create user with unique data', async () => {
const userData = TestDataFactory.createUserData();
const result = await userService.createUser(userData);
expect(result.username).toBe(userData.username);
});
});
```
**Step 3: 运行测试验证**
```bash
cd /Users/zhangxiang/Codes/Gitee/everything-is-suitable/everything-is-suitable-admin
npm test -- user.service.management.test.ts
```
Expected: 测试通过,无重复数据错误
**Step 4: 应用到其他测试文件**
```bash
# 查找所有需要修改的测试文件
grep -r "duplicate key" src/
```
**Step 5: 提交改进**
```bash
git add src/test/utils/test-data-factory.ts
git commit -m "feat: add test data factory to avoid duplicate data errors"
```
---
### Task 5: 实现测试隔离机制
**问题**: 测试间相互影响,状态污染
**Files:**
- Create: `everything-is-suitable-admin/src/test/setup/test-isolation.ts`
- Modify: `everything-is-suitable-admin/vitest.setup.ts`
**Step 1: 创建测试隔离工具**
```typescript
// everything-is-suitable-admin/src/test/setup/test-isolation.ts
import { beforeEach, afterEach } from 'vitest';
export function setupTestIsolation() {
beforeEach(async () => {
// 清理数据库
await cleanDatabase();
// 重置Mock状态
resetMockState();
// 清理本地存储
localStorage.clear();
sessionStorage.clear();
});
afterEach(async () => {
// 清理测试数据
await cleanupTestData();
// 验证无残留状态
await verifyCleanState();
});
}
async function cleanDatabase() {
// 实现数据库清理逻辑
}
function resetMockState() {
// 重置所有Mock状态
}
async function cleanupTestData() {
// 清理测试创建的数据
}
async function verifyCleanState() {
// 验证环境干净
}
```
**Step 2: 更新vitest配置**
```typescript
// everything-is-suitable-admin/vitest.setup.ts
import { setupTestIsolation } from './src/test/setup/test-isolation';
setupTestIsolation();
```
**Step 3: 运行测试验证隔离**
```bash
npm test
```
Expected: 测试通过,无状态污染
**Step 4: 提交改进**
```bash
git add src/test/setup/test-isolation.ts vitest.setup.ts
git commit -m "feat: implement test isolation mechanism"
```
---
### Task 6: 完善错误处理机制
**问题**: 未处理的Promise拒绝和异常
**Files:**
- Create: `everything-is-suitable-admin/src/test/utils/error-handler.ts`
- Modify: `everything-is-suitable-admin/src/test/setup/global-error-handler.ts`
**Step 1: 创建全局错误处理器**
```typescript
// everything-is-suitable-admin/src/test/setup/global-error-handler.ts
export function setupGlobalErrorHandler() {
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// 记录到测试报告
throw new Error(`Unhandled Promise Rejection: ${reason}`);
});
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
throw error;
});
}
```
**Step 2: 在测试中使用错误处理**
```typescript
// everything-is-suitable-admin/vitest.setup.ts
import { setupGlobalErrorHandler } from './src/test/setup/global-error-handler';
setupGlobalErrorHandler();
```
**Step 3: 运行测试验证**
```bash
npm test 2>&1 | grep -i "unhandled"
```
Expected: 无未处理的异常输出
**Step 4: 提交改进**
```bash
git add src/test/setup/global-error-handler.ts
git commit -m "feat: add global error handler for tests"
```
---
### Task 7: 修复失败的测试用例
**问题**: 231个测试失败
**Files:**
- Modify: 多个测试文件(根据失败列表)
**Step 1: 获取失败测试列表**
```bash
cd /Users/zhangxiang/Codes/Gitee/everything-is-suitable/everything-is-suitable-admin
npm test 2>&1 | grep "FAIL" > /tmp/failed-tests.txt
cat /tmp/failed-tests.txt
```
Expected: 获取完整的失败测试列表
**Step 2: 分类失败原因**
```bash
# 统计失败原因
npm test 2>&1 | grep -E "(duplicate|timeout|assertion)" | sort | uniq -c
```
**Step 3: 批量修复重复数据问题**
```bash
# 应用Task 4的数据工厂到所有相关测试
find src -name "*.test.ts" -exec sed -i '' 's/test_user_/TestDataFactory.generateUniqueUsername()/g' {} \;
```
**Step 4: 逐个修复其他失败测试**
```bash
# 运行单个测试文件
npm test -- specific-test-file.test.ts
# 查看详细错误
npm test -- --reporter=verbose specific-test-file.test.ts
```
**Step 5: 验证修复效果**
```bash
npm test
```
Expected: 测试失败率降至<5%
**Step 6: 提交修复**
```bash
git add .
git commit -m "fix: resolve failing test cases"
```
---
## 阶段三:测试覆盖率提升(预计2-3天)
### Task 8: 补充service层单元测试
**问题**: service层覆盖率0%
**Files:**
- Create: `everything-is-suitable-api/everything-is-suitable-biz/src/test/java/io/destiny/biz/service/impl/*Test.java`
**Step 1: 识别未测试的服务类**
```bash
cd /Users/zhangxiang/Codes/Gitee/everything-is-suitable/everything-is-suitable-api/everything-is-suitable-biz
find src/main/java -name "*ServiceImpl.java" | while read f; do
testfile=$(echo $f | sed 's|src/main/java|src/test/java|; s|\.java|Test.java|')
if [ ! -f "$testfile" ]; then
echo "Missing test: $testfile"
fi
done
```
**Step 2: 创建ZiweiChartServiceImplTest**
```java
// everything-is-suitable-api/everything-is-suitable-biz/src/test/java/io/destiny/biz/service/impl/ZiweiChartServiceImplTest.java
package io.destiny.biz.service.impl;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.*;
class ZiweiChartServiceImplTest {
private ZiweiChartServiceImpl service;
@BeforeEach
void setUp() {
service = new ZiweiChartServiceImpl();
}
@Test
void shouldGenerateZiweiChart() {
BirthInfo birthInfo = new BirthInfo(/* 参数 */);
ZiweiChart chart = service.generateChart(birthInfo);
assertNotNull(chart);
assertNotNull(chart.getPalaces());
assertTrue(chart.getPalaces().size() > 0);
}
}
```
**Step 3: 运行测试**
```bash
mvn test -Dtest=ZiweiChartServiceImplTest
```
Expected: 测试通过
**Step 4: 为所有service创建测试**
重复Step 2-3,为所有service创建单元测试
**Step 5: 验证覆盖率**
```bash
mvn jacoco:report
open target/site/jacoco/index.html
```
Expected: service层覆盖率>70%
**Step 6: 提交测试**
```bash
git add src/test/java
git commit -m "test: add unit tests for service layer"
```
---
### Task 9: 补充config层单元测试
**问题**: config层覆盖率15%
**Files:**
- Create: `everything-is-suitable-api/everything-is-suitable-biz/src/test/java/io/destiny/biz/config/*Test.java`
**Step 1: 创建路由配置测试**
```java
// everything-is-suitable-api/everything-is-suitable-biz/src/test/java/io/destiny/biz/config/AlmanacRouterTest.java
package io.destiny.biz.config;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class AlmanacRouterTest {
@Autowired
private WebTestClient webTestClient;
@Test
void shouldRouteAlmanacRequest() {
webTestClient.get()
.uri("/api/almanac")
.exchange()
.expectStatus().isOk();
}
}
```
**Step 2: 运行测试**
```bash
mvn test -Dtest=AlmanacRouterTest
```
**Step 3: 为所有config创建测试**
**Step 4: 验证覆盖率**
```bash
mvn jacoco:report
```
Expected: config层覆盖率>70%
**Step 5: 提交测试**
```bash
git add src/test/java
git commit -m "test: add unit tests for config layer"
```
---
### Task 10: 最终验收测试
**Files:**
- Test: 完整的端到端测试
**Step 1: 运行完整测试套件**
```bash
# 后端测试
cd everything-is-suitable-api
mvn clean test
# Admin前端测试
cd ../everything-is-suitable-admin
npm test
# E2E测试
npm run test:e2e
```
Expected: 所有测试通过
**Step 2: 验证测试覆盖率**
```bash
# 后端覆盖率
cd everything-is-suitable-api
mvn jacoco:report
cat target/site/jacoco/index.html | grep "Total"
# Admin前端覆盖率
cd ../everything-is-suitable-admin
npm test -- --coverage
```
Expected:
- 指令覆盖率≥70%
- 分支覆盖率≥65%
- 方法覆盖率≥90%
- 类覆盖率≥95%
**Step 3: 验证服务启动**
```bash
# 启动所有服务
./scripts/start-all-services.sh
# 验证健康状态
curl http://localhost:8080/actuator/health
curl http://localhost:5173
curl http://localhost:5174
```
Expected: 所有服务健康
**Step 4: 生成验收报告**
```bash
cat > docs/reports/final-acceptance-report.md << 'EOF'
# 产品上线准备验收报告
## 验收时间
$(date)
## 服务启动状态
- ✅ API服务: 正常启动
- ✅ Admin服务: 正常启动
- ✅ Uniapp服务: 正常启动
## 测试质量
- ✅ 单元测试失败率: <5%
- ✅ 测试覆盖率达标
- ✅ 无未处理异常
## 上线决策
✅ 产品已具备上线条件
EOF
```
**Step 5: 提交验收报告**
```bash
git add docs/reports/final-acceptance-report.md
git commit -m "docs: add final acceptance report"
```
---
## 验收标准
### P0级别(必须100%通过)
- [ ] API服务可正常启动
- [ ] Admin服务可正常启动
- [ ] Uniapp服务可正常启动
- [ ] 无配置冲突错误
### P1级别(必须95%以上通过)
- [ ] 单元测试失败率<5%
- [ ] 无未处理的Promise拒绝
- [ ] 无测试数据重复错误
- [ ] 测试隔离机制生效
### P2级别(必须80%以上通过)
- [ ] 指令覆盖率≥70%
- [ ] 分支覆盖率≥65%
- [ ] 方法覆盖率≥90%
- [ ] 类覆盖率≥95%
---
## 风险与应对
### 风险1:修复引入新问题
- **应对**: 每个修复后运行完整测试套件
- **验证**: 使用git bisect定位问题
### 风险2:测试覆盖率提升困难
- **应对**: 优先覆盖核心业务逻辑
- **验证**: 使用jacoco报告指导补充
### 风险3:时间估算偏差
- **应对**: 每日评估进度,及时调整计划
- **验证**: 使用燃尽图跟踪
---
## 执行建议
**推荐执行方式**: Subagent-Driven Development
- 每个Task分配给独立的subagent
- 完成后进行代码审查
- 快速迭代,及时反馈
**预计总时间**: 6-10个工作日
- 阶段一: 1-2天
- 阶段二: 3-5天
- 阶段三: 2-3天