Files
ccdi/docs/plans/2026-02-27-project-status-counts-fix.md

579 lines
13 KiB
Markdown
Raw Permalink Normal View History

# 项目管理状态统计修复实施计划
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** 修复项目管理标签页状态统计功能,使标签页显示数据库中所有该状态的项目总数,而非当前页的数量。
**Architecture:** 后端新增独立的状态统计接口 `/ccdi/project/statusCounts`,前端在加载列表时并行调用统计接口,使用 `Promise.all` 同时获取列表数据和统计数据。
**Tech Stack:** Java 17, Spring Boot 3.5.8, MyBatis Plus 3.5.10, Vue.js 2.6.12, Element UI 2.15.14
---
## Task 1: 创建状态统计 VO 类
**Files:**
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectStatusCountsVO.java`
**Step 1: 创建 VO 类文件**
创建新文件 `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectStatusCountsVO.java`:
```java
package com.ruoyi.ccdi.project.domain.vo;
import lombok.Data;
/**
* 项目状态统计VO
*
* @author ruoyi
*/
@Data
public class CcdiProjectStatusCountsVO {
/** 全部项目总数 */
private Long all;
/** 进行中项目数状态0 */
private Long status0;
/** 已完成项目数状态1 */
private Long status1;
/** 已归档项目数状态2 */
private Long status2;
}
```
**Step 2: 验证文件创建**
Run: `ls ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectStatusCountsVO.java`
Expected: 文件存在
**Step 3: Commit**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectStatusCountsVO.java
git commit -m "feat: 添加项目状态统计 VO 类"
```
---
## Task 2: 添加 Service 接口方法
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectService.java`
**Step 1: 读取当前 Service 接口**
Run: Read `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectService.java`
Expected: 看到现有方法列表
**Step 2: 添加统计方法声明**
`ICcdiProjectService.java` 文件末尾(类定义的最后一个方法之后)添加:
```java
/**
* 查询各状态的项目总数(不受搜索条件影响)
*
* @return 状态统计
*/
CcdiProjectStatusCountsVO getStatusCounts();
```
**Step 3: 验证语法**
Run: `cd ccdi-project && mvn compile`
Expected: BUILD SUCCESS
**Step 4: Commit**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectService.java
git commit -m "feat: Service 接口添加状态统计方法声明"
```
---
## Task 3: 实现 Service 统计方法
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectServiceImpl.java`
**Step 1: 读取当前 Service 实现类**
Run: Read `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectServiceImpl.java`
Expected: 看到现有实现和依赖
**Step 2: 确认需要的 import**
检查文件顶部是否已有以下 import
- `com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper`
- `com.ruoyi.ccdi.project.domain.vo.CcdiProjectStatusCountsVO`
如果没有,添加它们。
**Step 3: 实现 getStatusCounts 方法**
在 Service 实现类末尾添加方法实现:
```java
@Override
public CcdiProjectStatusCountsVO getStatusCounts() {
CcdiProjectStatusCountsVO vo = new CcdiProjectStatusCountsVO();
// 统计全部项目
Long totalCount = ccdiProjectMapper.selectCount(null);
vo.setAll(totalCount);
// 统计进行中项目状态0
Long status0Count = ccdiProjectMapper.selectCount(
new LambdaQueryWrapper<CcdiProject>()
.eq(CcdiProject::getStatus, "0")
);
vo.setStatus0(status0Count);
// 统计已完成项目状态1
Long status1Count = ccdiProjectMapper.selectCount(
new LambdaQueryWrapper<CcdiProject>()
.eq(CcdiProject::getStatus, "1")
);
vo.setStatus1(status1Count);
// 统计已归档项目状态2
Long status2Count = ccdiProjectMapper.selectCount(
new LambdaQueryWrapper<CcdiProject>()
.eq(CcdiProject::getStatus, "2")
);
vo.setStatus2(status2Count);
return vo;
}
```
**Step 4: 验证编译**
Run: `cd ccdi-project && mvn compile`
Expected: BUILD SUCCESS
**Step 5: Commit**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectServiceImpl.java
git commit -m "feat: 实现项目状态统计方法"
```
---
## Task 4: 添加 Controller 接口
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectController.java`
**Step 1: 读取当前 Controller**
Run: Read `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectController.java`
Expected: 看到现有接口定义
**Step 2: 添加状态统计接口**
在 Controller 类的最后一个方法之后添加:
```java
/**
* 查询项目状态统计
*/
@GetMapping("/statusCounts")
@Operation(summary = "查询项目状态统计")
@PreAuthorize("@ss.hasPermi('ccdi:project:list')")
public AjaxResult getStatusCounts() {
CcdiProjectStatusCountsVO counts = projectService.getStatusCounts();
return AjaxResult.success(counts);
}
```
**Step 3: 验证编译**
Run: `cd ccdi-project && mvn compile`
Expected: BUILD SUCCESS
**Step 4: Commit**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectController.java
git commit -m "feat: 添加项目状态统计接口"
```
---
## Task 5: 测试后端接口
**Files:**
- None (测试验证)
**Step 1: 启动后端服务**
Run: `mvn spring-boot:run``ry.bat`
Expected: 服务启动成功,看到 "Started RuoYiApplication" 日志
**Step 2: 获取访问令牌**
Run (使用 curl 或浏览器):
```bash
curl -X POST "http://localhost:8080/login/test?username=admin&password=admin123"
```
Expected: 返回 JSON 包含 token
**Step 3: 测试状态统计接口**
在 Swagger UI 中测试:
1. 访问: http://localhost:8080/swagger-ui/index.html
2. 找到: "纪检初核项目管理" → "GET /ccdi/project/statusCounts"
3. 点击 "Try it out" → "Execute"
或使用 curl (替换 YOUR_TOKEN):
```bash
curl -X GET "http://localhost:8080/ccdi/project/statusCounts" \
-H "Authorization: Bearer YOUR_TOKEN"
```
Expected: 返回类似以下的响应:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"all": 30,
"status0": 10,
"status1": 15,
"status2": 5
}
}
```
**Step 4: 验证数据正确性**
使用数据库工具连接 MySQL执行:
```sql
SELECT
status,
COUNT(*) as count
FROM ccdi_project
GROUP BY status;
```
Expected: 统计数字与接口返回一致
---
## Task 6: 添加前端 API 方法
**Files:**
- Modify: `ruoyi-ui/src/api/ccdiProject.js`
**Step 1: 读取当前 API 文件**
Run: Read `ruoyi-ui/src/api/ccdiProject.js`
Expected: 看到现有的 API 方法定义
**Step 2: 添加状态统计 API 方法**
在文件末尾(最后一个 export 函数之后)添加:
```javascript
// 查询项目状态统计
export function getStatusCounts() {
return request({
url: '/ccdi/project/statusCounts',
method: 'get'
})
}
```
**Step 3: 验证语法**
Run: `cd ruoyi-ui && npm run lint -- --fix src/api/ccdiProject.js`
Expected: No errors
**Step 4: Commit**
```bash
git add ruoyi-ui/src/api/ccdiProject.js
git commit -m "feat: 前端 API 添加状态统计方法"
```
---
## Task 7: 修改前端页面组件
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/index.vue`
**Step 1: 读取当前页面组件**
Run: Read `ruoyi-ui/src/views/ccdiProject/index.vue`
Expected: 看到现有代码结构
**Step 2: 修改 import 语句**
找到第 64 行左右的 import 语句:
```javascript
import {listProject} from '@/api/ccdiProject'
```
修改为:
```javascript
import {listProject, getStatusCounts} from '@/api/ccdiProject'
```
**Step 3: 重构 getList 方法**
找到 `getList()` 方法(大约第 122-134 行),完全替换为:
```javascript
/** 查询项目列表 */
getList() {
this.loading = true
// 并行请求列表数据和状态统计
Promise.all([
listProject(this.queryParams),
getStatusCounts()
]).then(([listResponse, countsResponse]) => {
// 处理列表数据
this.projectList = listResponse.rows
this.total = listResponse.total
// 处理状态统计
const counts = countsResponse.data
this.tabCounts = {
all: counts.all,
'0': counts.status0,
'1': counts.status1,
'2': counts.status2
}
this.loading = false
}).catch(() => {
this.loading = false
})
}
```
**Step 4: 删除旧的统计方法**
找到并删除 `calculateTabCounts()` 方法(大约第 135-145 行):
```javascript
// 删除这个方法
/** 计算标签页数量 */
calculateTabCounts() {
// 注意这里需要后端API返回所有状态的数量统计
// 目前暂时使用当前页的数据进行计算
this.tabCounts = {
all: this.total,
'0': this.projectList.filter(p => p.status === '0').length,
'1': this.projectList.filter(p => p.status === '1').length,
'2': this.projectList.filter(p => p.status === '2').length
}
}
```
**Step 5: 验证语法**
Run: `cd ruoyi-ui && npm run lint -- --fix src/views/ccdiProject/index.vue`
Expected: No errors
**Step 6: Commit**
```bash
git add ruoyi-ui/src/views/ccdiProject/index.vue
git commit -m "refactor: 使用后端统计接口替换前端计算"
```
---
## Task 8: 测试前端功能
**Files:**
- None (测试验证)
**Step 1: 确保后端服务运行**
确认后端服务在运行中。
**Step 2: 启动前端开发服务器**
Run:
```bash
cd ruoyi-ui
npm run dev
```
Expected: 服务启动,看到 "App running at" 消息
**Step 3: 测试页面加载**
1. 打开浏览器访问: http://localhost:80
2. 登录系统 (admin/admin123)
3. 导航到 "项目管理" 页面
Expected:
- 页面正常加载
- 标签页显示正确的统计数字(例如:全部项目(30)
- 标签页数字不随分页变化
**Step 4: 测试搜索功能**
1. 在搜索框输入项目名称
2. 点击搜索按钮或按回车
Expected:
- 列表正确过滤
- 标签页数字保持不变(显示总数)
**Step 5: 测试分页功能**
1. 点击分页组件切换到第 2 页
Expected:
- 列表切换到第 2 页
- 标签页数字保持不变
**Step 6: 测试状态切换功能**
1. 点击"进行中"标签
Expected:
- 列表只显示进行中的项目
- 标签页数字保持不变(仍显示总数)
**Step 7: 测试浏览器控制台**
打开浏览器开发者工具的 Console 标签
Expected:
- 没有 JavaScript 错误
- 看到两个 API 请求成功list 和 statusCounts
---
## Task 9: 最终提交和文档更新
**Files:**
- Modify: `docs/plans/2026-02-27-project-status-counts-fix-design.md`
**Step 1: 更新设计文档状态**
修改设计文档的状态部分:
```markdown
## 文档信息
- **创建日期**: 2026-02-27
- **作者**: Claude Code
- **状态**: ✅ 已完成
```
**Step 2: 验收清单**
对照设计文档的验收标准,确认:
- [ ] 后端 `/statusCounts` 接口返回正确的统计数字
- [ ] 前端标签页显示数据库中的完整统计
- [ ] 搜索不影响标签页统计数字
- [ ] 分页不影响标签页统计数字
- [ ] 状态过滤不影响标签页统计数字
- [ ] 统计接口响应时间 < 100ms
- [ ] 页面加载时间无明显增加
**Step 3: 提交文档更新**
```bash
git add docs/plans/2026-02-27-project-status-counts-fix-design.md
git commit -m "docs: 更新项目状态统计修复设计文档状态为已完成"
```
**Step 4: 推送所有提交**
```bash
git push origin dev
```
---
## 验收清单
在完成所有任务后,验证以下内容:
### 功能验收
- [ ] 后端接口正确返回统计数字
- [ ] 前端标签页显示正确统计
- [ ] 搜索不影响统计数字
- [ ] 分页不影响统计数字
- [ ] 状态过滤不影响统计数字
### 性能验收
- [ ] 统计接口响应时间 < 100ms
- [ ] 页面加载流畅
### 代码质量
- [ ] 后端代码符合规范
- [ ] 前端代码符合规范
- [ ] 提交信息清晰
---
## 注意事项
1. **测试数据准备**: 如果数据库中没有足够的项目数据,可以先插入一些测试数据以验证统计功能
2. **错误处理**: 当前实现中,如果统计接口失败,会在控制台显示错误但不阻塞列表加载
3. **性能考虑**: 如果项目数量很大(> 10000建议后续优化为 GROUP BY 单次查询
---
## 回滚方案
如果实施后发现问题,可以通过以下步骤回滚:
1. **回滚前端代码**:
```bash
git revert <commit-hash-of-task-6-and-7>
```
2. **回滚后端代码**:
```bash
git revert <commit-hash-of-task-1-to-4>
```
3. **重新部署服务**
---
## 相关文档
- 设计文档: `docs/plans/2026-02-27-project-status-counts-fix-design.md`
- 若依框架文档: 项目根目录的 `CLAUDE.md`
- MyBatis Plus 文档: https://baomidou.com/