需求分解
This commit is contained in:
612
openspec/changes/add-project-management/design.md
Normal file
612
openspec/changes/add-project-management/design.md
Normal file
@@ -0,0 +1,612 @@
|
||||
# Design: 项目管理模块
|
||||
|
||||
## 概述
|
||||
本文档描述项目管理模块的技术设计方案,包括系统架构、数据模型、API设计等。
|
||||
|
||||
## 系统架构
|
||||
|
||||
### 模块划分
|
||||
遵循若依框架的分层架构,新建 `ruoyi-dpc` 模块与若依框架代码分离,Controller 层也放在新建模块中:
|
||||
|
||||
```
|
||||
ruoyi-dpc/ (新建模块)
|
||||
├── pom.xml # 模块依赖配置
|
||||
├── src/main/java/com/ruoyi/dpc/
|
||||
│ ├── controller/
|
||||
│ │ └── DpcProjectController.java # 项目控制器
|
||||
│ ├── domain/
|
||||
│ │ ├── DpcProject.java # 项目实体
|
||||
│ │ ├── DpcProjectPerson.java # 项目人员关联
|
||||
│ │ ├── dto/
|
||||
│ │ │ ├── DpcProjectDTO.java # 项目数据传输对象
|
||||
│ │ │ ├── DpcProjectQueryDTO.java # 项目查询DTO
|
||||
│ │ │ └── DpcProjectImportDTO.java # 项目导入DTO
|
||||
│ │ └── vo/
|
||||
│ │ ├── DpcProjectVO.java # 项目视图对象
|
||||
│ │ └── DpcProjectQueryVO.java # 查询视图对象
|
||||
│ ├── mapper/
|
||||
│ │ ├── DpcProjectMapper.java
|
||||
│ │ └── DpcProjectPersonMapper.java
|
||||
│ └── service/
|
||||
│ ├── IDpcProjectService.java
|
||||
│ └── impl/
|
||||
│ └── DpcProjectServiceImpl.java
|
||||
└── src/main/resources/mapper/dpc/
|
||||
├── DpcProjectMapper.xml
|
||||
└── DpcProjectPersonMapper.xml
|
||||
|
||||
ruoyi-ui/src/
|
||||
├── api/
|
||||
│ └── dpcProject.js # API请求定义
|
||||
└── views/
|
||||
└── dpcProject/
|
||||
├── index.vue # 项目列表页
|
||||
├── add-or-edit.vue # 新增/编辑弹窗
|
||||
└── import-history.vue # 导入历史项目弹窗
|
||||
```
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 数据库表设计
|
||||
|
||||
#### dpc_project (项目主表)
|
||||
|
||||
| 字段名 | 类型 | 说明 | 约束 |
|
||||
|-------|------|------|-----|
|
||||
| project_id | BIGINT | 项目ID | PK, AUTO_INCREMENT |
|
||||
| project_name | VARCHAR(100) | 项目名称 | NOT NULL |
|
||||
| description | VARCHAR(500) | 项目描述 | |
|
||||
| status | CHAR(1) | 状态 | NOT NULL, DEFAULT '0' |
|
||||
| target_count | INT | 目标人数 | NOT NULL, DEFAULT 0 |
|
||||
| warning_count | INT | 预警人数 | NOT NULL, DEFAULT 0 |
|
||||
| start_date | DATE | 开始日期 | |
|
||||
| end_date | DATE | 结束日期 | |
|
||||
| is_archived | CHAR(1) | 是否归档 | DEFAULT '0' |
|
||||
| archive_file_path | VARCHAR(255) | 归档文件路径 | |
|
||||
| create_by | VARCHAR(64) | 创建者 | |
|
||||
| create_time | DATETIME | 创建时间 | |
|
||||
| update_by | VARCHAR(64) | 更新者 | |
|
||||
| update_time | DATETIME | 更新时间 | |
|
||||
| remark | VARCHAR(500) | 备注 | |
|
||||
|
||||
**状态枚举值**:
|
||||
- `0`: 进行中
|
||||
- `1`: 已完成
|
||||
- `2`: 已归档
|
||||
|
||||
#### dpc_project_person (项目人员关联表)
|
||||
|
||||
| 字段名 | 类型 | 说明 | 约束 |
|
||||
|-------|------|------|-----|
|
||||
| id | BIGINT | 主键ID | PK, AUTO_INCREMENT |
|
||||
| project_id | BIGINT | 项目ID | FK -> dpc_project.project_id |
|
||||
| person_id | BIGINT | 人员ID | FK -> sys_user.user_id |
|
||||
| person_name | VARCHAR(30) | 人员姓名 | 冗余字段 |
|
||||
| person_dept_id | BIGINT | 部门ID | 冗余字段 |
|
||||
|
||||
**索引**:
|
||||
- `idx_project_id`: (project_id)
|
||||
- `uk_project_person`: (project_id, person_id) 唯一索引
|
||||
|
||||
### 实体类设计
|
||||
|
||||
#### DpcProject.java
|
||||
```java
|
||||
@Data
|
||||
@TableName("dpc_project")
|
||||
public class DpcProject {
|
||||
/** 项目ID */
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long projectId;
|
||||
|
||||
/** 项目名称 */
|
||||
@NotBlank(message = "项目名称不能为空")
|
||||
@Size(max = 100, message = "项目名称不能超过100个字符")
|
||||
private String projectName;
|
||||
|
||||
/** 项目描述 */
|
||||
@Size(max = 500, message = "项目描述不能超过500个字符")
|
||||
private String description;
|
||||
|
||||
/** 状态(0进行中 1已完成 2已归档) */
|
||||
private String status;
|
||||
|
||||
/** 目标人数 */
|
||||
private Integer targetCount;
|
||||
|
||||
/** 预警人数 */
|
||||
private Integer warningCount;
|
||||
|
||||
/** 开始日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date startDate;
|
||||
|
||||
/** 结束日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date endDate;
|
||||
|
||||
/** 是否归档 */
|
||||
private String isArchived;
|
||||
|
||||
/** 归档文件路径 */
|
||||
private String archiveFilePath;
|
||||
|
||||
/** 创建者 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
/** 创建时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/** 更新者 */
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updateBy;
|
||||
|
||||
/** 更新时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
@Transient
|
||||
private List<Long> personIds; // 关联人员ID列表
|
||||
}
|
||||
```
|
||||
|
||||
#### 审计字段自动填充配置
|
||||
|
||||
```java
|
||||
/**
|
||||
* MyBatis Plus 审计字段自动填充处理器
|
||||
*/
|
||||
@Component
|
||||
public class DpcMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
@Resource
|
||||
private TokenService tokenService;
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
|
||||
this.strictInsertFill(metaObject, "createBy", String.class, getUsername());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
|
||||
this.strictUpdateFill(metaObject, "updateBy", String.class, getUsername());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户名
|
||||
*/
|
||||
private String getUsername() {
|
||||
try {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
return loginUser != null ? loginUser.getUsername() : "system";
|
||||
} catch (Exception e) {
|
||||
return "system";
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 实体类审计字段注解
|
||||
|
||||
```java
|
||||
@Data
|
||||
@TableName("dpc_project")
|
||||
public class DpcProject {
|
||||
// ... 其他字段
|
||||
|
||||
/** 创建者 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
/** 创建时间 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/** 更新者 */
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updateBy;
|
||||
|
||||
/** 更新时间 */
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
}
|
||||
```
|
||||
|
||||
**配置说明**:
|
||||
- `@TableField(fill = FieldFill.INSERT)` - 仅在插入时自动填充
|
||||
- `@TableField(fill = FieldFill.INSERT_UPDATE)` - 插入和更新时都自动填充
|
||||
- `MetaObjectHandler` 处理器会自动从 Spring Security 上下文中获取当前登录用户
|
||||
|
||||
### DTO 设计
|
||||
|
||||
按照全局配置要求,接口传参使用单独的 DTO,不与 entity 混用。
|
||||
|
||||
#### DpcProjectDTO.java(新增/修改项目DTO)
|
||||
```java
|
||||
@Data
|
||||
public class DpcProjectDTO {
|
||||
/** 项目名称 */
|
||||
@NotBlank(message = "项目名称不能为空")
|
||||
@Size(max = 100, message = "项目名称不能超过100个字符")
|
||||
private String projectName;
|
||||
|
||||
/** 项目描述 */
|
||||
@Size(max = 500, message = "项目描述不能超过500个字符")
|
||||
private String description;
|
||||
|
||||
/** 开始日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date startDate;
|
||||
|
||||
/** 结束日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date endDate;
|
||||
|
||||
/** 关联人员ID列表 */
|
||||
@NotEmpty(message = "请至少选择一名参与人员")
|
||||
private List<Long> personIds;
|
||||
}
|
||||
```
|
||||
|
||||
#### DpcProjectQueryDTO.java(查询项目DTO)
|
||||
```java
|
||||
@Data
|
||||
public class DpcProjectQueryDTO {
|
||||
/** 项目名称(模糊搜索) */
|
||||
private String projectName;
|
||||
|
||||
/** 状态 */
|
||||
private String status;
|
||||
|
||||
/** 创建时间范围开始 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTimeStart;
|
||||
|
||||
/** 创建时间范围结束 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTimeEnd;
|
||||
}
|
||||
```
|
||||
|
||||
#### DpcProjectImportDTO.java(导入历史项目DTO)
|
||||
```java
|
||||
@Data
|
||||
public class DpcProjectImportDTO {
|
||||
/** 历史项目ID */
|
||||
@NotNull(message = "请选择要导入的历史项目")
|
||||
private Long historyProjectId;
|
||||
|
||||
/** 新项目名称 */
|
||||
@NotBlank(message = "新项目名称不能为空")
|
||||
@Size(max = 100, message = "项目名称不能超过100个字符")
|
||||
private String projectName;
|
||||
}
|
||||
```
|
||||
|
||||
#### DTO 与 Entity 转换
|
||||
```java
|
||||
/**
|
||||
* DTO 与 Entity 转换工具类
|
||||
*/
|
||||
public class DpcProjectConverter {
|
||||
|
||||
/**
|
||||
* DTO 转 Entity(新增/修改)
|
||||
*/
|
||||
public static DpcProject toEntity(DpcProjectDTO dto) {
|
||||
if (dto == null) {
|
||||
return null;
|
||||
}
|
||||
DpcProject entity = new DpcProject();
|
||||
entity.setProjectName(dto.getProjectName());
|
||||
entity.setDescription(dto.getDescription());
|
||||
entity.setStartDate(dto.getStartDate());
|
||||
entity.setEndDate(dto.getEndDate());
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entity 转 VO
|
||||
*/
|
||||
public static DpcProjectVO toVO(DpcProject entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
DpcProjectVO vo = new DpcProjectVO();
|
||||
BeanUtils.copyProperties(entity, vo);
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entity 列表转 VO 列表
|
||||
*/
|
||||
public static List<DpcProjectVO> toVOList(List<DpcProject> entityList) {
|
||||
if (entityList == null || entityList.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return entityList.stream()
|
||||
.map(DpcProjectConverter::toVO)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Controller 使用 DTO
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/dpc/project")
|
||||
public class DpcProjectController {
|
||||
|
||||
@Resource
|
||||
private IDpcProjectService projectService;
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('dpc:project:add')")
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody DpcProjectDTO dto) {
|
||||
DpcProject project = DpcProjectConverter.toEntity(dto);
|
||||
return AjaxResult.success(projectService.insertProject(project));
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('dpc:project:edit')")
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Validated @RequestBody DpcProjectDTO dto) {
|
||||
DpcProject project = DpcProjectConverter.toEntity(dto);
|
||||
return AjaxResult.success(projectService.updateProject(project));
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('dpc:project:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(DpcProjectQueryDTO queryDTO) {
|
||||
DpcProject project = new DpcProject();
|
||||
// 将查询条件转换到实体
|
||||
BeanUtils.copyProperties(queryDTO, project);
|
||||
startPage();
|
||||
List<DpcProject> list = projectService.selectProjectList(project);
|
||||
List<DpcProjectVO> voList = DpcProjectConverter.toVOList(list);
|
||||
return getDataTable(voList);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API设计
|
||||
|
||||
### RESTful API规范
|
||||
|
||||
| 方法 | 路径 | 说明 | 权限 |
|
||||
|-----|------|------|-----|
|
||||
| GET | /project/list | 查询项目列表 | project:list |
|
||||
| GET | /project/{id} | 查询项目详情 | project:query |
|
||||
| POST | /project | 新增项目 | project:add |
|
||||
| PUT | /project | 修改项目 | project:edit |
|
||||
| DELETE | /project/{ids} | 删除项目 | project:remove |
|
||||
| GET | /project/history/{id} | 获取历史项目配置 | project:query |
|
||||
| POST | /project/import | 导入历史项目 | project:add |
|
||||
| POST | /project/archive/{id} | 归档项目 | project:archive |
|
||||
| POST | /project/reanalyze/{id} | 重新分析 | project:reanalyze |
|
||||
|
||||
### 请求/响应格式
|
||||
|
||||
#### 查询项目列表
|
||||
**请求**: `GET /project/list?projectName=xxx&status=0&pageNum=1&pageSize=10`
|
||||
|
||||
**响应**:
|
||||
```json
|
||||
{
|
||||
"total": 100,
|
||||
"rows": [
|
||||
{
|
||||
"projectId": 1,
|
||||
"projectName": "2026年Q1初核排查",
|
||||
"description": "季度常规排查",
|
||||
"status": "0",
|
||||
"targetCount": 100,
|
||||
"warningCount": 5,
|
||||
"createTime": "2026-01-01 10:00:00"
|
||||
}
|
||||
],
|
||||
"code": 200,
|
||||
"msg": "查询成功"
|
||||
}
|
||||
```
|
||||
|
||||
#### 新增项目
|
||||
**请求**: `POST /project`
|
||||
|
||||
```json
|
||||
{
|
||||
"projectName": "2026年Q1初核排查",
|
||||
"description": "季度常规排查",
|
||||
"startDate": "2026-01-01",
|
||||
"endDate": "2026-03-31",
|
||||
"personIds": [1, 2, 3, 4, 5]
|
||||
}
|
||||
```
|
||||
|
||||
**响应**:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "新增成功"
|
||||
}
|
||||
```
|
||||
|
||||
## 业务逻辑设计
|
||||
|
||||
### 项目状态流转
|
||||
|
||||
```
|
||||
[新建] → [进行中] → [已完成] → [已归档]
|
||||
↑
|
||||
|---- [重新分析]
|
||||
```
|
||||
|
||||
### 核心业务规则
|
||||
|
||||
1. **新建项目**
|
||||
- 项目名称必填
|
||||
- 至少选择一名人员
|
||||
- 默认状态为"进行中"
|
||||
|
||||
2. **导入历史项目**
|
||||
- 选择已完成的历史项目
|
||||
- 复制人员配置
|
||||
- 生成新项目(状态为"进行中")
|
||||
|
||||
3. **归档项目**
|
||||
- 只能归档"已完成"状态的项目
|
||||
- 生成PDF归档文件
|
||||
- 更新项目状态为"已归档"
|
||||
|
||||
4. **重新分析**
|
||||
- 只能对"已完成"项目执行
|
||||
- 异步执行风险模型
|
||||
- 更新预警人数
|
||||
|
||||
## 前端设计
|
||||
|
||||
### 页面组件结构
|
||||
|
||||
#### 项目列表页 (index.vue)
|
||||
```
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索区域 -->
|
||||
<el-form :inline="true">
|
||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" />
|
||||
<el-button @click="handleQuery">搜索</el-button>
|
||||
<el-button @click="handleAdd">新建项目</el-button>
|
||||
<el-button @click="handleImport">导入历史项目</el-button>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table :data="projectList">
|
||||
<el-table-column prop="projectName" label="项目名称" />
|
||||
<el-table-column prop="description" label="项目描述" />
|
||||
<el-table-column prop="createTime" label="创建时间" />
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.status === '0'">进行中</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === '1'" type="success">已完成</el-tag>
|
||||
<el-tag v-else type="info">已归档</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="targetCount" label="目标人数" />
|
||||
<el-table-column prop="warningCount" label="预警人数" />
|
||||
<el-table-column label="操作" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button v-if="scope.row.status === '0'" @click="handleEnter(scope.row)">进入项目</el-button>
|
||||
<el-button v-if="scope.row.status === '1'" @click="handleViewResult(scope.row)">查看结果</el-button>
|
||||
<el-button v-if="scope.row.status === '1'" @click="handleReanalyze(scope.row)">重新分析</el-button>
|
||||
<el-button v-if="scope.row.status === '1'" @click="handleArchive(scope.row)">归档</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
### API封装 (project.js)
|
||||
```javascript
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询项目列表
|
||||
export function listProject(query) {
|
||||
return request({
|
||||
url: '/dpc/project/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 新增项目
|
||||
export function addProject(data) {
|
||||
return request({
|
||||
url: '/dpc/project',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 归档项目
|
||||
export function archiveProject(projectId) {
|
||||
return request({
|
||||
url: '/dpc/project/archive/' + projectId,
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
// 重新分析
|
||||
export function reanalyzeProject(projectId) {
|
||||
return request({
|
||||
url: '/dpc/project/reanalyze/' + projectId,
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
// 导入历史项目
|
||||
export function importProject(data) {
|
||||
return request({
|
||||
url: '/dpc/project/import',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## 技术约束
|
||||
|
||||
1. **后端**
|
||||
- Spring Boot 3.5.8
|
||||
- 使用 MyBatis Plus 3.5.10 进行数据访问(Spring Boot 3 适配版)
|
||||
- 使用 `@Resource` 注入依赖(替代 `@Autowired`)
|
||||
- 使用 `@Data` 注解简化实体类
|
||||
- 实体类不继承 BaseEntity,基础字段直接定义在实体类中
|
||||
- 新建 `ruoyi-dpc` 模块,与若依框架代码分离
|
||||
- Controller 层也要放在新建模块中(不在 `ruoyi-admin` 中)
|
||||
- 接口传参使用单独的 DTO,不与 entity 混用
|
||||
|
||||
2. **前端**
|
||||
- Vue 2.6.12
|
||||
- 使用 Element UI 2.15.14 组件库
|
||||
- 遵循现有视图组件风格
|
||||
- 在添加页面和组件后,注意与数据库中菜单表进行联动修改
|
||||
|
||||
3. **数据库**
|
||||
- MySQL 8.2.0
|
||||
- 表名使用 `dpc_` 前缀(项目英文名首字母集合)
|
||||
|
||||
4. **安全**
|
||||
- 所有API需要 `@PreAuthorize` 权限注解
|
||||
- 敏感操作记录操作日志
|
||||
|
||||
5. **文档**
|
||||
- 完成后端代码 controller 层代码生成测试后,在项目文件目录下生成 API 文档
|
||||
|
||||
6. **测试**
|
||||
- 测试方式为生成可执行的测试脚本
|
||||
- 在测试中启动的进程,在测试完成后立刻结束
|
||||
- `/login/test` 接口可传入 `username` 和 `password` 获取 token(测试账号:admin/admin123)
|
||||
- swagger-ui 地址:`/swagger-ui/index.html`
|
||||
|
||||
7. **审计字段自动填充**
|
||||
- 配置 MyBatis Plus `MetaObjectHandler` 实现审计字段自动填充
|
||||
- 插入操作自动填充:`create_by`、`create_time`
|
||||
- 更新操作自动填充:`update_by`、`update_time`
|
||||
|
||||
## 待确认事项
|
||||
|
||||
1. **PDF生成方案**:需确认使用 iText 或其他方案
|
||||
2. **异步任务实现**:重新分析是否需要集成若依的定时任务模块
|
||||
3. **菜单配置**:项目管理在系统菜单中的位置
|
||||
112
openspec/changes/add-project-management/proposal.md
Normal file
112
openspec/changes/add-project-management/proposal.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Proposal: 添加项目管理模块
|
||||
|
||||
## Change ID
|
||||
`add-project-management`
|
||||
|
||||
## Summary
|
||||
添加项目管理模块,实现初核项目的创建、查询、状态管理、归档等核心功能。该模块是系统的首页和入口,用于管理所有历史创建的核查项目。
|
||||
|
||||
## Motivation
|
||||
目前系统缺少项目管理的核心功能模块。用户需要:
|
||||
1. 统一管理所有初核项目
|
||||
2. 快速查找和定位项目
|
||||
3. 跟踪项目状态(进行中/已完成)
|
||||
4. 监控预警人数变化
|
||||
5. 对已完成项目进行归档管理
|
||||
|
||||
## Scope
|
||||
本提案实现以下功能(不包括快捷入口区):
|
||||
|
||||
### 包含的功能
|
||||
- **1.1 导航与搜索区**
|
||||
- 项目搜索(模糊搜索项目名称)
|
||||
- 新建项目(标准表单创建)
|
||||
- 导入历史项目(复制历史配置快速创建)
|
||||
|
||||
- **1.2 项目列表区**
|
||||
- 项目信息展示(名称、描述、创建日期、状态、目标人数、预警人数)
|
||||
- 项目状态标识(进行中/已完成)
|
||||
- 预警人数动态更新
|
||||
- 查看结果(已完成项目跳转结果页)
|
||||
- 重新分析(已完成项目重新运行风险模型)
|
||||
- 归档项目(生成PDF导出)
|
||||
- 进入项目(进行中项目跳转工作台)
|
||||
|
||||
### 明确排除
|
||||
- **1.3 快捷入口区**(创建季度初核、创建新员工排查等快捷功能)
|
||||
|
||||
## Proposed Design
|
||||
|
||||
详见 [design.md](./design.md)
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### 选项1:使用若依代码生成器
|
||||
**优点**:
|
||||
- 快速生成标准CRUD代码
|
||||
- 符合项目规范
|
||||
|
||||
**缺点**:
|
||||
- 需要手动调整业务逻辑
|
||||
- 缺少复杂的业务规则处理
|
||||
|
||||
**决定**:不采用。项目管理模块包含复杂的业务逻辑(状态流转、归档、重新分析等),需要自定义实现。
|
||||
|
||||
### 选项2:完全自定义开发
|
||||
**优点**:
|
||||
- 完全控制实现细节
|
||||
- 灵活应对业务需求变化
|
||||
|
||||
**缺点**:
|
||||
- 开发周期较长
|
||||
- 需要确保代码规范一致
|
||||
|
||||
**决定**:采用。参考现有系统模块的代码模式,确保与项目风格一致。
|
||||
|
||||
## Impact
|
||||
|
||||
### 后端影响
|
||||
- 新建 `ruoyi-dpc` 模块,与若依框架代码分离(包含 Controller、Service、Mapper、Domain 层)
|
||||
- 新增表:`dpc_project`(项目主表)、`dpc_project_person`(项目人员关联表)
|
||||
- 新增权限:`dpc:project:list`, `dpc:project:query`, `dpc:project:add`, `dpc:project:edit`, `dpc:project:remove`, `dpc:project:archive`, `dpc:project:reanalyze`
|
||||
- Controller层:`ruoyi-dpc/src/main/java/com/ruoyi/dpc/controller/DpcProjectController.java`
|
||||
|
||||
### 前端影响
|
||||
- 新增视图:`ruoyi-ui/src/views/dpcProject/`
|
||||
- 新增API:`ruoyi-ui/src/api/dpcProject.js`
|
||||
- 新增菜单:项目管理(在系统菜单中添加,注意与数据库中菜单表进行联动修改)
|
||||
|
||||
### 数据库影响
|
||||
- 新增表:`dpc_project`(项目主表)
|
||||
- 新增表:`dpc_project_person`(项目人员关联表)
|
||||
|
||||
## Dependencies
|
||||
- 依赖现有用户系统(`SysUser`)进行人员选择
|
||||
- 依赖部门系统(`SysDept`)进行部门范围选择
|
||||
- 依赖文件上传功能(项目附件、归档PDF)
|
||||
|
||||
## Related Changes
|
||||
无
|
||||
|
||||
## Open Questions
|
||||
1. **项目人员关联方式**:使用多对多关联表还是JSON字段存储人员列表?
|
||||
- 建议:使用 `dpc_project_person` 关联表,便于查询和扩展
|
||||
|
||||
2. **归档PDF生成**:使用什么工具生成PDF?
|
||||
- 建议:使用 iText 或 Apache POI,需要后续确认
|
||||
|
||||
3. **重新分析的触发方式**:同步还是异步?
|
||||
- 建议:异步处理,避免长时间阻塞
|
||||
|
||||
## Success Criteria
|
||||
- [ ] 用户可以创建新项目并填写完整信息
|
||||
- [ ] 用户可以搜索项目(按名称模糊匹配)
|
||||
- [ ] 项目列表正确显示状态和预警人数
|
||||
- [ ] 进行中项目可以进入工作台
|
||||
- [ ] 已完成项目可以查看结果
|
||||
- [ ] 已完成项目可以归档并生成PDF
|
||||
- [ ] 已完成项目可以重新分析
|
||||
|
||||
## References
|
||||
- [模块设计文档](../../doc/modules/01-项目管理模块.md)
|
||||
- [若依开发文档](https://doc.ruoyi.vip/)
|
||||
@@ -0,0 +1,214 @@
|
||||
# Spec: 项目管理能力
|
||||
|
||||
## 概述
|
||||
本规范定义了项目管理模块的核心能力,包括项目的创建、查询、状态管理和归档功能。
|
||||
|
||||
---
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 项目列表查询
|
||||
|
||||
系统 MUST 允许用户查询所有项目列表,支持按项目名称进行模糊搜索。
|
||||
|
||||
#### Scenario: 查询所有项目
|
||||
**Given** 用户已登录系统并具有项目查看权限
|
||||
**When** 用户进入项目管理页面
|
||||
**Then** 系统显示所有项目列表,包括项目名称、描述、创建时间、状态、目标人数、预警人数
|
||||
|
||||
#### Scenario: 按名称搜索项目
|
||||
**Given** 用户在项目管理页面
|
||||
**When** 用户在搜索框输入"Q1初核"并点击搜索
|
||||
**Then** 系统显示所有包含"Q1初核"的项目
|
||||
|
||||
#### Scenario: 项目状态标识
|
||||
**Given** 项目列表中有多个不同状态的项目
|
||||
**When** 用户查看项目列表
|
||||
**Then** 进行中的项目显示蓝色标签,已完成的项目显示绿色标签,已归档的项目显示灰色标签
|
||||
|
||||
#### Scenario: 预警人数动态更新
|
||||
**Given** 存在状态为"进行中"的项目
|
||||
**When** 用户刷新项目列表
|
||||
**Then** 预警人数显示最新的统计值
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 创建新项目
|
||||
|
||||
系统 MUST 允许用户创建新的初核项目,填写项目基本信息并选择参与人员。
|
||||
|
||||
#### Scenario: 创建标准项目
|
||||
**Given** 用户在项目管理页面
|
||||
**When** 用户点击"新建项目"按钮
|
||||
**Then** 系统打开新增项目弹窗,包含项目名称、项目描述、时间范围、人员选择字段
|
||||
|
||||
#### Scenario: 必填字段验证
|
||||
**Given** 用户新增项目时未填写项目名称
|
||||
**When** 用户点击"确定"按钮
|
||||
**Then** 系统提示"项目名称不能为空"
|
||||
|
||||
#### Scenario: 至少选择一名人员
|
||||
**Given** 用户新增项目时未选择任何人员
|
||||
**When** 用户点击"确定"按钮
|
||||
**Then** 系统提示"请至少选择一名参与人员"
|
||||
|
||||
#### Scenario: 创建成功
|
||||
**Given** 用户填写了完整的项目信息
|
||||
**When** 用户点击"确定"按钮
|
||||
**Then** 系统创建项目并提示"新增成功",项目列表刷新显示新项目
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 导入历史项目
|
||||
|
||||
系统 MUST 允许用户从已完成的历史项目导入配置,快速创建新项目。
|
||||
|
||||
#### Scenario: 查看历史项目列表
|
||||
**Given** 用户点击"导入历史项目"按钮
|
||||
**When** 系统打开导入历史项目弹窗
|
||||
**Then** 系统显示所有已完成状态的历史项目列表
|
||||
|
||||
#### Scenario: 选择历史项目
|
||||
**Given** 用户在导入历史项目弹窗中
|
||||
**When** 用户选择一个历史项目
|
||||
**Then** 系统显示该项目的详细信息(人员范围、配置等)
|
||||
|
||||
#### Scenario: 复制配置创建新项目
|
||||
**Given** 用户选择了历史项目并填写了新项目名称
|
||||
**When** 用户点击"确定"按钮
|
||||
**Then** 系统创建新项目,复制原项目的人员和配置,状态为"进行中"
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 项目状态管理
|
||||
|
||||
系统 MUST 支持项目状态的流转和管理。
|
||||
|
||||
#### Scenario: 进入进行中的项目
|
||||
**Given** 存在状态为"进行中"的项目
|
||||
**When** 用户点击"进入项目"按钮
|
||||
**Then** 系统跳转到该项目的工作台页面
|
||||
|
||||
#### Scenario: 查看已完成项目结果
|
||||
**Given** 存在状态为"已完成"的项目
|
||||
**When** 用户点击"查看结果"按钮
|
||||
**Then** 系统跳转到该项目的初核结果总览页面
|
||||
|
||||
#### Scenario: 重新分析已完成项目
|
||||
**Given** 存在状态为"已完成"的项目
|
||||
**When** 用户点击"重新分析"按钮
|
||||
**Then** 系统基于原有数据重新运行风险模型,更新预警人数和结果
|
||||
|
||||
#### Scenario: 重新分析权限控制
|
||||
**Given** 用户没有重新分析的权限
|
||||
**When** 用户查看项目列表
|
||||
**Then** 不显示"重新分析"按钮
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 项目归档
|
||||
|
||||
系统 MUST 允许用户将已结束的项目归档,并生成PDF归档文件。
|
||||
|
||||
#### Scenario: 归档已完成项目
|
||||
**Given** 存在状态为"已完成"的项目
|
||||
**When** 用户点击"归档"按钮
|
||||
**Then** 系统生成PDF归档文件,更新项目状态为"已归档"
|
||||
|
||||
#### Scenario: 归档状态校验
|
||||
**Given** 存在状态为"进行中"的项目
|
||||
**When** 用户尝试归档该项目
|
||||
**Then** 系统提示"只能归档已完成的项目"
|
||||
|
||||
#### Scenario: 归档文件下载
|
||||
**Given** 存在已归档的项目
|
||||
**When** 用户点击"下载归档"按钮
|
||||
**Then** 系统下载该项目的PDF归档文件
|
||||
|
||||
#### Scenario: 归档项目不显示在默认列表
|
||||
**Given** 存在已归档的项目
|
||||
**When** 用户查看项目列表
|
||||
**Then** 默认不显示已归档的项目
|
||||
|
||||
#### Scenario: 查看归档项目
|
||||
**Given** 用户想查看已归档的项目
|
||||
**When** 用户勾选"显示已归档"选项
|
||||
**Then** 系统在列表中显示已归档的项目
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 项目数据模型
|
||||
|
||||
系统 MUST 使用正确的数据结构存储项目信息。
|
||||
|
||||
#### Scenario: 项目基础信息存储
|
||||
**Given** 创建新项目
|
||||
**When** 系统保存项目数据
|
||||
**Then** 数据库存储:项目ID、项目名称、项目描述、创建时间、状态、目标人数、预警人数
|
||||
|
||||
#### Scenario: 项目人员关联存储
|
||||
**Given** 项目包含多名参与人员
|
||||
**When** 系统保存项目数据
|
||||
**Then** 人员在关联表中存储,包含项目ID、人员ID、人员姓名(冗余)
|
||||
|
||||
#### Scenario: 状态枚举值
|
||||
**Given** 项目状态字段
|
||||
**When** 系统存储项目状态
|
||||
**Then** 状态值为:'0'进行中、'1'已完成、'2'已归档
|
||||
|
||||
---
|
||||
|
||||
### Requirement: API接口规范
|
||||
|
||||
系统 MUST 提供符合RESTful规范的API接口。
|
||||
|
||||
#### Scenario: 查询项目列表API
|
||||
**Given** 前端需要获取项目列表
|
||||
**When** 调用 `GET /dpc/project/list?projectName=xxx&pageNum=1&pageSize=10`
|
||||
**Then** 返回分页数据,包含total、rows、code、msg
|
||||
|
||||
#### Scenario: 创建项目API
|
||||
**Given** 前端需要创建新项目
|
||||
**When** 调用 `POST /dpc/project` 并传递项目数据
|
||||
**Then** 返回操作结果,code为200表示成功
|
||||
|
||||
#### Scenario: 归档项目API
|
||||
**Given** 前端需要归档项目
|
||||
**When** 调用 `POST /dpc/project/archive/{projectId}`
|
||||
**Then** 系统执行归档操作并返回结果
|
||||
|
||||
#### Scenario: 权限校验
|
||||
**Given** 用户没有相应的权限
|
||||
**When** 调用需要权限的API
|
||||
**Then** 返回403错误,提示无权限访问
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 前端用户体验
|
||||
|
||||
系统 MUST 提供友好的用户交互体验。
|
||||
|
||||
#### Scenario: 响应式布局
|
||||
**Given** 用户使用不同分辨率的设备
|
||||
**When** 用户访问项目管理页面
|
||||
**Then** 页面布局自适应,所有功能可用
|
||||
|
||||
#### Scenario: 操作反馈
|
||||
**Given** 用户执行操作
|
||||
**When** 操作成功或失败
|
||||
**Then** 系统显示明确的成功或错误提示消息
|
||||
|
||||
#### Scenario: 加载状态
|
||||
**Given** 数据加载需要时间
|
||||
**When** 用户请求数据
|
||||
**Then** 系统显示loading加载状态
|
||||
|
||||
---
|
||||
|
||||
## 相关能力
|
||||
|
||||
- **用户管理能力**:依赖用户系统获取人员信息
|
||||
- **部门管理能力**:依赖部门系统进行部门范围选择
|
||||
- **文件管理能力**:依赖文件上传功能处理项目附件和归档PDF
|
||||
- **项目工作台能力**:进入项目后跳转到工作台(后续实现)
|
||||
- **初核结果能力**:查看结果跳转到结果页(后续实现)
|
||||
257
openspec/changes/add-project-management/tasks.md
Normal file
257
openspec/changes/add-project-management/tasks.md
Normal file
@@ -0,0 +1,257 @@
|
||||
# Tasks: 项目管理模块开发
|
||||
|
||||
本文档列出了实现项目管理模块的具体开发任务,按优先级和依赖关系排序。
|
||||
|
||||
## 阶段1:基础架构搭建
|
||||
|
||||
### 1.1 创建数据库表
|
||||
- [ ] 创建 `dpc_project` 表
|
||||
- [ ] 创建 `dpc_project_person` 表
|
||||
- [ ] 创建索引和外键约束
|
||||
- [ ] 准备测试数据
|
||||
|
||||
**验证**:执行SQL脚本,表结构创建成功,可以使用 `DESC dpc_project;` 查看表结构
|
||||
|
||||
### 1.2 创建后端模块结构
|
||||
- [ ] 创建 `ruoyi-dpc` 新模块
|
||||
- [ ] 配置模块 `pom.xml` 依赖
|
||||
- [ ] 在根 `pom.xml` 中添加模块引用
|
||||
- [ ] 在 `ruoyi-admin` 的 `pom.xml` 中添加对 `ruoyi-dpc` 的依赖
|
||||
- [ ] 配置 Spring 扫描 `com.ruoyi.dpc.controller` 包
|
||||
- [ ] 创建包结构:`com.ruoyi.dpc.controller`, `com.ruoyi.dpc.domain`, `com.ruoyi.dpc.mapper`, `com.ruoyi.dpc.service`
|
||||
|
||||
**验证**:项目可以正常编译启动
|
||||
|
||||
### 1.3 创建实体类和DTO
|
||||
- [ ] 创建 `DpcProject.java` 实体类(使用 `@Data` 注解,不继承 BaseEntity)
|
||||
- [ ] 创建 `DpcProjectPerson.java` 实体类(使用 `@Data` 注解)
|
||||
- [ ] 创建 `DpcProjectVO.java` 视图对象
|
||||
- [ ] 创建 `DpcProjectQueryVO.java` 查询视图对象
|
||||
- [ ] 创建 `DpcProjectDTO.java` 数据传输对象(新增/修改)
|
||||
- [ ] 创建 `DpcProjectQueryDTO.java` 查询DTO
|
||||
- [ ] 创建 `DpcProjectImportDTO.java` 导入DTO
|
||||
- [ ] 为审计字段添加 `@TableField` 注解配置自动填充
|
||||
|
||||
**验证**:实体类和DTO编译通过,字段注解正确
|
||||
|
||||
### 1.4 创建DTO转换工具类
|
||||
- [ ] 创建 `DpcProjectConverter.java` 工具类
|
||||
- [ ] 实现 `toEntity(DpcProjectDTO)` 方法
|
||||
- [ ] 实现 `toVO(DpcProject)` 方法
|
||||
- [ ] 实现 `toVOList(List<DpcProject>)` 方法
|
||||
|
||||
**验证**:转换逻辑正确,覆盖所有字段
|
||||
|
||||
### 1.5 配置审计字段自动填充
|
||||
- [ ] 创建 `DpcMetaObjectHandler.java` 实现 `MetaObjectHandler` 接口
|
||||
- [ ] 实现 `insertFill` 方法自动填充 `create_by` 和 `create_time`
|
||||
- [ ] 实现 `updateFill` 方法自动填充 `update_by` 和 `update_time`
|
||||
- [ ] 从 Spring Security 上下文获取当前登录用户
|
||||
- [ ] 将处理器注册为 Spring 组件(`@Component`)
|
||||
|
||||
**验证**:插入和更新操作时审计字段自动填充
|
||||
|
||||
## 阶段2:数据访问层开发
|
||||
|
||||
### 2.1 创建Mapper接口
|
||||
- [ ] 创建 `DpcProjectMapper.java`(使用 MyBatis Plus)
|
||||
- [ ] 创建 `DpcProjectPersonMapper.java`(使用 MyBatis Plus)
|
||||
|
||||
### 2.2 创建Mapper XML
|
||||
- [ ] 创建 `DpcProjectMapper.xml`
|
||||
- [ ] 创建 `DpcProjectPersonMapper.xml`
|
||||
- [ ] 定义基础CRUD SQL(MyBatis Plus 自动生成)
|
||||
- [ ] 定义关联查询SQL(项目+人员)
|
||||
|
||||
**验证**:可以使用MyBatis Log查看SQL执行正确
|
||||
|
||||
## 阶段3:服务层开发
|
||||
|
||||
### 3.1 创建Service接口
|
||||
- [ ] 创建 `IDpcProjectService.java`
|
||||
- [ ] 定义方法签名:
|
||||
- `List<DpcProject> selectProjectList(DpcProject project)`
|
||||
- `DpcProject selectProjectById(Long projectId)`
|
||||
- `int insertProject(DpcProject project)`
|
||||
- `int updateProject(DpcProject project)`
|
||||
- `int deleteProjectByIds(Long[] projectIds)`
|
||||
- `boolean checkProjectNameUnique(DpcProject project)`
|
||||
- `void archiveProject(Long projectId)`
|
||||
- `void reanalyzeProject(Long projectId)`
|
||||
|
||||
### 3.2 实现Service
|
||||
- [ ] 创建 `DpcProjectServiceImpl.java`
|
||||
- [ ] 使用 `@Resource` 注入依赖
|
||||
- [ ] 实现基础CRUD方法
|
||||
- [ ] 实现项目名称唯一性校验
|
||||
- [ ] 实现项目归档逻辑(状态检查、PDF生成)
|
||||
- [ ] 实现重新分析逻辑(异步任务)
|
||||
|
||||
**验证**:单元测试通过,业务逻辑符合需求
|
||||
|
||||
## 阶段4:控制器层开发
|
||||
|
||||
### 4.1 创建Controller
|
||||
- [ ] 创建 `DpcProjectController.java`(位于 `ruoyi-dpc` 模块的 `com.ruoyi.dpc.controller` 包中)
|
||||
- [ ] 实现列表查询接口 `GET /dpc/project/list`
|
||||
- [ ] 实现详情查询接口 `GET /dpc/project/{id}`
|
||||
- [ ] 实现新增接口 `POST /dpc/project`
|
||||
- [ ] 实现修改接口 `PUT /dpc/project`
|
||||
- [ ] 实现删除接口 `DELETE /dpc/project/{ids}`
|
||||
- [ ] 实现归档接口 `POST /dpc/project/archive/{id}`
|
||||
- [ ] 实现重新分析接口 `POST /dpc/project/reanalyze/{id}`
|
||||
- [ ] 实现导入历史项目接口 `POST /dpc/project/import`
|
||||
|
||||
### 4.2 添加权限注解
|
||||
- [ ] 为所有接口添加 `@PreAuthorize` 注解
|
||||
- [ ] 配置权限字符串:
|
||||
- `dpc:project:list`
|
||||
- `dpc:project:query`
|
||||
- `dpc:project:add`
|
||||
- `dpc:project:edit`
|
||||
- `dpc:project:remove`
|
||||
- `dpc:project:archive`
|
||||
- `dpc:project:reanalyze`
|
||||
|
||||
### 4.3 添加操作日志
|
||||
- [ ] 为关键操作添加 `@Log` 注解
|
||||
- [ ] 配置业务类型
|
||||
|
||||
**验证**:使用Postman测试所有接口,返回正确
|
||||
|
||||
## 阶段4.5:生成API文档
|
||||
|
||||
### 4.5.1 生成接口文档
|
||||
- [ ] 使用 SpringDoc/Knife4j 生成 API 文档
|
||||
- [ ] 在项目文件目录下导出 API 文档
|
||||
|
||||
**验证**:API 文档生成成功,包含所有接口
|
||||
|
||||
## 阶段5:前端API开发
|
||||
|
||||
### 5.1 创建API文件
|
||||
- [ ] 创建 `ruoyi-ui/src/api/dpcProject.js`
|
||||
- [ ] 封装所有API请求方法:
|
||||
- `listProject(query)`
|
||||
- `getProject(projectId)`
|
||||
- `addProject(data)`
|
||||
- `updateProject(data)`
|
||||
- `delProject(projectIds)`
|
||||
- `archiveProject(projectId)`
|
||||
- `reanalyzeProject(projectId)`
|
||||
- `importProject(data)`
|
||||
|
||||
**验证**:API方法可以正常调用
|
||||
|
||||
## 阶段6:前端页面开发
|
||||
|
||||
### 6.1 创建项目列表页
|
||||
- [ ] 创建 `ruoyi-ui/src/views/dpcProject/index.vue`
|
||||
- [ ] 实现搜索区域(项目名称输入框、搜索按钮)
|
||||
- [ ] 实现操作按钮(新建、导入历史项目)
|
||||
- [ ] 实现数据表格(项目信息展示)
|
||||
- [ ] 实现状态标签(进行中/已完成/已归档)
|
||||
- [ ] 实现操作列(进入项目、查看结果、重新分析、归档)
|
||||
|
||||
### 6.2 创建新增/编辑弹窗
|
||||
- [ ] 创建 `ruoyi-ui/src/views/dpcProject/add-or-edit.vue`
|
||||
- [ ] 实现项目基本信息表单(项目名称、描述、时间范围)
|
||||
- [ ] 实现人员选择器(多选)
|
||||
- [ ] 实现表单验证
|
||||
|
||||
### 6.3 创建导入历史项目弹窗
|
||||
- [ ] 创建 `ruoyi-ui/src/views/dpcProject/import-history.vue`
|
||||
- [ ] 实现历史项目列表(只显示已完成项目)
|
||||
- [ ] 实现项目详情预览
|
||||
- [ ] 实现新项目配置
|
||||
|
||||
**验证**:页面显示正常,交互流畅
|
||||
|
||||
## 阶段7:菜单与权限配置
|
||||
|
||||
### 7.1 创建系统菜单
|
||||
- [ ] 在系统管理 > 菜单管理中创建"项目管理"菜单
|
||||
- [ ] 配置菜单图标和路由(路径:`dpcProject`)
|
||||
- [ ] 创建子菜单/按钮权限
|
||||
|
||||
### 7.2 配置角色权限
|
||||
- [ ] 为管理员角色分配项目管理权限
|
||||
- [ ] 为其他角色配置适当权限
|
||||
|
||||
**验证**:登录后可以看到项目管理菜单
|
||||
|
||||
## 阶段8:测试与优化
|
||||
|
||||
### 8.1 功能测试
|
||||
- [ ] 测试项目创建流程
|
||||
- [ ] 测试项目搜索功能
|
||||
- [ ] 测试项目状态流转
|
||||
- [ ] 测试项目归档功能
|
||||
- [ ] 测试重新分析功能
|
||||
- [ ] 测试导入历史项目功能
|
||||
|
||||
### 8.2 边界测试
|
||||
- [ ] 测试必填字段验证
|
||||
- [ ] 测试项目名称唯一性
|
||||
- [ ] 测试状态权限控制
|
||||
- [ ] 测试数据权限
|
||||
|
||||
### 8.3 性能优化
|
||||
- [ ] 优化SQL查询
|
||||
- [ ] 添加必要的数据库索引
|
||||
- [ ] 优化大数据量列表加载
|
||||
|
||||
**验证**:所有测试用例通过,无明显性能问题
|
||||
|
||||
## 阶段9:文档与交付
|
||||
|
||||
### 9.1 代码注释
|
||||
- [ ] 为所有公开方法添加JavaDoc注释
|
||||
- [ ] 为复杂逻辑添加行内注释
|
||||
|
||||
### 9.2 更新系统文档
|
||||
- [ ] 更新数据库设计文档
|
||||
- [ ] 更新API接口文档
|
||||
- [ ] 更新用户操作手册
|
||||
|
||||
**验证**:文档完整、准确
|
||||
|
||||
## 任务依赖关系
|
||||
|
||||
```
|
||||
阶段1 (基础架构)
|
||||
↓
|
||||
阶段2 (数据访问层) → 阶段3 (服务层) → 阶段4 (控制器层) → 阶段4.5 (API文档)
|
||||
↓
|
||||
阶段5 (前端API) ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ←
|
||||
↓
|
||||
阶段6 (前端页面)
|
||||
↓
|
||||
阶段7 (菜单权限)
|
||||
↓
|
||||
阶段8 (测试优化)
|
||||
↓
|
||||
阶段9 (文档交付)
|
||||
```
|
||||
|
||||
## 可并行开发任务
|
||||
|
||||
以下任务可以并行开发:
|
||||
- 阶段2和阶段3(后端不同层级)
|
||||
- 阶段5和阶段6的前端页面组件
|
||||
- 阶段7的菜单配置可以在后端开发完成后进行
|
||||
|
||||
## 预计工作量
|
||||
|
||||
| 阶段 | 预计工时 |
|
||||
|-----|---------|
|
||||
| 阶段1 | 0.5天 |
|
||||
| 阶段2 | 0.5天 |
|
||||
| 阶段3 | 1天 |
|
||||
| 阶段4 | 1天 |
|
||||
| 阶段5 | 0.5天 |
|
||||
| 阶段6 | 2天 |
|
||||
| 阶段7 | 0.5天 |
|
||||
| 阶段8 | 1天 |
|
||||
| 阶段9 | 0.5天 |
|
||||
| **总计** | **7.5天** |
|
||||
Reference in New Issue
Block a user