# 产品上线准备修复计划 > **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 = {}) { 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天