# 项目管理状态统计修复实施计划

> **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/design/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/design/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/design/2026-02-27-project-status-counts-fix-design.md`
- 若依框架文档: 项目根目录的 `CLAUDE.md`
- MyBatis Plus 文档: https://baomidou.com/
