Files
ccdi/assets/plans/2026-02-26-create-project-design.md
2026-03-03 16:14:16 +08:00

27 KiB
Raw Blame History

创建项目功能设计文档

文档版本: v1.0 创建日期: 2026-02-26 设计人员: Claude Code


1. 概述

1.1 功能描述

新增"创建项目"功能,允许用户在首页点击"新建项目"按钮后,通过弹窗表单创建新的纪检初核项目。

1.2 核心需求

  • 弹窗包含3个字段项目名称、项目描述、配置方式
  • 配置方式为单选按钮:全局默认模型参数配置 / 自定义项目规则参数配置
  • 项目列表展示项目名称和描述(上下排列)、状态、目标人数、预警人数、创建人、创建时间
  • 预警人数为各级别风险人数之和,悬停显示详细分布

2. 数据库设计

2.1 表结构

表名: ccdi_project

字段列表:

字段名 类型 长度 必填 默认值 说明
project_id BIGINT - 自增 项目ID主键
project_name VARCHAR 100 - 项目名称
project_desc VARCHAR 500 NULL 项目描述
config_type VARCHAR 20 'default' 配置方式default-全局默认custom-自定义
project_status CHAR 1 '0' 项目状态0-进行中1-已完成2-已归档
target_count INT - 0 目标人数
high_risk_count INT - 0 高风险人数
medium_risk_count INT - 0 中风险人数
low_risk_count INT - 0 低风险人数
create_by VARCHAR 64 '' 创建者
create_time DATETIME - CURRENT_TIMESTAMP 创建时间
update_by VARCHAR 64 '' 更新者
update_time DATETIME - CURRENT_TIMESTAMP 更新时间
remark VARCHAR 500 NULL 备注

索引设计:

  • 主键索引:PRIMARY KEY (project_id)
  • 项目名称索引:INDEX idx_project_name (project_name)
  • 项目状态索引:INDEX idx_project_status (project_status)
  • 创建时间索引:INDEX idx_create_time (create_time)

2.2 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';

3. 后端架构设计

3.1 实体类

类名: CcdiProject 位置: ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/

@Data
public class CcdiProject {
    /** 项目ID */
    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;
}

3.2 DTO 设计

类名: CcdiProjectSaveDTO 位置: ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/

@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;
}

3.3 VO 设计

类名: CcdiProjectVO 位置: ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/

@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;
}

3.4 Controller 接口

类名: CcdiProjectController 位置: ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/controller/

接口列表:

接口路径 方法 说明 权限标识
/ccdi/project POST 创建项目 ccdi:project:add
/ccdi/project PUT 更新项目 ccdi:project:edit
/ccdi/project/{projectId} DELETE 删除项目 ccdi:project:remove
/ccdi/project/{projectId} GET 查询项目详情 ccdi:project:query
/ccdi/project/list GET 查询项目列表(分页) ccdi:project:list

示例代码:

@RestController
@RequestMapping("/ccdi/project")
@Api(tags = "纪检初核项目管理")
public class CcdiProjectController extends BaseController {

    @Resource
    private ICcdiProjectService projectService;

    @PostMapping
    @ApiOperation("创建项目")
    @PreAuthorize("@ss.hasPermi('ccdi:project:add')")
    public AjaxResult createProject(@Validated @RequestBody CcdiProjectSaveDTO dto) {
        CcdiProjectVO vo = projectService.createProject(dto);
        return AjaxResult.success("项目创建成功", vo);
    }

    @GetMapping("/list")
    @ApiOperation("查询项目列表")
    @PreAuthorize("@ss.hasPermi('ccdi:project:list')")
    public TableDataInfo listProject(CcdiProjectQueryDTO queryDTO) {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Page<CcdiProjectVO> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
        Page<CcdiProjectVO> result = projectService.selectProjectPage(page, queryDTO);
        return getDataTable(result.getRecords(), result.getTotal());
    }
}

3.5 Service 层

接口名: ICcdiProjectService 实现类名: CcdiProjectServiceImpl 位置: ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/service/

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<CcdiProjectVO> selectProjectPage(Page<CcdiProjectVO> page, CcdiProjectQueryDTO queryDTO);
}

