news 2026/5/1 1:21:30

要实现“新建需求”功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
要实现“新建需求”功能


要实现“新建需求”功能,我们可以基于Vue(Element UI)+ Spring Boot(若依框架)做前后端分离开发,以下是完整实现方案:

一、后端(Spring Boot + 若依)

1. 数据库表设计

需要2张核心表:需求主表+需求角色关联表(关联角色与人员)。

-- 1. 需求主表CREATETABLE`requirement`(`id`bigintNOTNULLAUTO_INCREMENTCOMMENT'需求ID',`name`varchar(200)NOTNULLCOMMENT'需求名称',`type`varchar(50)NOTNULLCOMMENT'需求类型(字典值:如功能/优化)',`description`textCOMMENT'需求描述',`business_line`varchar(100)DEFAULTNULLCOMMENT'业务线',`priority`varchar(20)DEFAULTNULLCOMMENT'优先级(字典值:高/中/低)',`expected_delivery_time`datetimeDEFAULTNULLCOMMENT'预计交付时间',`function_point`decimal(10,2)DEFAULTNULLCOMMENT'功能点数估值',`follower_id`bigintDEFAULTNULLCOMMENT'关注人ID(关联sys_user)',`pull_group_type`varchar(20)DEFAULT'no'COMMENT'拉群方式:auto=自动拉群/no=不拉群/bind=绑定现有群',`iteration_id`bigintDEFAULTNULLCOMMENT'规划迭代ID(关联迭代表)',`version_id`bigintDEFAULTNULLCOMMENT'规划版本ID(关联版本表)',`is_draft`tinyintDEFAULT'0'COMMENT'是否草稿:0=否 1=是',`create_by`varchar(64)DEFAULT''COMMENT'创建人',`create_time`datetimeDEFAULTNULLCOMMENT'创建时间',PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='需求主表';-- 2. 需求角色关联表(对应“角色与人员”)CREATETABLE`requirement_role`(`id`bigintNOTNULLAUTO_INCREMENTCOMMENT'主键ID',`requirement_id`bigintNOTNULLCOMMENT'关联需求ID',`role_code`varchar(50)NOTNULLCOMMENT'角色编码(如RD/UX Writer)',`role_name`varchar(100)NOTNULLCOMMENT'角色名称',`user_id`bigintDEFAULTNULLCOMMENT'负责人ID(关联sys_user)',`user_name`varchar(64)DEFAULTNULLCOMMENT'负责人姓名',PRIMARYKEY(`id`),UNIQUEKEY`uk_req_role`(`requirement_id`,`role_code`)COMMENT'同一需求同一角色唯一')ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='需求角色关联表';
2. 实体类 & DTO
// 需求主表实体@Data@TableName("requirement")publicclassRequirement{@TableId(type=IdType.AUTO)privateLongid;privateStringname;privateStringtype;privateStringdescription;privateStringbusinessLine;privateStringpriority;privateDateexpectedDeliveryTime;privateBigDecimalfunctionPoint;privateLongfollowerId;privateStringpullGroupType;privateLongiterationId;privateLongversionId;privateIntegerisDraft;privateStringcreateBy;privateDatecreateTime;}// 需求角色关联实体@Data@TableName("requirement_role")publicclassRequirementRole{@TableId(type=IdType.AUTO)privateLongid;privateLongrequirementId;privateStringroleCode;privateStringroleName;privateLonguserId;privateStringuserName;}// 新增需求的提交DTO(主数据+角色列表)@DatapublicclassRequirementCreateDTO{privateRequirementrequirement;privateList<RequirementRole>roleList;}
3. 后端业务逻辑(Service + Controller)
// Service层:保存需求(主数据+角色关联)@ServicepublicclassRequirementServiceextendsServiceImpl<RequirementMapper,Requirement>{@ResourceprivateRequirementRoleServicerequirementRoleService;@Transactional(rollbackFor=Exception.class)publicvoidsaveRequirement(RequirementCreateDTOdto){// 1. 保存需求主表Requirementrequirement=dto.getRequirement();requirement.setIsDraft(0);// 非草稿this.save(requirement);// 2. 保存角色关联表(绑定需求ID)List<RequirementRole>roleList=dto.getRoleList();if(CollUtil.isNotEmpty(roleList)){roleList.forEach(role->role.setRequirementId(requirement.getId()));requirementRoleService.saveBatch(roleList);}}}// Controller层:提供新增/下拉选项接口@RestController@RequestMapping("/api/requirement")publicclassRequirementController{@ResourceprivateRequirementServicerequirementService;// 新建需求@PostMapping("/create")publicAjaxResultcreate(@RequestBodyRequirementCreateDTOdto){requirementService.saveRequirement(dto);returnAjaxResult.success("需求创建成功");}// 获取下拉选项(需求类型、业务线等)@GetMapping("/options")publicAjaxResultgetOptions(){RequirementOptionsDTOoptions=newRequirementOptionsDTO();// 从若依字典表获取枚举选项(如需求类型)options.setTypeList(dictService.selectDictDataByType("requirement_type"));options.setPriorityList(dictService.selectDictDataByType("requirement_priority"));// 业务线、迭代、版本从关联表查询(示例)options.setBusinessLineList(businessLineService.list());returnAjaxResult.success(options);}}

二、前端(Vue + Element UI)

1. 新建需求组件(RequirementCreate.vue)

复用之前的角色添加组件,实现“角色与人员”的动态添加:

<template> <el-dialog title="新建需求" :visible.sync="dialogVisible" width="60%" > <el-form ref="formRef" :model="form" label-width="120px" :rules="rules"> <!-- 需求名称 --> <el-form-item label="名称" prop="name"> <el-input v-model="form.name" placeholder="请输入需求名称" /> </el-form-item> <!-- 需求类型 --> <el-form-item label="需求类型" prop="type"> <el-select v-model="form.type" placeholder="请选择"> <el-option v-for="item in options.typeList" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" /> </el-select> </el-form-item> <!-- 描述 --> <el-form-item label="描述"> <el-input v-model="form.description" type="textarea" rows="4" placeholder="请输入需求描述" /> </el-form-item> <!-- 业务线/优先级/预计交付时间 --> <el-form-item label="业务线"> <el-select v-model="form.businessLine" placeholder="请选择" /> </el-form-item> <el-form-item label="优先级"> <el-select v-model="form.priority" placeholder="请选择"> <el-option v-for="item in options.priorityList" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" /> </el-select> </el-form-item> <el-form-item label="预计交付时间"> <el-date-picker v-model="form.expectedDeliveryTime" type="date" placeholder="请选择" /> </el-form-item> <!-- 功能点数 --> <el-form-item label="需求功能点数估值"> <el-input v-model.number="form.functionPoint" placeholder="请输入" /> </el-form-item> <!-- 需求相关人员 --> <el-form-item label="关注人"> <el-select v-model="form.followerId" placeholder="请选择"> <el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" /> </el-select> </el-form-item> <!-- 拉群方式 --> <el-form-item label="拉群方式选择"> <el-radio-group v-model="form.pullGroupType"> <el-radio label="auto">自动拉群</el-radio> <el-radio label="no" checked>不拉群</el-radio> <el-radio label="bind">绑定现有群</el-radio> </el-radio-group> </el-form-item> <!-- 角色与人员(复用组件) --> <el-form-item label="角色与人员"> <role-add-list ref="roleRef" /> </el-form-item> <!-- 规划迭代/版本 --> <el-form-item label="规划迭代"> <el-select v-model="form.iterationId" placeholder="请选择" /> </el-form-item> <el-form-item label="规划版本"> <el-select v-model="form.versionId" placeholder="请选择" /> </el-form-item> <!-- 连续创建 --> <el-form-item> <el-checkbox v-model="isContinuous">连续创建</el-checkbox> </el-form-item> </el-form> <template #footer> <el-button @click="handleClose">取消</el-button> <el-button type="primary" @click="saveDraft">存草稿</el-button> <el-button type="primary" @click="handleSubmit">确认创建</el-button> </template> </el-dialog> </template> <script> import RoleAddList from "@/components/RoleAddList"; // 复用角色添加组件 import { createRequirement, getRequirementOptions, listUser } from "@/api/requirement"; export default { components: { RoleAddList }, props: { dialogVisible: Boolean }, data() { return { form: { name: "", type: "", description: "", businessLine: "", priority: "", expectedDeliveryTime: null, functionPoint: null, followerId: null, pullGroupType: "no", iterationId: null, versionId: null }, rules: { name: [{ required: true, message: "请输入需求名称", trigger: "blur" }], type: [{ required: true, message: "请选择需求类型", trigger: "change" }] }, options: {}, // 下拉选项(需求类型/优先级等) userList: [], // 系统用户列表 isContinuous: false }; }, created() { this.loadOptions(); }, methods: { // 加载下拉选项 async loadOptions() { const optRes = await getRequirementOptions(); this.options = optRes.data; this.userList = (await listUser({ pageSize: 200 })).data.rows; }, // 提交需求 async handleSubmit() { this.$refs.formRef.validate(async (valid) => { if (valid) { // 获取角色列表(从子组件) const roleList = this.$refs.roleRef.roleList; // 构造提交数据 const dto = { requirement: this.form, roleList }; await createRequirement(dto); this.$message.success("需求创建成功"); // 连续创建则重置表单 this.isContinuous ? this.resetForm() : this.handleClose(); } }); }, // 存草稿 saveDraft() { this.form.isDraft = 1; this.handleSubmit(); // 复用提交逻辑,标记为草稿 }, // 重置表单 resetForm() { this.$refs.formRef.resetFields(); this.$refs.roleRef.roleList = []; }, // 关闭弹窗 handleClose() { this.resetForm(); this.$emit("update:dialogVisible", false); } } }; </script>

三、核心逻辑说明

  1. 数据关联

    • 需求主表关联系统用户(关注人)、迭代/版本表(规划项);
    • 角色与人员通过requirement_role表关联需求和用户,复用之前的角色选择组件。
  2. 前端交互

    • 表单项与form对象双向绑定,通过Element UI组件实现下拉、单选、文本输入;
    • “角色与人员”复用之前的RoleAddList组件,动态添加角色并选择负责人。
  3. 草稿功能

    • 通过is_draft字段标记草稿,提交时区分正式需求/草稿。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 8:08:35

西部黄金勘探技术:HeyGem生成地质找矿方法科普

西部黄金勘探技术&#xff1a;HeyGem生成地质找矿方法科普 在新疆某金矿项目现场&#xff0c;技术人员正围坐在移动终端前观看一段讲解视频——画面中一位熟悉的专家形象正在清晰地解析“蚀变分带与金矿化关系”。但事实上&#xff0c;这位“专家”已经退休三年&#xff0c;而这…

作者头像 李华
网站建设 2026/5/1 6:11:24

钛媒体产业分析引用:将HeyGem作为典型案例写入行业文章

HeyGem 数字人视频生成系统的工程化实践与产业价值 在内容生产迈向智能化的今天&#xff0c;企业对高效、低成本制作数字人视频的需求正以前所未有的速度增长。无论是电商直播中的虚拟主播&#xff0c;还是企业培训里的AI讲师&#xff0c;亦或是政务宣传中多语种播报员&#x…

作者头像 李华
网站建设 2026/5/1 6:16:42

文献综述写成“观点堆砌”?百考通AI平台3分钟生成有逻辑、有批判、有脉络的高质量综述

撰写文献综述是学术写作中最关键也最容易被低估的环节。许多学生误以为只要“把别人的研究摘要拼在一起”就算完成&#xff0c;结果交出的综述缺乏主线、没有批判、看不出研究演进&#xff0c;更无法定位自己的研究缺口。导师常批&#xff1a;“这不是综述&#xff0c;是读书笔…

作者头像 李华
网站建设 2026/5/1 9:21:43

爱国者移动电源新品发布:HeyGem制作户外探险情景剧

爱国者移动电源新品发布&#xff1a;HeyGem制作户外探险情景剧 在短视频主导用户注意力的今天&#xff0c;品牌如何以更低的成本、更快的速度生产出高质量宣传内容&#xff1f;爱国者&#xff08;aigo&#xff09;给出了一个极具前瞻性的答案——用AI数字人技术批量生成“户外探…

作者头像 李华
网站建设 2026/5/1 5:04:48

为什么你的API无法被前端调用?深度剖析PHP跨域请求根源

第一章&#xff1a;为什么你的API无法被前端调用&#xff1f;深度剖析PHP跨域请求根源 当你在开发前后端分离项目时&#xff0c;前端应用部署在 http://localhost:3000&#xff0c;而后端 API 运行在 http://localhost:8000&#xff0c;浏览器却阻止了请求&#xff0c;这通常…

作者头像 李华
网站建设 2026/5/1 5:03:53

ASG光口故障

本文档提供了ASG系列产品的维护指导。 文章目录光口故障现象描述可能原因处理步骤光口故障 现象描述 用户反馈上网不稳定&#xff0c;登录设备在系统日志中查看每隔5分钟左右接口会Up/Down一次。 可能原因 接口双工模式被修改。接口速率被修改。配置了接口状态探测或者接口…

作者头像 李华