求助:JavaScript无法将employeeBookedMonths推入Chart.js的dataArray
问题说明
我不是JavaScript开发者,之前在Stack Overflow的帮助下实现了Chart.js图表功能。后来把数据结构从2表调整为3表(包含一对多、多对一关系),现在接近完成,但需要解决如何将employeeBookedMonths正确推入data数组的问题——目前代码只会取员工在同一个项目下的第一条数据,而实际上一个员工可能在同一个项目里有多个employeeBookedMonths条目,需要把这些数值累加后再放入图表数据中。
数据结构 listEmployees
var listEmployees = [ {"id":1,"name":"Bill Turner","contractedFrom":"2022-09-01","contractedTo":"2022-10-30", "employeeProjects":[ {"id":14,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":7.7}, {"id":2,"project":{"id":6,"projectNumber":66666,"name":"Project 6","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":60.0,"remainingBookedMonths":6.0,"numberOfEmployees":6},"employeeBookedMonths":6.0}, {"id":7,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":8.0}, {"id":5,"project":{"id":9,"projectNumber":56789,"name":"Project 9","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":30.0,"remainingBookedMonths":5.0,"numberOfEmployees":3},"employeeBookedMonths":8.0}, {"id":15,"project":{"id":8,"projectNumber":54321,"name":"Project 8","startDate":"2020-05-01","endDate":"2022-06-31","projectLengthInMonths":40.0,"currentBookedMonths":32.0,"remainingBookedMonths":8.0,"numberOfEmployees":4},"employeeBookedMonths":8.8}]}, {"id":2,"name":"Kate Miller","contractedFrom":"2022-01-01","contractedTo":"2022-05-30", "employeeProjects":[ {"id":3,"project":{"id":4,"projectNumber":44444,"name":"Project 4","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":40.0,"remainingBookedMonths":4.0,"numberOfEmployees":4},"employeeBookedMonths":14.0}, {"id":6,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":5.0}, {"id":8,"project":{"id":9,"projectNumber":56789,"name":"Project 9","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":30.0,"remainingBookedMonths":5.0,"numberOfEmployees":3},"employeeBookedMonths":5.0}, {"id":13,"project":{"id":8,"projectNumber":54321,"name":"Project 8","startDate":"2020-05-01","endDate":"2022-06-31","projectLengthInMonths":40.0,"currentBookedMonths":32.0,"remainingBookedMonths":8.0,"numberOfEmployees":4},"employeeBookedMonths":6.6}]}, {"id":3,"name":"John Smith","contractedFrom":"2022-06-01","contractedTo":"2022-12-30","employeeProjects":[ {"id":12,"project":{"id":1,"projectNumber":12345,"name":"Project 1","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":2.5}]}];
当前Chart.js代码
const labels = listEmployees.reduce(function(result, item) { result.push(item.name); return result; }, []); const randomColorGenerator = function () { return '#' + (Math.random().toString(16) + '0000000').slice(2, 8); }; const projects = listEmployees.reduce(function(result, item) { item.employeeProjects.forEach(function(prj){ const prjId = prj.project.id; if (!result[prjId]) { result[prjId] = { label: prj.project.name, data: [], backgroundColor: randomColorGenerator() }; } }); return result; }, {}); listEmployees.forEach(function(item) { for (const prjId of Object.keys(projects)) { const prj = projects[prjId]; const empPrj = item.employeeProjects.filter(el => el.project.id === prjId); if (empPrj.length) { prj.data.push(empPrj[0].employeeBookedMonths); } else { prj.data.push(0); } } }); const ctx = document.getElementById("myChart"); const myChart = new Chart(ctx, { type: 'bar', data: { labels: labels, datasets: Object.values(projects) }, options: { scales: { x: { stacked: true }, y: { stacked: true } } } });
解决方案
问题出在遍历员工项目时,只取了匹配项目的第一条数据。需要把同一个员工在同一个项目下的所有employeeBookedMonths数值相加,再推入数据数组。
修改listEmployees.forEach这段代码:
listEmployees.forEach(function(item) { // 先统计当前员工每个项目的总预订月份 const empProjectTotals = item.employeeProjects.reduce((totals, empPrj) => { const prjId = empPrj.project.id.toString(); // 转为字符串和projects的key匹配 totals[prjId] = (totals[prjId] || 0) + empPrj.employeeBookedMonths; return totals; }, {}); for (const prjId of Object.keys(projects)) { const prj = projects[prjId]; // 取统计后的总和,没有则为0 prj.data.push(empProjectTotals[prjId] || 0); } });
这样修改后,每个员工在同一个项目下的多条employeeBookedMonths会被累加,比如Bill Turner在Project7的7.7+8.0=15.7会被正确计入图表数据。
内容的提问来源于stack exchange,提问作者Kayd Anderson
相关产品推荐
相关产品推荐