实现类示例:

@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;
    }
}

3.6 Mapper 层

接口名: CcdiProjectMapper 位置: ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/mapper/

public interface CcdiProjectMapper extends BaseMapper<CcdiProject> {
    /**
     * 分页查询项目列表
     * @param page 分页对象
     * @param queryDTO 查询条件
     * @return 分页结果
     */
    Page<CcdiProjectVO> selectProjectPage(Page<CcdiProjectVO> page, @Param("queryDTO") CcdiProjectQueryDTO queryDTO);
}

XML 文件: CcdiProjectMapper.xml 位置: ruoyi-info-collection/src/main/resources/mapper/info/collection/

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.info.collection.mapper.CcdiProjectMapper">

    <resultMap id="ProjectVOResultMap" type="com.ruoyi.info.collection.domain.vo.CcdiProjectVO">
        <id property="projectId" column="project_id"/>
        <result property="projectName" column="project_name"/>
        <result property="projectDesc" column="project_desc"/>
        <result property="configType" column="config_type"/>
        <result property="projectStatus" column="project_status"/>
        <result property="targetCount" column="target_count"/>
        <result property="highRiskCount" column="high_risk_count"/>
        <result property="mediumRiskCount" column="medium_risk_count"/>
        <result property="lowRiskCount" column="low_risk_count"/>
        <result property="createTime" column="create_time"/>
        <result property="createBy" column="create_by"/>
    </resultMap>

    <!-- 分页查询项目列表 -->
    <select id="selectProjectPage" resultMap="ProjectVOResultMap">
        SELECT
            project_id, project_name, project_desc, config_type,
            project_status, target_count, high_risk_count,
            medium_risk_count, low_risk_count, create_time, create_by
        FROM ccdi_project
        <where>
            <if test="queryDTO.projectName != null and queryDTO.projectName != ''">
                AND project_name LIKE CONCAT('%', #{queryDTO.projectName}, '%')
            </if>
            <if test="queryDTO.projectStatus != null and queryDTO.projectStatus != ''">
                AND project_status = #{queryDTO.projectStatus}
            </if>
        </where>
        ORDER BY create_time DESC
    </select>
</mapper>

4. 前端架构设计

4.1 组件修改

组件名称: AddProjectDialog.vue 位置: ruoyi-ui/src/views/ccdiProject/components/

修改内容:

  1. 简化表单字段只保留项目名称、项目描述、配置方式3个字段
  2. 移除字段:目标人员、开始日期、结束日期、目标人数、高级设置
  3. 默认值:配置方式默认为 'default'

关键代码:

<template>
  <el-dialog
    :visible.sync="dialogVisible"
    :title="title"
    width="600px"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    @close="handleClose"
  >
    <el-form
      ref="projectForm"
      :model="formData"
      :rules="rules"
      label-width="100px"
      label-position="right"
    >
      <!-- 项目名称 -->
      <el-form-item label="项目名称" prop="projectName">
        <el-input
          v-model="formData.projectName"
          placeholder="请输入项目名称"
          maxlength="100"
          show-word-limit
        />
      </el-form-item>

      <!-- 项目描述 -->
      <el-form-item label="项目描述" prop="projectDesc">
        <el-input
          v-model="formData.projectDesc"
          type="textarea"
          :rows="4"
          placeholder="请输入项目描述"
          maxlength="500"
          show-word-limit
        />
      </el-form-item>

      <!-- 配置方式 -->
      <el-form-item label="配置方式" prop="configType">
        <el-radio-group v-model="formData.configType">
          <el-radio label="default">全局默认模型参数配置</el-radio>
          <el-radio label="custom">自定义项目规则参数配置</el-radio>
        </el-radio-group>
      </el-form-item>
    </el-form>

    <div slot="footer" class="dialog-footer">
      <el-button @click="handleClose"> </el-button>
      <el-button type="primary" :loading="submitting" @click="handleSubmit">
        创建项目
      </el-button>
    </div>
  </el-dialog>
</template>

<script>
import { createProject } from '@/api/ccdiProject'

export default {
  name: 'AddProjectDialog',
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: '新建项目'
    }
  },
  data() {
    return {
      submitting: false,
      formData: {
        projectName: '',
        projectDesc: '',
        configType: 'default'
      },
      rules: {
        projectName: [
          { required: true, message: '请输入项目名称', trigger: 'blur' },
          { min: 2, max: 100, message: '长度在 2 到 100 个字符', trigger: 'blur' }
        ],
        configType: [
          { required: true, message: '请选择配置方式', trigger: 'change' }
        ]
      }
    }
  },
  computed: {
    dialogVisible: {
      get() {
        return this.visible
      },
      set(val) {
        if (!val) {
          this.handleClose()
        }
      }
    }
  },
  methods: {
    handleSubmit() {
      this.$refs.projectForm.validate(valid => {
        if (valid) {
          this.submitting = true
          createProject(this.formData).then(response => {
            this.$message.success('项目创建成功')
            this.submitting = false
            this.$emit('submit', response.data)
            this.handleClose()
          }).catch(() => {
            this.submitting = false
          })
        }
      })
    },

    handleClose() {
      this.$emit('close')
      this.$refs.projectForm.resetFields()
      this.formData = {
        projectName: '',
        projectDesc: '',
        configType: 'default'
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.dialog-footer {
  text-align: right;

  .el-button + .el-button {
    margin-left: 8px;
  }
}

:deep(.el-radio-group) {
  display: flex;
  flex-direction: column;
  gap: 12px;

  .el-radio {
    line-height: 32px;
  }
}
</style>

4.2 项目列表表格

组件名称: ProjectTable.vue 位置: ruoyi-ui/src/views/ccdiProject/components/

关键特性:

  1. 项目名称和描述上下排列:同一单元格内,项目名称加粗深色,项目描述常规浅色
  2. 预警人数悬停提示:显示高、中、低风险人数详细分布
  3. 预警人数样式:根据风险级别自动调整颜色

表格列配置:

列名 宽度 对齐方式 说明
项目名称 最小300px 左对齐 包含项目名称(上)+项目描述(下),自适应
项目状态 100px 居中对齐 固定宽度
目标人数 100px 居中对齐 固定宽度
预警人数 120px 居中对齐 悬停显示详细风险分布
创建人 120px 居中对齐 固定宽度
创建时间 160px 居中对齐 格式化显示
操作 280px 居中对齐 固定在右侧

关键代码:

<!-- 项目名称含描述 -->
<el-table-column label="项目名称" min-width="300" align="left">
  <template slot-scope="scope">
    <div class="project-info-cell">
      <div class="project-name">{{ scope.row.projectName }}</div>
      <div class="project-desc">{{ scope.row.projectDesc || '暂无描述' }}</div>
    </div>
  </template>
</el-table-column>

<!-- 预警人数带悬停详情 -->
<el-table-column label="预警人数" width="120" align="center">
  <template slot-scope="scope">
    <el-tooltip placement="top" effect="light">
      <div slot="content">
        <div style="padding: 8px;">
          <div style="margin-bottom: 8px; font-weight: bold; color: #303133;">
            风险人数统计
          </div>
          <div style="margin-bottom: 6px;">
            <span style="color: #f56c6c;"> 高风险</span>
            <span style="font-weight: bold;">{{ scope.row.highRiskCount }} </span>
          </div>
          <div style="margin-bottom: 6px;">
            <span style="color: #e6a23c;"> 中风险</span>
            <span style="font-weight: bold;">{{ scope.row.mediumRiskCount }} </span>
          </div>
          <div>
            <span style="color: #909399;"> 低风险</span>
            <span style="font-weight: bold;">{{ scope.row.lowRiskCount }} </span>
          </div>
        </div>
      </div>
      <div class="warning-count-wrapper">
        <span :class="getWarningClass(scope.row)" style="cursor: pointer;">
          {{ scope.row.highRiskCount + scope.row.mediumRiskCount + scope.row.lowRiskCount }}
        </span>
      </div>
    </el-tooltip>
  </template>
</el-table-column>

样式代码:

.project-info-cell {
  padding: 8px 0;
  line-height: 1.5;

  .project-name {
    font-size: 14px;
    font-weight: 600;
    color: #303133;
    margin-bottom: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .project-desc {
    font-size: 12px;
    color: #909399;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

.text-danger {
  color: #f56c6c;
}

.text-warning {
  color: #e6a23c;
}

.text-info {
  color: #909399;
}

.text-bold {
  font-weight: bold;
}

预警人数样式规则:

  • 高风险 > 0红色加粗
  • 中风险 > 0橙色加粗
  • 低风险 > 0灰色
  • 无预警:普通黑色

4.3 API 接口

文件名: ccdiProject.js 位置: ruoyi-ui/src/api/

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'
  })
}

5. 实施计划

5.1 实施步骤

阶段一:数据库与后端开发(预计 2.5 小时)

  1. 创建数据库表15 分钟)

    • 执行 ccdi_project 表创建脚本
    • 插入字典数据和菜单数据
  2. 后端开发2 小时)

    • 创建实体类 CcdiProject
    • 创建 DTO CcdiProjectSaveDTO
    • 创建 VO CcdiProjectVO
    • 创建 Mapper 接口和 XML
    • 创建 Service 接口和实现类
    • 创建 Controller 接口
    • 添加 Swagger 注解
  3. 后端测试30 分钟)

    • 使用 Swagger 测试创建项目接口
    • 使用 Swagger 测试查询项目列表接口
    • 验证数据字典显示

