Files
ccdi/doc/requirements/plans/2026-02-06-ccdi_purchase_transaction.md
wkc 1cd87d2695 refactor: 重命名 ruoyi-ccdi 模块为 ruoyi-info-collection
- Maven 模块从 ruoyi-ccdi 重命名为 ruoyi-info-collection
- Java 包名从 com.ruoyi.ccdi 改为 com.ruoyi.info.collection
- MyBatis XML 命名空间同步更新
- 保留数据库表名、API URL、权限标识中的 ccdi 前缀
- 更新项目文档中的模块引用
2026-02-24 17:12:11 +08:00

34 KiB
Raw Blame History

员工采购交易信息管理功能实施计划

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

目标: 构建完整的员工采购交易信息管理模块支持CRUD操作、分页查询、异步导入导出、批量删除等功能

架构: 基于若依框架前后端分离架构后端使用MyBatis Plus + EasyExcel + Redis实现异步导入前端使用Vue 2 + Element UI

技术栈:

  • 后端: Spring Boot 3.5.8, MyBatis Plus 3.5.10, EasyExcel, Redis
  • 前端: Vue 2.6.12, Element UI 2.15.14, Axios
  • 数据库: MySQL 8.2.0

前置条件

参考文档

  • 员工招聘信息模块: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/**/CcdiStaffRecruitment*
  • 员工异步导入实现: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/impl/CcdiEmployeeImportServiceImpl.java
  • 数据库表定义: doc/docs/ccdi_purchase_transaction.csv

数据库表结构

