diff --git a/doc/plans/2026-02-26-create-project-backend-implementation.md b/doc/plans/2026-02-26-create-project-backend-implementation.md new file mode 100644 index 0000000..a33ccfd --- /dev/null +++ b/doc/plans/2026-02-26-create-project-backend-implementation.md @@ -0,0 +1,943 @@ +# 创建项目功能 - 后端实施计划 + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**目标:** 实现创建项目功能的后端接口,包括数据库表、实体类、DTO/VO、Mapper、Service、Controller + +**架构:** 基于若依框架 + MyBatis Plus,采用分层架构(Controller -> Service -> Mapper) + +**技术栈:** Spring Boot 3.5.8, MyBatis Plus 3.5.10, MySQL 8.2.0, SpringDoc OpenAPI 2.8.14 + +--- + +## 前置条件 + +- MySQL 数据库已启动 +- 后端项目已启动 +- 已有 admin 账号和测试权限 +- 数据库连接配置正确 + +--- + +## Task 1: 创建数据库表和字典数据 + +**文件:** +- Create: `sql/ccdi_project.sql` + +**Step 1: 创建 SQL 脚本文件** + +创建文件 `sql/ccdi_project.sql`,内容如下: + +```sql +-- 创建项目表 +CREATE TABLE `ccdi_project` ( + `project_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '项目ID', + `project_name` VARCHAR(100) NOT NULL COMMENT '项目名称', + `project_desc` VARCHAR(500) DEFAULT NULL COMMENT '项目描述', + `config_type` VARCHAR(20) NOT NULL DEFAULT 'default' COMMENT '配置方式:default-全局默认,custom-自定义', + `project_status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '项目状态:0-进行中,1-已完成,2-已归档', + `target_count` INT NOT NULL DEFAULT 0 COMMENT '目标人数', + `high_risk_count` INT NOT NULL DEFAULT 0 COMMENT '高风险人数', + `medium_risk_count` INT NOT NULL DEFAULT 0 COMMENT '中风险人数', + `low_risk_count` INT NOT NULL DEFAULT 0 COMMENT '低风险人数', + `create_by` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`project_id`), + INDEX `idx_project_name` (`project_name`), + INDEX `idx_project_status` (`project_status`), + INDEX `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='纪检初核项目表'; + +-- 插入项目状态字典 +INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark) +VALUES ('项目状态', 'ccdi_project_status', '0', 'admin', NOW(), '纪检初核项目状态'); + +INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) +VALUES +(1, '进行中', '0', 'ccdi_project_status', '', 'primary', 'Y', '0', 'admin', NOW()), +(2, '已完成', '1', 'ccdi_project_status', '', 'success', 'N', '0', 'admin', NOW()), +(3, '已归档', '2', 'ccdi_project_status', '', 'info', 'N', '0', 'admin', NOW()); + +-- 插入配置方式字典 +INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark) +VALUES ('配置方式', 'ccdi_config_type', '0', 'admin', NOW(), '项目配置方式'); + +INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time) +VALUES +(1, '全局默认模型参数配置', 'default', 'ccdi_config_type', '', 'primary', 'Y', '0', 'admin', NOW()), +(2, '自定义项目规则参数配置', 'custom', 'ccdi_config_type', '', 'warning', 'N', '0', 'admin', NOW()); + +-- 插入菜单权限 +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, menu_type, visible, status, perms, icon, create_by, create_time) +VALUES ('纪检初核管理', 0, 1, 'ccdi', NULL, 'M', '0', '0', '', 'monitor', 'admin', NOW()); + +SET @parent_id = LAST_INSERT_ID(); + +INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, menu_type, visible, status, perms, icon, create_by, create_time) +VALUES ('项目管理', @parent_id, 1, 'project', 'ccdiProject/index', 'C', '0', '0', 'ccdi:project:list', 'project', 'admin', NOW()); + +SET @menu_id = LAST_INSERT_ID(); + +INSERT INTO sys_menu (menu_name, parent_id, order_num, menu_type, visible, status, perms, create_by, create_time) +VALUES +('创建项目', @menu_id, 1, 'F', '0', '0', 'ccdi:project:add', 'admin', NOW()), +('编辑项目', @menu_id, 2, 'F', '0', '0', 'ccdi:project:edit', 'admin', NOW()), +('删除项目', @menu_id, 3, 'F', '0', '0', 'ccdi:project:remove', 'admin', NOW()), +('查询项目', @menu_id, 4, 'F', '0', '0', 'ccdi:project:query', 'admin', NOW()); + +-- 为管理员角色分配权限 +INSERT INTO sys_role_menu (role_id, menu_id) +SELECT 1, menu_id FROM sys_menu WHERE perms LIKE 'ccdi:project:%' OR perms = 'ccdi:project:list'; +``` + +**Step 2: 执行 SQL 脚本** + +运行命令连接数据库并执行脚本: + +```bash +mysql -h -u -p ccdi < sql/ccdi_project.sql +``` + +预期输出:无错误,表创建成功 + +**Step 3: 验证数据库表** + +连接数据库验证表是否创建成功: + +```bash +mysql -h -u -p -e "USE ccdi; SHOW TABLES LIKE 'ccdi_project'; DESC ccdi_project;" +``` + +预期输出:显示 `ccdi_project` 表及其字段结构 + +**Step 4: 验证字典数据** + +验证字典数据是否插入成功: + +```bash +mysql -h -u -p -e "USE ccdi; SELECT * FROM sys_dict_type WHERE dict_type IN ('ccdi_project_status', 'ccdi_config_type'); SELECT * FROM sys_dict_data WHERE dict_type IN ('ccdi_project_status', 'ccdi_config_type');" +``` + +预期输出:显示新插入的字典类型和数据 + +**Step 5: 提交代码** + +```bash +git add sql/ccdi_project.sql +git commit -m "feat: 添加项目表和字典数据SQL脚本" +``` + +--- + +## Task 2: 创建实体类 CcdiProject + +**文件:** +- Create: `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/CcdiProject.java` + +**Step 1: 创建实体类** + +创建文件 `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/CcdiProject.java`: + +```java +package com.ruoyi.info.collection.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +/** + * 纪检初核项目实体类 + * + * @author ruoyi + */ +@Data +@TableName("ccdi_project") +public class CcdiProject { + /** 项目ID */ + @TableId(type = IdType.AUTO) + private Long projectId; + + /** 项目名称 */ + private String projectName; + + /** 项目描述 */ + private String projectDesc; + + /** 配置方式:default-全局默认,custom-自定义 */ + private String configType; + + /** 项目状态:0-进行中,1-已完成,2-已归档 */ + private String projectStatus; + + /** 目标人数 */ + private Integer targetCount; + + /** 高风险人数 */ + private Integer highRiskCount; + + /** 中风险人数 */ + private Integer mediumRiskCount; + + /** 低风险人数 */ + private Integer lowRiskCount; + + /** 创建者 */ + private String createBy; + + /** 创建时间 */ + private Date createTime; + + /** 更新者 */ + private String updateBy; + + /** 更新时间 */ + private Date updateTime; + + /** 备注 */ + private String remark; +} +``` + +**Step 2: 验证编译** + +```bash +cd ruoyi-info-collection && mvn clean compile +``` + +预期输出:BUILD SUCCESS + +**Step 3: 提交代码** + +```bash +git add ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/CcdiProject.java +git commit -m "feat: 添加项目实体类" +``` + +--- + +## Task 3: 创建 DTO - CcdiProjectSaveDTO + +**文件:** +- Create: `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiProjectSaveDTO.java` + +**Step 1: 创建 DTO 目录(如果不存在)** + +```bash +mkdir -p ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto +``` + +**Step 2: 创建 DTO 类** + +创建文件 `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiProjectSaveDTO.java`: + +```java +package com.ruoyi.info.collection.domain.dto; + +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; +import org.hibernate.validator.constraints.Length; + +/** + * 项目保存DTO + * + * @author ruoyi + */ +@Data +public class CcdiProjectSaveDTO { + /** 项目名称(必填) */ + @NotBlank(message = "项目名称不能为空") + @Length(max = 100, message = "项目名称长度不能超过100个字符") + private String projectName; + + /** 项目描述(可选) */ + @Length(max = 500, message = "项目描述长度不能超过500个字符") + private String projectDesc; + + /** 配置方式(必填):default-全局默认,custom-自定义 */ + @NotBlank(message = "配置方式不能为空") + private String configType; +} +``` + +**Step 3: 验证编译** + +```bash +cd ruoyi-info-collection && mvn clean compile +``` + +预期输出:BUILD SUCCESS + +**Step 4: 提交代码** + +```bash +git add ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiProjectSaveDTO.java +git commit -m "feat: 添加项目保存DTO" +``` + +--- + +## Task 4: 创建 VO - CcdiProjectVO + +**文件:** +- Create: `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/CcdiProjectVO.java` + +**Step 1: 创建 VO 目录(如果不存在)** + +```bash +mkdir -p ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo +``` + +**Step 2: 创建 VO 类** + +创建文件 `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/CcdiProjectVO.java`: + +```java +package com.ruoyi.info.collection.domain.vo; + +import lombok.Data; + +import java.util.Date; + +/** + * 项目VO + * + * @author ruoyi + */ +@Data +public class CcdiProjectVO { + /** 项目ID */ + private Long projectId; + + /** 项目名称 */ + private String projectName; + + /** 项目描述 */ + private String projectDesc; + + /** 配置方式 */ + private String configType; + + /** 项目状态 */ + private String projectStatus; + + /** 目标人数 */ + private Integer targetCount; + + /** 高风险人数 */ + private Integer highRiskCount; + + /** 中风险人数 */ + private Integer mediumRiskCount; + + /** 低风险人数 */ + private Integer lowRiskCount; + + /** 创建时间 */ + private Date createTime; + + /** 创建者 */ + private String createBy; +} +``` + +**Step 3: 验证编译** + +```bash +cd ruoyi-info-collection && mvn clean compile +``` + +预期输出:BUILD SUCCESS + +**Step 4: 提交代码** + +```bash +git add ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/CcdiProjectVO.java +git commit -m "feat: 添加项目VO" +``` + +--- + +## Task 5: 创建查询 DTO - CcdiProjectQueryDTO + +**文件:** +- Create: `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiProjectQueryDTO.java` + +**Step 1: 创建查询 DTO 类** + +创建文件 `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiProjectQueryDTO.java`: + +```java +package com.ruoyi.info.collection.domain.dto; + +import lombok.Data; + +/** + * 项目查询DTO + * + * @author ruoyi + */ +@Data +public class CcdiProjectQueryDTO { + /** 项目名称 */ + private String projectName; + + /** 项目状态 */ + private String projectStatus; +} +``` + +**Step 2: 验证编译** + +```bash +cd ruoyi-info-collection && mvn clean compile +``` + +预期输出:BUILD SUCCESS + +**Step 3: 提交代码** + +```bash +git add ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiProjectQueryDTO.java +git commit -m "feat: 添加项目查询DTO" +``` + +--- + +## Task 6: 创建 Mapper 接口 + +**文件:** +- Create: `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/mapper/CcdiProjectMapper.java` + +**Step 1: 创建 Mapper 接口** + +创建文件 `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/mapper/CcdiProjectMapper.java`: + +```java +package com.ruoyi.info.collection.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.info.collection.domain.CcdiProject; +import com.ruoyi.info.collection.domain.dto.CcdiProjectQueryDTO; +import com.ruoyi.info.collection.domain.vo.CcdiProjectVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 项目Mapper接口 + * + * @author ruoyi + */ +@Mapper +public interface CcdiProjectMapper extends BaseMapper { + /** + * 分页查询项目列表 + * + * @param page 分页对象 + * @param queryDTO 查询条件 + * @return 分页结果 + */ + Page selectProjectPage(Page page, @Param("queryDTO") CcdiProjectQueryDTO queryDTO); +} +``` + +**Step 2: 验证编译** + +```bash +cd ruoyi-info-collection && mvn clean compile +``` + +预期输出:BUILD SUCCESS + +**Step 3: 提交代码** + +```bash +git add ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/mapper/CcdiProjectMapper.java +git commit -m "feat: 添加项目Mapper接口" +``` + +--- + +## Task 7: 创建 Mapper XML 文件 + +**文件:** +- Create: `ruoyi-info-collection/src/main/resources/mapper/info/collection/CcdiProjectMapper.xml` + +**Step 1: 创建 Mapper 目录(如果不存在)** + +```bash +mkdir -p ruoyi-info-collection/src/main/resources/mapper/info/collection +``` + +**Step 2: 创建 XML 文件** + +创建文件 `ruoyi-info-collection/src/main/resources/mapper/info/collection/CcdiProjectMapper.xml`: + +```xml + + + + + + + + + + + + + + + + + + + + + +``` + +**Step 3: 验证编译** + +```bash +cd ruoyi-info-collection && mvn clean compile +``` + +预期输出:BUILD SUCCESS + +**Step 4: 提交代码** + +```bash +git add ruoyi-info-collection/src/main/resources/mapper/info/collection/CcdiProjectMapper.xml +git commit -m "feat: 添加项目Mapper XML配置" +``` + +--- + +## Task 8: 创建 Service 接口 + +**文件:** +- Create: `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiProjectService.java` + +**Step 1: 创建 Service 接口** + +创建文件 `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiProjectService.java`: + +```java +package com.ruoyi.info.collection.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.info.collection.domain.dto.CcdiProjectQueryDTO; +import com.ruoyi.info.collection.domain.dto.CcdiProjectSaveDTO; +import com.ruoyi.info.collection.domain.vo.CcdiProjectVO; + +/** + * 项目Service接口 + * + * @author ruoyi + */ +public interface ICcdiProjectService { + /** + * 创建项目 + * + * @param dto 项目保存DTO + * @return 项目VO + */ + CcdiProjectVO createProject(CcdiProjectSaveDTO dto); + + /** + * 更新项目 + * + * @param dto 项目更新DTO + * @return 项目VO + */ + CcdiProjectVO updateProject(CcdiProjectSaveDTO dto); + + /** + * 删除项目 + * + * @param projectId 项目ID + * @return 是否成功 + */ + boolean deleteProject(Long projectId); + + /** + * 查询项目详情 + * + * @param projectId 项目ID + * @return 项目VO + */ + CcdiProjectVO getProjectById(Long projectId); + + /** + * 分页查询项目列表 + * + * @param page 分页对象 + * @param queryDTO 查询条件 + * @return 分页结果 + */ + Page selectProjectPage(Page page, CcdiProjectQueryDTO queryDTO); +} +``` + +**Step 2: 验证编译** + +```bash +cd ruoyi-info-collection && mvn clean compile +``` + +预期输出:BUILD SUCCESS + +**Step 3: 提交代码** + +```bash +git add ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiProjectService.java +git commit -m "feat: 添加项目Service接口" +``` + +--- + +## Task 9: 创建 Service 实现类 + +**文件:** +- Create: `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiProjectServiceImpl.java` + +**Step 1: 创建 Service 实现目录(如果不存在)** + +```bash +mkdir -p ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl +``` + +**Step 2: 创建 Service 实现类** + +创建文件 `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiProjectServiceImpl.java`: + +```java +package com.ruoyi.info.collection.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.info.collection.domain.CcdiProject; +import com.ruoyi.info.collection.domain.dto.CcdiProjectQueryDTO; +import com.ruoyi.info.collection.domain.dto.CcdiProjectSaveDTO; +import com.ruoyi.info.collection.domain.vo.CcdiProjectVO; +import com.ruoyi.info.collection.mapper.CcdiProjectMapper; +import com.ruoyi.info.collection.service.ICcdiProjectService; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +/** + * 项目Service实现类 + * + * @author ruoyi + */ +@Service +public class CcdiProjectServiceImpl implements ICcdiProjectService { + + @Resource + private CcdiProjectMapper projectMapper; + + @Override + public CcdiProjectVO createProject(CcdiProjectSaveDTO dto) { + CcdiProject project = new CcdiProject(); + BeanUtils.copyProperties(dto, project); + + // 设置默认值 + project.setProjectStatus("0"); // 进行中 + project.setTargetCount(0); + project.setHighRiskCount(0); + project.setMediumRiskCount(0); + project.setLowRiskCount(0); + + projectMapper.insert(project); + + CcdiProjectVO vo = new CcdiProjectVO(); + BeanUtils.copyProperties(project, vo); + return vo; + } + + @Override + public CcdiProjectVO updateProject(CcdiProjectSaveDTO dto) { + // TODO: 实现更新逻辑 + return null; + } + + @Override + public boolean deleteProject(Long projectId) { + return projectMapper.deleteById(projectId) > 0; + } + + @Override + public CcdiProjectVO getProjectById(Long projectId) { + CcdiProject project = projectMapper.selectById(projectId); + if (project == null) { + return null; + } + CcdiProjectVO vo = new CcdiProjectVO(); + BeanUtils.copyProperties(project, vo); + return vo; + } + + @Override + public Page selectProjectPage(Page page, CcdiProjectQueryDTO queryDTO) { + return projectMapper.selectProjectPage(page, queryDTO); + } +} +``` + +**Step 3: 验证编译** + +```bash +cd ruoyi-info-collection && mvn clean compile +``` + +预期输出:BUILD SUCCESS + +**Step 4: 提交代码** + +```bash +git add ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiProjectServiceImpl.java +git commit -m "feat: 添加项目Service实现类" +``` + +--- + +## Task 10: 创建 Controller + +**文件:** +- Create: `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiProjectController.java` + +**Step 1: 创建 Controller 类** + +创建文件 `ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiProjectController.java`: + +```java +package com.ruoyi.info.collection.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.PageDomain; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.page.TableSupport; +import com.ruoyi.info.collection.domain.dto.CcdiProjectQueryDTO; +import com.ruoyi.info.collection.domain.dto.CcdiProjectSaveDTO; +import com.ruoyi.info.collection.domain.vo.CcdiProjectVO; +import com.ruoyi.info.collection.service.ICcdiProjectService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 纪检初核项目管理Controller + * + * @author ruoyi + */ +@RestController +@RequestMapping("/ccdi/project") +@Tag(name = "纪检初核项目管理") +public class CcdiProjectController extends BaseController { + + @Resource + private ICcdiProjectService projectService; + + /** + * 创建项目 + */ + @PostMapping + @Operation(summary = "创建项目") + @PreAuthorize("@ss.hasPermi('ccdi:project:add')") + public AjaxResult createProject(@Validated @RequestBody CcdiProjectSaveDTO dto) { + CcdiProjectVO vo = projectService.createProject(dto); + return AjaxResult.success("项目创建成功", vo); + } + + /** + * 更新项目 + */ + @PutMapping + @Operation(summary = "更新项目") + @PreAuthorize("@ss.hasPermi('ccdi:project:edit')") + public AjaxResult updateProject(@Validated @RequestBody CcdiProjectSaveDTO dto) { + CcdiProjectVO vo = projectService.updateProject(dto); + return AjaxResult.success("项目更新成功", vo); + } + + /** + * 删除项目 + */ + @DeleteMapping("/{projectId}") + @Operation(summary = "删除项目") + @PreAuthorize("@ss.hasPermi('ccdi:project:remove')") + public AjaxResult deleteProject(@PathVariable Long projectId) { + boolean success = projectService.deleteProject(projectId); + return success ? AjaxResult.success("项目删除成功") : AjaxResult.error("项目删除失败"); + } + + /** + * 查询项目详情 + */ + @GetMapping("/{projectId}") + @Operation(summary = "查询项目详情") + @PreAuthorize("@ss.hasPermi('ccdi:project:query')") + public AjaxResult getProject(@PathVariable Long projectId) { + CcdiProjectVO vo = projectService.getProjectById(projectId); + return AjaxResult.success(vo); + } + + /** + * 查询项目列表(分页) + */ + @GetMapping("/list") + @Operation(summary = "查询项目列表") + @PreAuthorize("@ss.hasPermi('ccdi:project:list')") + public TableDataInfo listProject(CcdiProjectQueryDTO queryDTO) { + PageDomain pageDomain = TableSupport.buildPageRequest(); + Page page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize()); + Page result = projectService.selectProjectPage(page, queryDTO); + return getDataTable(result.getRecords(), result.getTotal()); + } +} +``` + +**Step 2: 验证编译** + +```bash +cd ruoyi-info-collection && mvn clean compile +``` + +预期输出:BUILD SUCCESS + +**Step 3: 提交代码** + +```bash +git add ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiProjectController.java +git commit -m "feat: 添加项目Controller" +``` + +--- + +## Task 11: 启动后端并测试接口 + +**Step 1: 启动后端服务** + +```bash +cd ruoyi-admin && mvn spring-boot:run +``` + +预期输出:Spring Boot 启动成功日志,端口 8080 + +**Step 2: 获取测试 Token** + +使用测试接口获取 Token: + +```bash +curl -X POST "http://localhost:8080/login/test?username=admin&password=admin123" +``` + +预期输出:返回包含 token 的 JSON 响应 + +**Step 3: 测试创建项目接口** + +使用 Token 测试创建项目接口: + +```bash +curl -X POST "http://localhost:8080/ccdi/project" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "projectName": "测试项目1", + "projectDesc": "这是测试项目描述", + "configType": "default" + }' +``` + +预期输出:返回成功响应,包含项目 ID 和创建的项目信息 + +**Step 4: 测试查询项目列表接口** + +```bash +curl -X GET "http://localhost:8080/ccdi/project/list?pageNum=1&pageSize=10" \ + -H "Authorization: Bearer " +``` + +预期输出:返回分页数据,包含刚才创建的项目 + +**Step 5: 使用 Swagger 测试** + +访问 Swagger UI 进行接口测试: + +```bash +# 浏览器打开 +http://localhost:8080/swagger-ui/index.html +``` + +预期结果:在 Swagger UI 中可以看到项目管理的所有接口,并进行测试 + +--- + +## Task 12: 提交最终代码 + +**Step 1: 检查所有文件** + +```bash +git status +``` + +预期输出:所有后端文件已提交 + +**Step 2: 推送到远程仓库** + +```bash +git push origin dev +``` + +预期输出:推送成功 + +--- + +## 完成检查清单 + +- [ ] 数据库表 `ccdi_project` 创建成功 +- [ ] 字典数据 `ccdi_project_status` 和 `ccdi_config_type` 插入成功 +- [ ] 菜单权限配置成功 +- [ ] 实体类 `CcdiProject` 创建并编译通过 +- [ ] DTO `CcdiProjectSaveDTO` 创建并编译通过 +- [ ] VO `CcdiProjectVO` 创建并编译通过 +- [ ] Mapper 接口和 XML 创建并编译通过 +- [ ] Service 接口和实现类创建并编译通过 +- [ ] Controller 创建并编译通过 +- [ ] 后端服务启动成功 +- [ ] 创建项目接口测试通过 +- [ ] 查询项目列表接口测试通过 +- [ ] Swagger 文档显示正确 +- [ ] 所有代码已提交到 git + +--- + +**后端实施计划完成!** diff --git a/doc/plans/2026-02-26-create-project-frontend-implementation.md b/doc/plans/2026-02-26-create-project-frontend-implementation.md new file mode 100644 index 0000000..417919e --- /dev/null +++ b/doc/plans/2026-02-26-create-project-frontend-implementation.md @@ -0,0 +1,881 @@ +# 创建项目功能 - 前端实施计划 + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**目标:** 实现创建项目功能的前端界面,包括弹窗表单、项目列表展示、API调用 + +**架构:** 基于 Vue 2.6.12 + Element UI 2.15.14,采用组件化开发 + +**技术栈:** Vue.js 2.6.12, Element UI 2.15.14, Axios 0.28.1 + +--- + +## 前置条件 + +- 后端接口已部署并测试通过 +- 前端项目依赖已安装 +- 已有测试账号(admin/admin123) +- 后端服务运行在 http://localhost:8080 + +--- + +## Task 1: 更新 API 接口文件 + +**文件:** +- Modify: `ruoyi-ui/src/api/ccdiProject.js` + +**Step 1: 备份原文件** + +```bash +cp ruoyi-ui/src/api/ccdiProject.js ruoyi-ui/src/api/ccdiProject.js.bak +``` + +**Step 2: 修改 API 文件** + +将 `ruoyi-ui/src/api/ccdiProject.js` 修改为以下内容: + +```javascript +import request from '@/utils/request' + +// 创建初核项目 +export function createProject(data) { + return request({ + url: '/ccdi/project', + method: 'post', + data: data + }) +} + +// 查询初核项目列表(分页) +export function listProject(query) { + return request({ + url: '/ccdi/project/list', + method: 'get', + params: query + }) +} + +// 查询初核项目详细 +export function getProject(projectId) { + return request({ + url: '/ccdi/project/' + projectId, + method: 'get' + }) +} + +// 修改初核项目 +export function updateProject(data) { + return request({ + url: '/ccdi/project', + method: 'put', + data: data + }) +} + +// 删除初核项目 +export function delProject(projectId) { + return request({ + url: '/ccdi/project/' + projectId, + method: 'delete' + }) +} + +// Mock数据:获取项目列表(保留用于测试) +export function getMockProjectList() { + return Promise.resolve({ + code: 200, + total: 3, + rows: [ + { + projectId: 1, + projectName: '2024年Q1初核', + projectDesc: '2024年第一季度纪检初核排查工作', + createTime: '2024-01-01', + projectStatus: '0', + configType: 'default', + targetCount: 500, + highRiskCount: 5, + mediumRiskCount: 10, + lowRiskCount: 0 + }, + { + projectId: 2, + projectName: '2023年Q4初核', + projectDesc: '2023年第四季度纪检初核排查工作', + createTime: '2023-10-01', + projectStatus: '1', + configType: 'custom', + targetCount: 480, + highRiskCount: 8, + mediumRiskCount: 15, + lowRiskCount: 0 + }, + { + projectId: 3, + projectName: '2023年Q3初核', + projectDesc: '2023年第三季度纪检初核排查工作', + createTime: '2023-07-01', + projectStatus: '2', + configType: 'default', + targetCount: 450, + highRiskCount: 0, + mediumRiskCount: 18, + lowRiskCount: 5 + } + ] + }) +} +``` + +**Step 3: 验证语法** + +```bash +cd ruoyi-ui && npm run lint -- --fix src/api/ccdiProject.js +``` + +预期输出:无 ESLint 错误 + +**Step 4: 提交代码** + +```bash +git add ruoyi-ui/src/api/ccdiProject.js +git commit -m "feat: 更新项目API接口,添加创建项目接口" +``` + +--- + +## Task 2: 修改 AddProjectDialog 组件 + +**文件:** +- Modify: `ruoyi-ui/src/views/ccdiProject/components/AddProjectDialog.vue` + +**Step 1: 备份原文件** + +```bash +cp ruoyi-ui/src/views/ccdiProject/components/AddProjectDialog.vue ruoyi-ui/src/views/ccdiProject/components/AddProjectDialog.vue.bak +``` + +**Step 2: 重写组件** + +将 `ruoyi-ui/src/views/ccdiProject/components/AddProjectDialog.vue` 重写为以下内容: + +```vue + + + + + +``` + +**Step 3: 验证语法** + +```bash +cd ruoyi-ui && npm run lint -- --fix src/views/ccdiProject/components/AddProjectDialog.vue +``` + +预期输出:无 ESLint 错误 + +**Step 4: 提交代码** + +```bash +git add ruoyi-ui/src/views/ccdiProject/components/AddProjectDialog.vue +git commit -m "feat: 简化项目创建弹窗,只保留3个核心字段" +``` + +--- + +## Task 3: 修改 ProjectTable 组件 + +**文件:** +- Modify: `ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue` + +**Step 1: 备份原文件** + +```bash +cp ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue.bak +``` + +**Step 2: 重写组件** + +将 `ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue` 重写为以下内容: + +```vue + + + + + +``` + +**Step 3: 验证语法** + +```bash +cd ruoyi-ui && npm run lint -- --fix src/views/ccdiProject/components/ProjectTable.vue +``` + +预期输出:无 ESLint 错误 + +**Step 4: 提交代码** + +```bash +git add ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue +git commit -m "feat: 优化项目列表表格,添加预警人数悬停提示" +``` + +--- + +## Task 4: 修改父组件 index.vue + +**文件:** +- Modify: `ruoyi-ui/src/views/ccdiProject/index.vue` + +**Step 1: 备份原文件** + +```bash +cp ruoyi-ui/src/views/ccdiProject/index.vue ruoyi-ui/src/views/ccdiProject/index.vue.bak +``` + +**Step 2: 修改父组件** + +将 `ruoyi-ui/src/views/ccdiProject/index.vue` 的 `getList` 和 `handleSubmitProject` 方法修改为: + +```javascript +/** 查询项目列表 */ +getList() { + this.loading = true + // 使用真实API + listProject(this.queryParams).then(response => { + this.projectList = response.rows + this.total = response.total + this.loading = false + }).catch(() => { + this.loading = false + }) +}, + +/** 提交项目表单 */ +handleSubmitProject(data) { + // 不需要再次调用API,因为AddProjectDialog已经处理了 + this.addDialogVisible = false + this.getList() // 刷新列表 +} +``` + +**Step 3: 验证语法** + +```bash +cd ruoyi-ui && npm run lint -- --fix src/views/ccdiProject/index.vue +``` + +预期输出:无 ESLint 错误 + +**Step 4: 提交代码** + +```bash +git add ruoyi-ui/src/views/ccdiProject/index.vue +git commit -m "feat: 修改父组件,切换为真实API调用" +``` + +--- + +## Task 5: 启动前端并测试 + +**Step 1: 启动前端开发服务器** + +```bash +cd ruoyi-ui && npm run dev +``` + +预期输出:前端服务启动成功,访问地址 http://localhost:80 + +**Step 2: 测试登录** + +浏览器访问 http://localhost:80,使用测试账号登录: +- 用户名:admin +- 密码:admin123 + +预期结果:登录成功,进入首页 + +**Step 3: 测试项目列表** + +导航到"纪检初核管理 > 项目管理"菜单: + +预期结果: +- 项目列表正常显示 +- 项目名称和描述上下排列 +- 项目状态标签显示正确 +- 预警人数悬停提示显示风险详情 + +**Step 4: 测试创建项目** + +点击"新建项目"按钮: + +预期结果: +- 弹窗正常打开 +- 显示3个字段(项目名称、项目描述、配置方式) +- 配置方式默认选中"全局默认模型参数配置" + +填写表单: +- 项目名称:测试项目001 +- 项目描述:这是测试项目的描述 +- 配置方式:选择"自定义项目规则参数配置" + +点击"创建项目"按钮: + +预期结果: +- 按钮显示 loading 状态 +- 创建成功,提示"项目创建成功" +- 弹窗关闭 +- 项目列表自动刷新,显示新创建的项目 + +**Step 5: 测试预警人数悬停** + +在项目列表中,将鼠标悬停在预警人数上: + +预期结果: +- 显示风险人数统计提示框 +- 显示高风险、中风险、低风险人数 +- 预警人数颜色根据风险级别变化 + +**Step 6: 测试表单验证** + +不填写项目名称,直接点击"创建项目": + +预期结果: +- 提示"请输入项目名称" +- 表单不提交 + +**Step 7: 测试取消按钮** + +点击"新建项目",然后点击"取消": + +预期结果: +- 弹窗关闭 +- 表单数据清空 + +--- + +## Task 6: 跨浏览器测试 + +**Step 1: Chrome 测试** + +在 Chrome 浏览器中重复 Task 5 的所有测试: + +预期结果:所有功能正常 + +**Step 2: Edge 测试** + +在 Edge 浏览器中重复 Task 5 的所有测试: + +预期结果:所有功能正常 + +**Step 3: Firefox 测试(可选)** + +在 Firefox 浏览器中重复 Task 5 的所有测试: + +预期结果:所有功能正常 + +--- + +## Task 7: 响应式测试 + +**Step 1: 测试不同分辨率** + +调整浏览器窗口大小,测试以下分辨率: + +- 1920x1080(桌面) +- 1366x768(笔记本) +- 768x1024(平板) + +预期结果: +- 表格自适应宽度 +- 弹窗居中显示 +- 所有功能正常使用 + +**Step 2: 测试表格横向滚动** + +缩小浏览器窗口,使表格宽度小于内容宽度: + +预期结果: +- 表格出现横向滚动条 +- 操作列固定在右侧 +- 可以横向滚动查看所有列 + +--- + +## Task 8: 提交最终代码 + +**Step 1: 检查所有文件** + +```bash +git status +``` + +预期输出:所有前端文件已提交 + +**Step 2: 推送到远程仓库** + +```bash +git push origin dev +``` + +预期输出:推送成功 + +--- + +## 完成检查清单 + +- [ ] API 接口文件更新完成 +- [ ] AddProjectDialog 组件简化完成(3个字段) +- [ ] ProjectTable 组件优化完成(上下排列、预警悬停) +- [ ] 父组件切换为真实API +- [ ] 前端服务启动成功 +- [ ] 登录功能正常 +- [ ] 项目列表显示正常 +- [ ] 项目名称和描述上下排列正确 +- [ ] 项目状态标签显示正确 +- [ ] 预警人数悬停提示显示正常 +- [ ] 预警人数颜色根据风险级别变化 +- [ ] 创建项目弹窗打开正常 +- [ ] 配置方式默认值正确 +- [ ] 创建项目功能正常 +- [ ] 创建成功后列表刷新 +- [ ] 表单验证正常 +- [ ] 取消按钮功能正常 +- [ ] 跨浏览器测试通过 +- [ ] 响应式测试通过 +- [ ] 所有代码已提交到 git + +--- + +**前端实施计划完成!** diff --git a/doc/创建项目功能/ScreenShot_2026-02-26_162233_965.png b/doc/创建项目功能/ScreenShot_2026-02-26_162233_965.png new file mode 100644 index 0000000..594cf69 Binary files /dev/null and b/doc/创建项目功能/ScreenShot_2026-02-26_162233_965.png differ