阶段二:前端开发(预计 2.5 小时)

  1. 前端组件开发1.5 小时)

    • 修改 AddProjectDialog.vue 组件
    • 修改 ProjectTable.vue 组件
    • 更新 API 接口文件 ccdiProject.js
    • 修改父组件调用逻辑
  2. 前端联调1 小时)

    • 测试创建项目功能
    • 测试项目列表显示
    • 测试预警人数悬停提示
    • 测试字典数据展示

6. 注意事项

6.1 数据完整性

  • 创建项目时,project_status 默认为 '0'(进行中)
  • 创建项目时,风险计数字段默认为 0
  • config_type 默认为 'default'
  • 项目名称和描述不能为空

6.2 权限控制

  • 创建项目需要 ccdi:project:add 权限
  • 编辑项目需要 ccdi:project:edit 权限
  • 删除项目需要 ccdi:project:remove 权限
  • 查询项目需要 ccdi:project:list 权限

6.3 前端验证

  • 项目名称必填2-100字符
  • 项目描述可选最多500字符
  • 配置方式:必填,只能选择 defaultcustom

6.4 后端验证

  • 使用 @Validated 注解进行参数校验
  • 项目名称长度校验
  • 配置方式枚举值校验

6.5 性能优化

  • 项目列表分页查询
  • 项目名称和状态字段添加索引
  • 字典数据使用缓存