CREATE TABLE `ccdi_purchase_transaction` (
  `purchase_id` VARCHAR(32) NOT NULL COMMENT '采购事项ID',
  `purchase_category` VARCHAR(50) NOT NULL COMMENT '采购类别',
  `project_name` VARCHAR(200) DEFAULT NULL COMMENT '项目名称',
  `subject_name` VARCHAR(200) NOT NULL COMMENT '标的物名称',
  `subject_desc` TEXT COMMENT '标的物描述',
  `purchase_qty` DECIMAL(12,4) NOT NULL DEFAULT 1 COMMENT '采购数量',
  `budget_amount` DECIMAL(18,2) NOT NULL COMMENT '预算金额',
  `bid_amount` DECIMAL(18,2) DEFAULT NULL COMMENT '中标金额',
  `actual_amount` DECIMAL(18,2) DEFAULT NULL COMMENT '实际采购金额',
  `contract_amount` DECIMAL(18,2) DEFAULT NULL COMMENT '合同金额',
  `settlement_amount` DECIMAL(18,2) DEFAULT NULL COMMENT '结算金额',
  `purchase_method` VARCHAR(50) NOT NULL COMMENT '采购方式',
  `supplier_name` VARCHAR(200) DEFAULT NULL COMMENT '中标供应商名称',
  `contact_person` VARCHAR(50) DEFAULT NULL COMMENT '供应商联系人',
  `contact_phone` VARCHAR(20) DEFAULT NULL COMMENT '供应商联系电话',
  `supplier_uscc` VARCHAR(18) DEFAULT NULL COMMENT '供应商统一信用代码',
  `supplier_bank_account` VARCHAR(50) DEFAULT NULL COMMENT '供应商银行账户',
  `apply_date` DATE NOT NULL COMMENT '采购申请日期',
  `plan_approve_date` DATE DEFAULT NULL COMMENT '采购计划批准日期',
  `announce_date` DATE DEFAULT NULL COMMENT '采购公告发布日期',
  `bid_open_date` DATE DEFAULT NULL COMMENT '开标日期',
  `contract_sign_date` DATE DEFAULT NULL COMMENT '合同签订日期',
  `expected_delivery_date` DATE DEFAULT NULL COMMENT '预计交货日期',
  `actual_delivery_date` DATE DEFAULT NULL COMMENT '实际交货日期',
  `acceptance_date` DATE DEFAULT NULL COMMENT '验收日期',
  `settlement_date` DATE DEFAULT NULL COMMENT '结算日期',
  `applicant_id` VARCHAR(7) NOT NULL COMMENT '申请人工号',
  `applicant_name` VARCHAR(50) NOT NULL COMMENT '申请人姓名',
  `apply_department` VARCHAR(100) NOT NULL COMMENT '申请部门',
  `purchase_leader_id` VARCHAR(7) DEFAULT NULL COMMENT '采购负责人工号',
  `purchase_leader_name` VARCHAR(50) DEFAULT NULL COMMENT '采购负责人姓名',
  `purchase_department` VARCHAR(100) DEFAULT NULL COMMENT '采购部门',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `created_by` VARCHAR(50) NOT NULL COMMENT '创建人',
  `updated_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人',
  PRIMARY KEY (`purchase_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工采购交易信息表';

Task 1: 创建数据库表

Files:

  • Modify: 执行SQL创建表

Step 1: 连接数据库并创建表

使用MCP连接MySQL数据库:

# 使用 mcp__mysql__connect_db 连接到数据库
# 然后执行上面的CREATE TABLE语句

Step 2: 验证表创建

SHOW CREATE TABLE ccdi_purchase_transaction;

Expected: 表结构正确创建

Step 3: Commit

git add sql/
git commit -m "feat: 添加员工采购交易信息表"

Task 2: 创建实体类

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/CcdiPurchaseTransaction.java

Step 1: 创建实体类

package com.ruoyi.ccdi.domain;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;

/**
 * 员工采购交易信息对象 ccdi_purchase_transaction
 *
 * @author ruoyi
 * @date 2026-02-06
 */
@Data
public class CcdiPurchaseTransaction implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /** 采购事项ID */
    @TableId(type = IdType.INPUT)
    private String purchaseId;

    /** 采购类别 */
    private String purchaseCategory;

    /** 项目名称 */
    private String projectName;

    /** 标的物名称 */
    private String subjectName;

    /** 标的物描述 */
    private String subjectDesc;

    /** 采购数量 */
    private BigDecimal purchaseQty;

    /** 预算金额 */
    private BigDecimal budgetAmount;

    /** 中标金额 */
    private BigDecimal bidAmount;

    /** 实际采购金额 */
    private BigDecimal actualAmount;

    /** 合同金额 */
    private BigDecimal contractAmount;

    /** 结算金额 */
    private BigDecimal settlementAmount;

    /** 采购方式 */
    private String purchaseMethod;

    /** 中标供应商名称 */
    private String supplierName;

    /** 供应商联系人 */
    private String contactPerson;

    /** 供应商联系电话 */
    private String contactPhone;

    /** 供应商统一信用代码 */
    private String supplierUscc;

    /** 供应商银行账户 */
    private String supplierBankAccount;

    /** 采购申请日期 */
    private LocalDate applyDate;

    /** 采购计划批准日期 */
    private LocalDate planApproveDate;

    /** 采购公告发布日期 */
    private LocalDate announceDate;

    /** 开标日期 */
    private LocalDate bidOpenDate;

    /** 合同签订日期 */
    private LocalDate contractSignDate;

    /** 预计交货日期 */
    private LocalDate expectedDeliveryDate;

    /** 实际交货日期 */
    private LocalDate actualDeliveryDate;

    /** 验收日期 */
    private LocalDate acceptanceDate;

    /** 结算日期 */
    private LocalDate settlementDate;

    /** 申请人工号 */
    private String applicantId;

    /** 申请人姓名 */
    private String applicantName;

    /** 申请部门 */
    private String applyDepartment;

    /** 采购负责人工号 */
    private String purchaseLeaderId;

    /** 采购负责人姓名 */
    private String purchaseLeaderName;

    /** 采购部门 */
    private String purchaseDepartment;

    /** 创建时间 */
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    /** 更新时间 */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

    /** 创建人 */
    @TableField(fill = FieldFill.INSERT)
    private String createdBy;

    /** 更新人 */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updatedBy;
}

Step 2: 验证编译

cd ruoyi-info-collection
mvn compile -pl . -am

Expected: 编译成功,无错误

Step 3: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/CcdiPurchaseTransaction.java
git commit -m "feat: 添加采购交易信息实体类"

Task 3: 创建查询DTO

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionQueryDTO.java

Step 1: 创建查询DTO

package com.ruoyi.ccdi.domain.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;

/**
 * 采购交易信息查询DTO
 *
 * @author ruoyi
 * @date 2026-02-06
 */
