如何从Projects数组生成含嵌套Subtasks的对象数组?
解决Projects数组转多层嵌套任务数组的问题
需求说明
需要将包含workItems子数组的projects数组,转换为每个项目对应一个主任务对象的数组,每个主任务的subtasks属性由对应项目的workItems转换而来,且每个workItem还需进一步拆分为更细的子任务(如Design、Workshop、Site等阶段)。
现有问题代码
当前代码通过两层map导致每个workItem生成一个主任务对象,不符合“一个项目对应一个主任务”的预期:
let newProjects1 = projects.map((project, index) => { return project.workItems.map((workItem) => { return { TaskID: index, ProjectNo: project.projectNumber, TaskName: project.projectTitle, StartDate: new Date("11/11/2024"), EndDate: new Date(project.projectEnd), subtasks: [ { TaskID: index, TaskName: workItem.name, StartDate: new Date("11/11/2024"), Duration: 80, Progress: 150, }, ], }; }) });
输入数据示例(单个Project对象)
[{ "projectNumber": 26278, "projectTitle": "Ifon WTW", "chemicals": ["sodium hypochlorite", "sodium hydroxide", "pacl"], "projectStatus": "site survey", "siteType": "SR", "location": "Glasgow", "contractType": "construction", "designLead": "Craig Garvie", "projectManager": "Isaac Stanton", "projectType": "Other", "spm": "Mark Tench", "client": "Yorkshire Water", "comments": "project going swimmingly", "projectStart": "12/20/2022", "projectEnd": "07/28/2024", "createdAt": "2022-11-22T07:43:42Z", "updatedAt": "2023-04-09T10:13:14Z", "equipment": [ { "name": "kiosk", "count": 2 }, { "name": "tanker fill point", "count": 1 }, { "name": "dosing skid", "count": 1 }, { "name": "POA catchpot", "count": 1 }, { "name": "Low Point Catchpot", "count": 0 }, { "name": "MCC", "count": 1 } ], "workItems": [ { "name": "work Item 1", "siteSurveyStart": "11/29/2022", "siteSurveyEnd": "01/25/2023", "designStart": "02/14/2023", "designEnd": "03/06/2023", "workShopStart": "04/24/2023", "workShopEnd": "05/05/2023", "rsePremisesStart": "06/24/2023", "rsePremisesEnd": "07/09/2023", "siteStart": "08/20/2023", "siteEnd": "09/13/2023" }, { "name": "work Item 2", "siteSurveyStart": "11/02/2022", "siteSurveyEnd": "01/05/2023", "designStart": "02/02/2023", "designEnd": "03/24/2023", "workShopStart": "04/11/2023", "workShopEnd": "05/19/2023", "rsePremisesStart": "06/19/2023", "rsePremisesEnd": "07/17/2023", "siteStart": "08/20/2023", "siteEnd": "09/23/2023" } ], "chemical": [{ "name": "sodium carbonate" }, { "name": "sulphuric acid" }], "projectPersonnel": [ { "name": "daniel carey" }, { "name": "erin donnelly" }, { "name": "craig garvie" }, { "name": "ryan watson" }, { "name": "lewis scott" }, { "name": "jack overfield" }, { "name": "fidel hernandez" } } }]
修正后的代码
// 计算两个日期之间的天数差,用于Duration const getDuration = (startDateStr, endDateStr) => { const start = new Date(startDateStr); const end = new Date(endDateStr); return Math.ceil((end - start) / (1000 * 60 * 60 * 24)); }; let newProjects = projects.map((project, projIndex) => { // 主任务ID,从1开始 const mainTaskId = projIndex + 1; return { TaskID: mainTaskId, ProjectNo: project.projectNumber.toString(), TaskName: project.projectTitle, StartDate: new Date(project.projectStart), EndDate: new Date(project.projectEnd), // 生成当前项目的subtasks(对应workItems) subtasks: project.workItems.map((workItem, itemIndex) => { // workItem的ID格式:主ID.序号 const workItemId = `${mainTaskId}.${itemIndex + 1}`; // 从workItem中提取各阶段生成子任务 const stageSubtasks = [ { TaskID: `${workItemId}.1`, TaskName: "Design", StartDate: new Date(workItem.designStart), Duration: getDuration(workItem.designStart, workItem.designEnd), Progress: 150 }, { TaskID: `${workItemId}.2`, TaskName: "Workshop", StartDate: new Date(workItem.workShopStart), Duration: getDuration(workItem.workShopStart, workItem.workShopEnd), Progress: 150 }, { TaskID: `${workItemId}.3`, TaskName: "Site", StartDate: new Date(workItem.siteStart), Duration: getDuration(workItem.siteStart, workItem.siteEnd), Progress: 150 } ]; return { TaskID: parseFloat(workItemId), TaskName: workItem.name, StartDate: new Date(project.projectStart), Duration: getDuration(project.projectStart, project.projectEnd), Progress: 150, comments: project.comments, subtasks: stageSubtasks }; }) }; });
代码说明
- 外层map遍历Projects:每个项目生成一个主任务对象,而非拆分多个主任务
- subtasks生成逻辑:主任务的
subtasks由当前项目的workItems数组转换而来,每个workItem对应一个子任务 - 多层子任务拆分:每个workItem进一步拆分为Design、Workshop、Site等阶段子任务,通过提取workItem中的日期字段计算Duration
- TaskID规则:主任务ID从1开始,workItemID为
主ID.序号,阶段子任务ID为workItemID.序号,保证层级清晰 - 日期与Duration计算:通过工具函数
getDuration计算两个日期之间的天数差,替代固定值,更贴合实际数据
内容的提问来源于stack exchange,提问作者Blob
相关产品推荐
相关产品推荐