6.6 用户体验

  • 提交按钮显示 loading 状态
  • 创建成功后自动刷新列表
  • 预警人数悬停提示详细信息
  • 项目名称和描述上下排列,层次分明

7. 测试清单

7.1 后端测试

  • 创建项目成功(必填字段)
  • 创建项目失败(缺少必填字段)
  • 创建项目失败(字段长度超限)
  • 查询项目列表(分页)
  • 查询项目详情
  • 更新项目
  • 删除项目
  • 字典数据正确返回
  • 权限验证正确

7.2 前端测试

  • 弹窗显示正确3个字段
  • 表单验证正常(必填项)
  • 表单验证正常(长度限制)
  • 项目名称和描述上下排列
  • 项目名称样式正确(加粗深色)
  • 项目描述样式正确(常规浅色)
  • 项目状态标签正确显示
  • 预警人数计算正确(高+中+低)
  • 预警人数悬停提示显示
  • 预警人数颜色根据风险级别变化
  • 创建人正确显示
  • 创建时间格式化正确
  • 操作按钮权限控制
  • 提交按钮 loading 状态
  • 创建成功后列表刷新

8. 附录

8.1 参考文档

  • 若依框架官方文档
  • Element UI 组件库文档
  • MyBatis Plus 官方文档

8.2 相关文件

  • 数据库脚本:sql/ccdi_project.sql
  • 设计截图:doc/创建项目功能/ScreenShot_2026-02-26_153149_900.png
  • 设计截图:doc/创建项目功能/ScreenShot_2026-02-26_162233_965.png

文档结束