@Data
@Schema(description = "采购交易信息查询条件")
public class CcdiPurchaseTransactionQueryDTO implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /** 项目名称 */
    @Schema(description = "项目名称")
    private String projectName;

    /** 标的物名称 */
    @Schema(description = "标的物名称")
    private String subjectName;

    /** 申请人姓名 */
    @Schema(description = "申请人姓名")
    private String applicantName;

    /** 申请人工号 */
    @Schema(description = "申请人工号")
    private String applicantId;

    /** 申请日期-开始 */
    @Schema(description = "申请日期-开始")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate applyDateStart;

    /** 申请日期-结束 */
    @Schema(description = "申请日期-结束")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate applyDateEnd;
}

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionQueryDTO.java
git commit -m "feat: 添加采购交易查询DTO"

Task 4: 创建新增DTO

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionAddDTO.java

Step 1: 创建新增DTO包含验证注解

package com.ruoyi.ccdi.domain.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import lombok.Data;

import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;

/**
 * 采购交易信息新增DTO
 *
 * @author ruoyi
 * @date 2026-02-06
 */
@Data
@Schema(description = "采购交易信息新增")
public class CcdiPurchaseTransactionAddDTO implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    @Schema(description = "采购事项ID")
    @NotBlank(message = "采购事项ID不能为空")
    @Size(max = 32, message = "采购事项ID长度不能超过32个字符")
    private String purchaseId;

    @Schema(description = "采购类别")
    @NotBlank(message = "采购类别不能为空")
    @Size(max = 50, message = "采购类别长度不能超过50个字符")
    private String purchaseCategory;

    @Schema(description = "项目名称")
    @Size(max = 200, message = "项目名称长度不能超过200个字符")
    private String projectName;

    @Schema(description = "标的物名称")
    @NotBlank(message = "标的物名称不能为空")
    @Size(max = 200, message = "标的物名称长度不能超过200个字符")
    private String subjectName;

    @Schema(description = "标的物描述")
    private String subjectDesc;

    @Schema(description = "采购数量")
    @NotNull(message = "采购数量不能为空")
    @DecimalMin(value = "0.0001", message = "采购数量必须大于0")
    private BigDecimal purchaseQty;

    @Schema(description = "预算金额")
    @NotNull(message = "预算金额不能为空")
    @DecimalMin(value = "0.01", message = "预算金额必须大于0")
    private BigDecimal budgetAmount;

    @Schema(description = "中标金额")
    @DecimalMin(value = "0", message = "中标金额不能为负数")
    private BigDecimal bidAmount;

    @Schema(description = "实际采购金额")
    @DecimalMin(value = "0", message = "实际采购金额不能为负数")
    private BigDecimal actualAmount;

    @Schema(description = "合同金额")
    @DecimalMin(value = "0", message = "合同金额不能为负数")
    private BigDecimal contractAmount;

    @Schema(description = "结算金额")
    @DecimalMin(value = "0", message = "结算金额不能为负数")
    private BigDecimal settlementAmount;

    @Schema(description = "采购方式")
    @NotBlank(message = "采购方式不能为空")
    @Size(max = 50, message = "采购方式长度不能超过50个字符")
    private String purchaseMethod;

    @Schema(description = "中标供应商名称")
    @Size(max = 200, message = "中标供应商名称长度不能超过200个字符")
    private String supplierName;

    @Schema(description = "供应商联系人")
    @Size(max = 50, message = "供应商联系人长度不能超过50个字符")
    private String contactPerson;

    @Schema(description = "供应商联系电话")
    @Size(max = 20, message = "供应商联系电话长度不能超过20个字符")
    private String contactPhone;

    @Schema(description = "供应商统一信用代码")
    @Size(max = 18, message = "供应商统一信用代码长度不能超过18个字符")
    private String supplierUscc;

    @Schema(description = "供应商银行账户")
    @Size(max = 50, message = "供应商银行账户长度不能超过50个字符")
    private String supplierBankAccount;

    @Schema(description = "采购申请日期")
    @NotNull(message = "采购申请日期不能为空")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate applyDate;

    @Schema(description = "采购计划批准日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate planApproveDate;

    @Schema(description = "采购公告发布日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate announceDate;

    @Schema(description = "开标日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate bidOpenDate;

    @Schema(description = "合同签订日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate contractSignDate;

    @Schema(description = "预计交货日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate expectedDeliveryDate;

    @Schema(description = "实际交货日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate actualDeliveryDate;

    @Schema(description = "验收日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate acceptanceDate;

    @Schema(description = "结算日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate settlementDate;

    @Schema(description = "申请人工号")
    @NotBlank(message = "申请人工号不能为空")
    @Pattern(regexp = "^\\d{7}$", message = "申请人工号必须为7位数字")
    private String applicantId;

    @Schema(description = "申请人姓名")
    @NotBlank(message = "申请人姓名不能为空")
    @Size(max = 50, message = "申请人姓名长度不能超过50个字符")
    private String applicantName;

    @Schema(description = "申请部门")
    @NotBlank(message = "申请部门不能为空")
    @Size(max = 100, message = "申请部门长度不能超过100个字符")
    private String applyDepartment;

    @Schema(description = "采购负责人工号")
    @Pattern(regexp = "^\\d{7}$", message = "采购负责人工号必须为7位数字")
    private String purchaseLeaderId;

    @Schema(description = "采购负责人姓名")
    @Size(max = 50, message = "采购负责人姓名长度不能超过50个字符")
    private String purchaseLeaderName;

    @Schema(description = "采购部门")
    @Size(max = 100, message = "采购部门长度不能超过100个字符")
    private String purchaseDepartment;
}

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionAddDTO.java
git commit -m "feat: 添加采购交易新增DTO"

Task 5: 创建编辑DTO

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionEditDTO.java

Step 1: 创建编辑DTO

复制AddDTO的内容,修改类名和类注释,所有验证注解保持不变。

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionEditDTO.java
git commit -m "feat: 添加采购交易编辑DTO"

Task 6: 创建VO类

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/vo/CcdiPurchaseTransactionVO.java

Step 1: 创建VO类

package com.ruoyi.ccdi.domain.vo;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;

/**
 * 采购交易信息VO
 *
 * @author ruoyi
 * @date 2026-02-06
 */
@Data
@Schema(description = "采购交易信息")
public class CcdiPurchaseTransactionVO implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    @Schema(description = "采购事项ID")
    private String purchaseId;

    @Schema(description = "采购类别")
    private String purchaseCategory;

    @Schema(description = "项目名称")
    private String projectName;

    @Schema(description = "标的物名称")
    private String subjectName;

    @Schema(description = "标的物描述")
    private String subjectDesc;

    @Schema(description = "采购数量")
    private BigDecimal purchaseQty;

    @Schema(description = "预算金额")
    private BigDecimal budgetAmount;

    @Schema(description = "中标金额")
    private BigDecimal bidAmount;

    @Schema(description = "实际采购金额")
    private BigDecimal actualAmount;

    @Schema(description = "合同金额")
    private BigDecimal contractAmount;

    @Schema(description = "结算金额")
    private BigDecimal settlementAmount;

    @Schema(description = "采购方式")
    private String purchaseMethod;

    @Schema(description = "中标供应商名称")
    private String supplierName;

    @Schema(description = "供应商联系人")
    private String contactPerson;

    @Schema(description = "供应商联系电话")
    private String contactPhone;

    @Schema(description = "供应商统一信用代码")
    private String supplierUscc;

    @Schema(description = "供应商银行账户")
    private String supplierBankAccount;

    @Schema(description = "采购申请日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate applyDate;

    @Schema(description = "采购计划批准日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate planApproveDate;

    @Schema(description = "采购公告发布日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate announceDate;

    @Schema(description = "开标日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate bidOpenDate;

    @Schema(description = "合同签订日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate contractSignDate;

    @Schema(description = "预计交货日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate expectedDeliveryDate;

    @Schema(description = "实际交货日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate actualDeliveryDate;

    @Schema(description = "验收日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate acceptanceDate;

    @Schema(description = "结算日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate settlementDate;

    @Schema(description = "申请人工号")
    private String applicantId;

    @Schema(description = "申请人姓名")
    private String applicantName;

    @Schema(description = "申请部门")
    private String applyDepartment;

    @Schema(description = "采购负责人工号")
    private String purchaseLeaderId;

    @Schema(description = "采购负责人姓名")
    private String purchaseLeaderName;

    @Schema(description = "采购部门")
    private String purchaseDepartment;

    @Schema(description = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    @Schema(description = "更新时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;

    @Schema(description = "创建人")
    private String createdBy;

    @Schema(description = "更新人")
    private String updatedBy;
}

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/vo/CcdiPurchaseTransactionVO.java
git commit -m "feat: 添加采购交易VO类"

Task 7: 创建Excel导入导出类

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiPurchaseTransactionExcel.java

Step 1: 创建Excel类

参考 CcdiStaffRecruitmentExcel.java为36个字段添加 @ExcelProperty@ColumnWidth@Required 注解。必填字段purchaseId, purchaseCategory, subjectName, purchaseQty, budgetAmount, purchaseMethod, applyDate, applicantId, applicantName, applyDepartment。

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiPurchaseTransactionExcel.java
git commit -m "feat: 添加采购交易Excel类"

Task 8: 创建Mapper接口

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/mapper/CcdiPurchaseTransactionMapper.java

Step 1: 创建Mapper接口

package com.ruoyi.ccdi.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.domain.CcdiPurchaseTransaction;
import com.ruoyi.ccdi.domain.dto.CcdiPurchaseTransactionQueryDTO;
import com.ruoyi.ccdi.domain.vo.CcdiPurchaseTransactionVO;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 采购交易信息 数据层
 *
 * @author ruoyi
 * @date 2026-02-06
 */
public interface CcdiPurchaseTransactionMapper extends BaseMapper<CcdiPurchaseTransaction> {

    /**
     * 分页查询采购交易列表
     */
    Page<CcdiPurchaseTransactionVO> selectTransactionPage(@Param("page") Page<CcdiPurchaseTransactionVO> page,
                                                          @Param("query") CcdiPurchaseTransactionQueryDTO queryDTO);

    /**
     * 查询采购交易详情
     */
    CcdiPurchaseTransactionVO selectTransactionById(@Param("purchaseId") String purchaseId);

    /**
     * 批量插入
     */
    int insertBatch(@Param("list") List<CcdiPurchaseTransaction> list);

    /**
     * 批量更新(先删除再插入)
     */
    int insertOrUpdateBatch(@Param("list") List<CcdiPurchaseTransaction> list);
}

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/mapper/CcdiPurchaseTransactionMapper.java
git commit -m "feat: 添加采购交易Mapper接口"

Task 9: 创建Mapper XML文件

Files:

  • Create: ruoyi-info-collection/src/main/resources/mapper/ccdi/CcdiPurchaseTransactionMapper.xml

Step 1: 创建XML映射文件

参考 CcdiStaffRecruitmentMapper.xml编写SQL映射:

  • selectTransactionPage: 分页查询,支持项目名称、标的物名称、申请人、日期范围查询
  • selectTransactionById: 根据ID查询详情
  • insertBatch: 批量插入
  • insertOrUpdateBatch: 批量更新(先删除再插入)

Step 2: Commit

git add ruoyi-info-collection/src/main/resources/mapper/ccdi/CcdiPurchaseTransactionMapper.xml
git commit -m "feat: 添加采购交易Mapper XML"

Task 10: 创建Service接口

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/ICcdiPurchaseTransactionService.java

Step 1: 创建Service接口

参考 ICcdiStaffRecruitmentService.java,定义以下方法:

  • selectTransactionList
  • selectTransactionPage
  • selectTransactionListForExport
  • selectTransactionById
  • insertTransaction
  • updateTransaction
  • deleteTransactionByIds
  • importTransaction (返回taskId)

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/ICcdiPurchaseTransactionService.java
git commit -m "feat: 添加采购交易Service接口"

Task 11: 创建异步导入Service接口

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/ICcdiPurchaseTransactionImportService.java

Step 1: 创建异步导入Service接口

参考 ICcdiEmployeeImportService.java,定义方法:

  • importTransactionAsync
  • getImportStatus
  • getImportFailures

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/ICcdiPurchaseTransactionImportService.java
git commit -m "feat: 添加采购交易异步导入Service接口"

Task 12: 创建Service实现类

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionServiceImpl.java

Step 1: 创建Service实现

参考 CcdiStaffRecruitmentServiceImpl.java实现所有CRUD方法和importTransaction方法(初始化Redis状态,调用异步服务)。

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionServiceImpl.java
git commit -m "feat: 添加采购交易Service实现"

Task 13: 创建异步导入Service实现类

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionImportServiceImpl.java

Step 1: 创建异步导入实现

参考 CcdiEmployeeImportServiceImpl.java,实现:

  • @Async + @Transactional 注解
  • importTransactionAsync方法(接收userName参数)
  • 数据分类(新记录/更新记录/失败记录)
  • 批量插入和更新
  • Redis状态管理
  • 数据验证逻辑

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionImportServiceImpl.java
git commit -m "feat: 添加采购交易异步导入Service实现"

Task 14: 创建Controller控制器

Files:

  • Create: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/controller/CcdiPurchaseTransactionController.java

Step 1: 创建Controller

参考 CcdiStaffRecruitmentController.javaCcdiEmployeeController.java,实现接口:

  • GET /list - 分页查询
  • GET /{purchaseId} - 查询详情
  • POST / - 新增
  • PUT / - 修改
  • DELETE /{purchaseIds} - 删除
  • POST /export - 导出
  • POST /importTemplate - 下载模板
  • POST /importData - 异步导入
  • GET /importStatus/{taskId} - 查询导入状态
  • GET /importFailures/{taskId} - 查询失败记录

添加完整的Swagger注解。

Step 2: Commit

git add ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/controller/CcdiPurchaseTransactionController.java
git commit -m "feat: 添加采购交易Controller"

Task 15: 创建前端API文件

Files:

  • Create: ruoyi-ui/src/api/ccdiPurchaseTransaction.js

Step 1: 创建API定义

import request from '@/utils/request'

// 查询采购交易列表
export function listTransaction(query) {
  return request({
    url: '/ccdi/purchaseTransaction/list',
    method: 'get',
    params: query
  })
}

// 查询采购交易详情
export function getTransaction(purchaseId) {
  return request({
    url: '/ccdi/purchaseTransaction/' + purchaseId,
    method: 'get'
  })
}

// 新增采购交易
export function addTransaction(data) {
  return request({
    url: '/ccdi/purchaseTransaction',
    method: 'post',
    data: data
  })
}

// 修改采购交易
export function updateTransaction(data) {
  return request({
    url: '/ccdi/purchaseTransaction',
    method: 'put',
    data: data
  })
}

// 删除采购交易
export function delTransaction(purchaseIds) {
  return request({
    url: '/ccdi/purchaseTransaction/' + purchaseIds,
    method: 'delete'
  })
}

// 导出采购交易
export function exportTransaction(query) {
  return request({
    url: '/ccdi/purchaseTransaction/export',
    method: 'post',
    params: query
  })
}

// 下载导入模板
export function importTemplate() {
  return request({
    url: '/ccdi/purchaseTransaction/importTemplate',
    method: 'post'
  })
}

// 导入采购交易
export function importData(file, updateSupport) {
  const formData = new FormData()
  formData.append('file', file)
  formData.append('updateSupport', updateSupport)
  return request({
    url: '/ccdi/purchaseTransaction/importData',
    method: 'post',
    data: formData
  })
}

// 查询导入状态
export function getImportStatus(taskId) {
  return request({
    url: '/ccdi/purchaseTransaction/importStatus/' + taskId,
    method: 'get'
  })
}

// 查询导入失败记录
export function getImportFailures(taskId, pageNum, pageSize) {
  return request({
    url: '/ccdi/purchaseTransaction/importFailures/' + taskId,
    method: 'get',
    params: { pageNum, pageSize }
  })
}

Step 2: Commit

git add ruoyi-ui/src/api/ccdiPurchaseTransaction.js
git commit -m "feat: 添加采购交易前端API"

Task 16: 创建前端页面组件

Files:

  • Create: ruoyi-ui/src/views/ccdiPurchaseTransaction/index.vue

Step 1: 创建页面组件

参考 ruoyi-ui/src/views/ccdiStaffRecruitment/index.vue,实现:

  • 查询表单(项目名称、标的物名称、申请人、日期范围)
  • 列表表格(13个字段 + 操作列)
  • 新增/编辑对话框
  • 导入对话框(支持异步导入状态轮询)
  • 删除确认

Step 2: Commit

git add ruoyi-ui/src/views/ccdiPurchaseTransaction/index.vue
git commit -m "feat: 添加采购交易管理页面"

Task 17: 配置菜单和权限

Files:

  • Modify: 数据库菜单表

Step 1: 添加菜单数据

执行SQL:

-- 添加采购交易管理菜单
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES
('采购交易管理', (SELECT menu_id FROM sys_menu WHERE menu_name='CCDI管理' AND parent_id=0), 5, 'purchaseTransaction', 'ccdiPurchaseTransaction/index', 1, 0, 'C', '0', '0', 'ccdi:purchaseTransaction:list', 'shopping', 'admin', NOW(), '', NULL, '采购交易信息管理菜单');

-- 获取刚插入的菜单ID
SET @menu_id = LAST_INSERT_ID();

-- 添加按钮权限
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) VALUES
('采购交易查询', @menu_id, 1, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:query', '#', 'admin', NOW(), ''),
('采购交易新增', @menu_id, 2, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:add', '#', 'admin', NOW(), ''),
('采购交易修改', @menu_id, 3, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:edit', '#', 'admin', NOW(), ''),
('采购交易删除', @menu_id, 4, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:remove', '#', 'admin', NOW(), ''),
('采购交易导出', @menu_id, 5, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:export', '#', 'admin', NOW(), ''),
('采购交易导入', @menu_id, 6, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:import', '#', 'admin', NOW(), '');

Step 2: Commit

git add sql/
git commit -m "feat: 配置采购交易管理菜单和权限"

Task 18: 生成测试脚本

Files:

  • Create: test/test_purchase_transaction_api.ps1

Step 1: 创建测试脚本

参考 test/test_employee_api.ps1,编写完整的测试脚本:

  • 登录获取token
  • 测试分页查询
  • 测试新增
  • 测试查询详情
  • 测试修改
  • 测试删除
  • 测试导入
  • 测试导出

Step 2: Commit

git add test/test_purchase_transaction_api.ps1
git commit -m "test: 添加采购交易API测试脚本"

Task 19: 运行测试并生成报告

Step 1: 运行测试脚本

cd test
./test_purchase_transaction_api.ps1 > test_report_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt

Step 2: 验证所有接口正常

Expected: 所有测试用例通过

Step 3: 保存测试报告

将测试报告保存到 doc/test-data/purchase_transaction/ 目录。

Step 4: Commit

git add doc/test-data/purchase_transaction/
git commit -m "test: 添加采购交易测试报告"

Task 20: 生成API文档

Files:

  • Create: doc/api/ccdi_purchase_transaction_api.md

Step 1: 导出Swagger API文档

访问 http://localhost:8080/swagger-ui/index.html导出采购交易管理的API文档

Step 2: 整理为Markdown格式

整理所有接口的请求参数、响应格式、示例。

Step 3: Commit

git add doc/api/ccdi_purchase_transaction_api.md
git commit -m "docs: 添加采购交易API文档"

Task 21: 最终验证和清理

Step 1: 完整功能测试

  1. 启动后端服务
  2. 启动前端服务
  3. 登录系统
  4. 导航到采购交易管理菜单
  5. 测试所有功能:
    • 列表查询
    • 新增记录
    • 编辑记录
    • 删除记录
    • 批量删除
    • 导入功能(含异步状态轮询)
    • 导出功能

Step 2: 代码审查

检查:

  • 所有DTO验证注解完整
  • 所有Swagger注解完整
  • 异常处理完善
  • 日志记录完整
  • 审计字段正确填充

Step 3: 性能测试

测试批量导入1000条数据的性能。

Step 4: 最终Commit

git add .
git commit -m "feat: 完成采购交易信息管理功能开发"

实施注意事项

  1. 必填字段: purchaseId, purchaseCategory, subjectName, purchaseQty, budgetAmount, purchaseMethod, applyDate, applicantId, applicantName, applyDepartment
  2. 异步导入: 使用@Async + @Transactional + Redis
  3. 批量操作: 每批500条记录
  4. 更新策略: 先批量删除,再批量插入
  5. 数据验证: Jakarta Validation + 自定义业务验证
  6. 审计字段: 使用@TableField(fill = FieldFill.INSERT/INSERT_UPDATE)
  7. 错误处理: 只返回失败记录,不返回成功记录
  8. 导入轮询: 每2秒轮询一次状态

参考文件

  • 员工招聘信息模块: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/**/CcdiStaffRecruitment*
  • 员工异步导入: ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/impl/CcdiEmployeeImportServiceImpl.java
  • 前端页面: ruoyi-ui/src/views/ccdiStaffRecruitment/index.vue
  • 测试脚本: test/test_employee_api.ps1