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

579 lines
13 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 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/