ct-gantt-core 1.0.12 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +189 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -6
- package/dist/index.d.ts +45 -6
- package/dist/index.js +182 -62
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -22,12 +22,14 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
DAY_MS: () => DAY_MS,
|
|
24
24
|
DEFAULT_HOUR_COLORS: () => DEFAULT_HOUR_COLORS,
|
|
25
|
+
DEFAULT_RESOURCE_COLORS: () => DEFAULT_RESOURCE_COLORS,
|
|
25
26
|
DEFAULT_TASK_COLORS: () => DEFAULT_TASK_COLORS,
|
|
26
27
|
EDITOR_COLOR_OPTIONS: () => EDITOR_COLOR_OPTIONS,
|
|
27
28
|
GanttEngine: () => GanttEngine,
|
|
28
29
|
HOUR_MS: () => HOUR_MS,
|
|
29
30
|
OWNER_COLOR_PALETTE: () => OWNER_COLOR_PALETTE,
|
|
30
31
|
RESOURCE_COLOR_PALETTE: () => RESOURCE_COLOR_PALETTE,
|
|
32
|
+
RESOURCE_EDITOR_COLOR_OPTIONS: () => RESOURCE_EDITOR_COLOR_OPTIONS,
|
|
31
33
|
addDays: () => addDays,
|
|
32
34
|
addHours: () => addHours,
|
|
33
35
|
addPlannedDuration: () => addPlannedDuration,
|
|
@@ -38,8 +40,10 @@ __export(index_exports, {
|
|
|
38
40
|
computeLayout: () => computeLayout,
|
|
39
41
|
computeResourceLayout: () => computeResourceLayout,
|
|
40
42
|
computeTimeScale: () => computeTimeScale,
|
|
43
|
+
computeVisibleWindow: () => computeVisibleWindow,
|
|
41
44
|
computeWorkload: () => computeWorkload,
|
|
42
45
|
createGanttEngine: () => createGanttEngine,
|
|
46
|
+
dateExtent: () => dateExtent,
|
|
43
47
|
defaultConfig: () => defaultConfig,
|
|
44
48
|
diffDays: () => diffDays,
|
|
45
49
|
diffHours: () => diffHours,
|
|
@@ -49,15 +53,18 @@ __export(index_exports, {
|
|
|
49
53
|
hasTimeComponent: () => hasTimeComponent,
|
|
50
54
|
inclusiveDays: () => inclusiveDays,
|
|
51
55
|
isValidDate: () => isValidDate,
|
|
56
|
+
mergeGanttConfig: () => mergeGanttConfig,
|
|
52
57
|
mergeTaskPatch: () => mergeTaskPatch,
|
|
53
58
|
normalizeLinks: () => normalizeLinks,
|
|
54
59
|
plannedDurationBetween: () => plannedDurationBetween,
|
|
60
|
+
resolveGanttConfig: () => resolveGanttConfig,
|
|
55
61
|
resolveResourceColor: () => resolveResourceColor,
|
|
56
62
|
resolveUsageColor: () => resolveUsageColor,
|
|
57
63
|
resolveUsageTimes: () => resolveUsageTimes,
|
|
58
64
|
resultInvalidDate: () => resultInvalidDate,
|
|
59
65
|
scheduleByDependencies: () => scheduleByDependencies,
|
|
60
66
|
shiftTask: () => shiftTask,
|
|
67
|
+
sliceRangeItems: () => sliceRangeItems,
|
|
61
68
|
startOfDay: () => startOfDay,
|
|
62
69
|
subtractPlannedDuration: () => subtractPlannedDuration,
|
|
63
70
|
toDate: () => toDate,
|
|
@@ -67,41 +74,50 @@ module.exports = __toCommonJS(index_exports);
|
|
|
67
74
|
|
|
68
75
|
// src/styles/colors.ts
|
|
69
76
|
var DEFAULT_TASK_COLORS = {
|
|
70
|
-
task: "#
|
|
71
|
-
// 普通任务实际条
|
|
72
|
-
summary: "#
|
|
73
|
-
// 阶段条
|
|
74
|
-
milestone: "#
|
|
75
|
-
// 里程碑菱形 / 参考线默认
|
|
76
|
-
plan: "#
|
|
77
|
-
// 计划条外部底色
|
|
78
|
-
progress: "#
|
|
79
|
-
//
|
|
77
|
+
task: "#409EFF",
|
|
78
|
+
// 普通任务实际条 · Element 主色
|
|
79
|
+
summary: "#909399",
|
|
80
|
+
// 阶段条 · Element Info
|
|
81
|
+
milestone: "#E6A23C",
|
|
82
|
+
// 里程碑菱形 / 参考线默认 · Element Warning
|
|
83
|
+
plan: "#C6E2FF",
|
|
84
|
+
// 计划条外部底色 · 主色浅阶
|
|
85
|
+
progress: "#67C23A"
|
|
86
|
+
// 计划条内部进度色 · Element Success
|
|
80
87
|
};
|
|
81
88
|
var DEFAULT_HOUR_COLORS = {
|
|
82
|
-
plan: "#
|
|
83
|
-
//
|
|
84
|
-
progress: "#
|
|
85
|
-
//
|
|
86
|
-
milestone: "#
|
|
89
|
+
plan: "#409EFF",
|
|
90
|
+
// 小时视图只有计划条,用主色保证在白底网格上可见
|
|
91
|
+
progress: "#67C23A",
|
|
92
|
+
// 兼容保留,小时视图不再绘制进度填充
|
|
93
|
+
milestone: "#E6A23C"
|
|
87
94
|
// 里程碑菱形 / 参考线默认
|
|
88
95
|
};
|
|
89
|
-
var
|
|
96
|
+
var DEFAULT_RESOURCE_COLORS = {
|
|
97
|
+
booking: "#409EFF",
|
|
98
|
+
assignment: "#909399"
|
|
99
|
+
};
|
|
100
|
+
var RESOURCE_COLOR_PALETTE = [DEFAULT_RESOURCE_COLORS.booking];
|
|
101
|
+
var RESOURCE_EDITOR_COLOR_OPTIONS = [
|
|
102
|
+
"#409eff",
|
|
103
|
+
"#79bbff",
|
|
104
|
+
"#909399"
|
|
105
|
+
];
|
|
90
106
|
var EDITOR_COLOR_OPTIONS = [
|
|
91
|
-
"#
|
|
92
|
-
"#
|
|
93
|
-
"#
|
|
94
|
-
"#
|
|
95
|
-
"#
|
|
96
|
-
"#
|
|
97
|
-
"#
|
|
98
|
-
"#
|
|
107
|
+
"#409eff",
|
|
108
|
+
"#66b1ff",
|
|
109
|
+
"#67c23a",
|
|
110
|
+
"#e6a23c",
|
|
111
|
+
"#f56c6c",
|
|
112
|
+
"#909399",
|
|
113
|
+
"#9b87c4",
|
|
114
|
+
"#36cfc9"
|
|
99
115
|
];
|
|
100
|
-
var OWNER_COLOR_PALETTE = ["#
|
|
116
|
+
var OWNER_COLOR_PALETTE = ["#409EFF", "#67C23A", "#E6A23C", "#F56C6C", "#909399"];
|
|
101
117
|
|
|
102
118
|
// src/types/index.ts
|
|
103
119
|
var defaultConfig = {
|
|
104
|
-
viewMode: "
|
|
120
|
+
viewMode: "day",
|
|
105
121
|
rowHeight: 44,
|
|
106
122
|
columnWidth: 30,
|
|
107
123
|
headerHeight: 50,
|
|
@@ -124,7 +140,9 @@ var defaultConfig = {
|
|
|
124
140
|
hourWidth: 12,
|
|
125
141
|
autoSchedule: true,
|
|
126
142
|
editable: true,
|
|
127
|
-
enableSelection: false
|
|
143
|
+
enableSelection: false,
|
|
144
|
+
showAddTaskColumn: true,
|
|
145
|
+
addTaskAs: "child"
|
|
128
146
|
};
|
|
129
147
|
|
|
130
148
|
// src/services/checkCyclicDependency.ts
|
|
@@ -234,12 +252,21 @@ function flattenTasks(tasks, collapsedIds = /* @__PURE__ */ new Set()) {
|
|
|
234
252
|
const children = /* @__PURE__ */ new Map();
|
|
235
253
|
for (const task of tasks) {
|
|
236
254
|
const parentId = task.parentId ?? null;
|
|
237
|
-
const bucket = children.get(parentId)
|
|
238
|
-
bucket
|
|
239
|
-
|
|
255
|
+
const bucket = children.get(parentId);
|
|
256
|
+
if (bucket) {
|
|
257
|
+
bucket.push(task);
|
|
258
|
+
} else {
|
|
259
|
+
children.set(parentId, [task]);
|
|
260
|
+
}
|
|
240
261
|
}
|
|
241
262
|
const flattened = [];
|
|
263
|
+
const visited = /* @__PURE__ */ new Set();
|
|
264
|
+
const taskIds = new Set(tasks.map((task) => task.id));
|
|
242
265
|
const visit = (task, depth) => {
|
|
266
|
+
if (visited.has(task.id)) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
visited.add(task.id);
|
|
243
270
|
const childTasks = children.get(task.id) ?? [];
|
|
244
271
|
const collapsed = collapsedIds.has(task.id);
|
|
245
272
|
flattened.push({
|
|
@@ -258,6 +285,12 @@ function flattenTasks(tasks, collapsedIds = /* @__PURE__ */ new Set()) {
|
|
|
258
285
|
for (const root of children.get(null) ?? []) {
|
|
259
286
|
visit(root, 0);
|
|
260
287
|
}
|
|
288
|
+
for (const task of tasks) {
|
|
289
|
+
if (visited.has(task.id)) continue;
|
|
290
|
+
const parentId = task.parentId ?? null;
|
|
291
|
+
if (parentId && taskIds.has(parentId)) continue;
|
|
292
|
+
visit(task, 0);
|
|
293
|
+
}
|
|
261
294
|
return flattened;
|
|
262
295
|
}
|
|
263
296
|
|
|
@@ -359,6 +392,18 @@ function isValidDate(value) {
|
|
|
359
392
|
const date = value instanceof Date ? value : new Date(value);
|
|
360
393
|
return !Number.isNaN(date.getTime());
|
|
361
394
|
}
|
|
395
|
+
function dateExtent(dates) {
|
|
396
|
+
let min = Number.POSITIVE_INFINITY;
|
|
397
|
+
let max = Number.NEGATIVE_INFINITY;
|
|
398
|
+
for (const value of dates) {
|
|
399
|
+
const time = typeof value === "number" ? value : value.getTime();
|
|
400
|
+
if (!Number.isFinite(time)) continue;
|
|
401
|
+
if (time < min) min = time;
|
|
402
|
+
if (time > max) max = time;
|
|
403
|
+
}
|
|
404
|
+
if (!Number.isFinite(min) || !Number.isFinite(max)) return void 0;
|
|
405
|
+
return { start: new Date(min), end: new Date(max) };
|
|
406
|
+
}
|
|
362
407
|
function formatDate(date) {
|
|
363
408
|
const value = toDate(date);
|
|
364
409
|
const year = value.getFullYear();
|
|
@@ -463,6 +508,49 @@ function computeHourScale(start, end, hourWidth) {
|
|
|
463
508
|
return { days, hours, start: rangeStart, end: rangeEnd };
|
|
464
509
|
}
|
|
465
510
|
|
|
511
|
+
// src/services/computeVisibleWindow.ts
|
|
512
|
+
function computeVisibleWindow(scroll, viewportSize, itemSize, itemCount, overscan = 8) {
|
|
513
|
+
if (itemCount <= 0 || itemSize <= 0) {
|
|
514
|
+
return { start: 0, end: -1, before: 0, after: 0 };
|
|
515
|
+
}
|
|
516
|
+
if (viewportSize <= 0) {
|
|
517
|
+
return { start: 0, end: itemCount - 1, before: 0, after: 0 };
|
|
518
|
+
}
|
|
519
|
+
const start = Math.max(0, Math.floor(scroll / itemSize) - overscan);
|
|
520
|
+
const end = Math.min(
|
|
521
|
+
itemCount - 1,
|
|
522
|
+
Math.ceil((scroll + viewportSize) / itemSize) + overscan
|
|
523
|
+
);
|
|
524
|
+
return {
|
|
525
|
+
start,
|
|
526
|
+
end,
|
|
527
|
+
before: start * itemSize,
|
|
528
|
+
after: Math.max(0, (itemCount - end - 1) * itemSize)
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
function sliceRangeItems(items, scrollLeft, viewportWidth, overscanPx = 320) {
|
|
532
|
+
if (viewportWidth <= 0 || items.length === 0) {
|
|
533
|
+
return items;
|
|
534
|
+
}
|
|
535
|
+
const min = scrollLeft - overscanPx;
|
|
536
|
+
const max = scrollLeft + viewportWidth + overscanPx;
|
|
537
|
+
return items.filter((item) => item.left + item.width >= min && item.left <= max);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// src/utils/mergeConfig.ts
|
|
541
|
+
function mergeGanttConfig(base, patch = {}) {
|
|
542
|
+
return {
|
|
543
|
+
...base,
|
|
544
|
+
...patch,
|
|
545
|
+
taskColors: { ...base.taskColors, ...patch.taskColors },
|
|
546
|
+
columnWidths: { ...base.columnWidths, ...patch.columnWidths },
|
|
547
|
+
resourceColors: { ...base.resourceColors, ...patch.resourceColors }
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
function resolveGanttConfig(patch = {}) {
|
|
551
|
+
return mergeGanttConfig(defaultConfig, patch);
|
|
552
|
+
}
|
|
553
|
+
|
|
466
554
|
// src/engines/scheduling.ts
|
|
467
555
|
function scheduleByDependencies(tasks, links) {
|
|
468
556
|
const cycle = checkCyclicDependency(links);
|
|
@@ -491,8 +579,18 @@ function scheduleByDependencies(tasks, links) {
|
|
|
491
579
|
}
|
|
492
580
|
};
|
|
493
581
|
}
|
|
494
|
-
|
|
495
|
-
|
|
582
|
+
const incomingList = incoming.get(link.targetId);
|
|
583
|
+
if (incomingList) {
|
|
584
|
+
incomingList.push(link);
|
|
585
|
+
} else {
|
|
586
|
+
incoming.set(link.targetId, [link]);
|
|
587
|
+
}
|
|
588
|
+
const outgoingList = outgoing.get(link.sourceId);
|
|
589
|
+
if (outgoingList) {
|
|
590
|
+
outgoingList.push(link);
|
|
591
|
+
} else {
|
|
592
|
+
outgoing.set(link.sourceId, [link]);
|
|
593
|
+
}
|
|
496
594
|
}
|
|
497
595
|
const ordered = topologicalOrder(tasks.map((task) => task.id), links);
|
|
498
596
|
for (const taskId of ordered) {
|
|
@@ -550,12 +648,20 @@ function topologicalOrder(ids, links) {
|
|
|
550
648
|
const outgoing = /* @__PURE__ */ new Map();
|
|
551
649
|
for (const link of links) {
|
|
552
650
|
indegree.set(link.targetId, (indegree.get(link.targetId) ?? 0) + 1);
|
|
553
|
-
|
|
651
|
+
const targets = outgoing.get(link.sourceId);
|
|
652
|
+
if (targets) {
|
|
653
|
+
targets.push(link.targetId);
|
|
654
|
+
} else {
|
|
655
|
+
outgoing.set(link.sourceId, [link.targetId]);
|
|
656
|
+
}
|
|
554
657
|
}
|
|
555
658
|
const queue = ids.filter((id) => (indegree.get(id) ?? 0) === 0);
|
|
556
659
|
const ordered = [];
|
|
557
|
-
|
|
558
|
-
|
|
660
|
+
let cursor = 0;
|
|
661
|
+
while (cursor < queue.length) {
|
|
662
|
+
const current = queue[cursor];
|
|
663
|
+
cursor += 1;
|
|
664
|
+
if (!current) continue;
|
|
559
665
|
ordered.push(current);
|
|
560
666
|
for (const target of outgoing.get(current) ?? []) {
|
|
561
667
|
indegree.set(target, (indegree.get(target) ?? 1) - 1);
|
|
@@ -590,7 +696,7 @@ function shiftTask(task, start) {
|
|
|
590
696
|
|
|
591
697
|
// src/engines/computeLayout.ts
|
|
592
698
|
function computeLayout(tasks, links, config, collapsedIds = /* @__PURE__ */ new Set(), viewport) {
|
|
593
|
-
const mergedConfig =
|
|
699
|
+
const mergedConfig = resolveGanttConfig(config);
|
|
594
700
|
for (const task of tasks) {
|
|
595
701
|
if (!isValidDate(task.actual.start) || !isValidDate(task.actual.end)) {
|
|
596
702
|
return {
|
|
@@ -608,7 +714,7 @@ function computeLayout(tasks, links, config, collapsedIds = /* @__PURE__ */ new
|
|
|
608
714
|
return scheduled;
|
|
609
715
|
}
|
|
610
716
|
const flatTasks = flattenTasks(scheduled.data, collapsedIds);
|
|
611
|
-
const firstDate = mergedConfig.visibleRange ? toDate(mergedConfig.visibleRange.start) :
|
|
717
|
+
const firstDate = mergedConfig.visibleRange ? toDate(mergedConfig.visibleRange.start) : dateExtent(scheduled.data.map((task) => toDate(task.actual.start)))?.start ?? toDate(/* @__PURE__ */ new Date());
|
|
612
718
|
const visibleStart = viewport ? Math.max(0, Math.floor(viewport.scrollTop / mergedConfig.rowHeight) - 8) : 0;
|
|
613
719
|
const visibleEnd = viewport ? Math.ceil((viewport.scrollTop + viewport.clientHeight) / mergedConfig.rowHeight) + 8 : Number.POSITIVE_INFINITY;
|
|
614
720
|
const layouts = flatTasks.filter((flat) => flat.rowIndex >= visibleStart && flat.rowIndex <= visibleEnd).map((flat) => {
|
|
@@ -627,9 +733,6 @@ function computeLayout(tasks, links, config, collapsedIds = /* @__PURE__ */ new
|
|
|
627
733
|
});
|
|
628
734
|
return { ok: true, data: layouts };
|
|
629
735
|
}
|
|
630
|
-
function minDate(dates) {
|
|
631
|
-
return new Date(Math.min(...dates.map((date) => date.getTime())));
|
|
632
|
-
}
|
|
633
736
|
|
|
634
737
|
// src/engines/computeImpact.ts
|
|
635
738
|
function computeImpact(taskId, patch, tasks, links, config) {
|
|
@@ -719,7 +822,13 @@ function resolveResourceColor(resource, resourceColors) {
|
|
|
719
822
|
return RESOURCE_COLOR_PALETTE[colorHash(source) % RESOURCE_COLOR_PALETTE.length];
|
|
720
823
|
}
|
|
721
824
|
function resolveUsageColor(usage, resource, resourceColors) {
|
|
722
|
-
|
|
825
|
+
if (usage.color) {
|
|
826
|
+
return usage.color;
|
|
827
|
+
}
|
|
828
|
+
if (resource.color || resourceColors?.[resource.id]) {
|
|
829
|
+
return resolveResourceColor(resource, resourceColors);
|
|
830
|
+
}
|
|
831
|
+
return usage.type === "assignment" ? DEFAULT_RESOURCE_COLORS.assignment : DEFAULT_RESOURCE_COLORS.booking;
|
|
723
832
|
}
|
|
724
833
|
function resolveUsageTimes(usage, timeUnit) {
|
|
725
834
|
if (timeUnit === "hour") {
|
|
@@ -730,7 +839,7 @@ function resolveUsageTimes(usage, timeUnit) {
|
|
|
730
839
|
return { start: toDate(usage.start), end: toDate(usage.end) };
|
|
731
840
|
}
|
|
732
841
|
function computeResourceLayout(resources, usages, config, viewport) {
|
|
733
|
-
const mergedConfig =
|
|
842
|
+
const mergedConfig = resolveGanttConfig(config);
|
|
734
843
|
const timeUnit = mergedConfig.timeUnit ?? "day";
|
|
735
844
|
const hourMode = timeUnit === "hour";
|
|
736
845
|
const hourW = mergedConfig.hourWidth ?? 12;
|
|
@@ -763,7 +872,12 @@ function computeResourceLayout(resources, usages, config, viewport) {
|
|
|
763
872
|
const resourceById = new Map(resources.map((resource) => [resource.id, resource]));
|
|
764
873
|
const usagesByResource = /* @__PURE__ */ new Map();
|
|
765
874
|
for (const usage of usages) {
|
|
766
|
-
|
|
875
|
+
const grouped = usagesByResource.get(usage.resourceId);
|
|
876
|
+
if (grouped) {
|
|
877
|
+
grouped.push(usage);
|
|
878
|
+
} else {
|
|
879
|
+
usagesByResource.set(usage.resourceId, [usage]);
|
|
880
|
+
}
|
|
767
881
|
}
|
|
768
882
|
const rows = [];
|
|
769
883
|
const usageLayouts = [];
|
|
@@ -808,8 +922,8 @@ function computeResourceLayout(resources, usages, config, viewport) {
|
|
|
808
922
|
const visibleStart = viewport ? Math.max(0, Math.floor(viewport.scrollTop / mergedConfig.rowHeight) - 8) : 0;
|
|
809
923
|
const visibleEnd = viewport ? Math.ceil((viewport.scrollTop + viewport.clientHeight) / mergedConfig.rowHeight) + 8 : Number.POSITIVE_INFINITY;
|
|
810
924
|
const firstDate = hourMode ? startOfDay(
|
|
811
|
-
mergedConfig.visibleRange ? toDateTime(mergedConfig.visibleRange.start) :
|
|
812
|
-
) : mergedConfig.visibleRange ? toDate(mergedConfig.visibleRange.start) :
|
|
925
|
+
mergedConfig.visibleRange ? toDateTime(mergedConfig.visibleRange.start) : dateExtent(usages.map((usage) => resolveUsageTimes(usage, "hour").start))?.start ?? toDateTime(/* @__PURE__ */ new Date())
|
|
926
|
+
) : mergedConfig.visibleRange ? toDate(mergedConfig.visibleRange.start) : dateExtent(usages.map((usage) => toDate(usage.start)))?.start ?? toDate(/* @__PURE__ */ new Date());
|
|
813
927
|
for (const row of rows) {
|
|
814
928
|
if (row.rowIndex < visibleStart || row.rowIndex > visibleEnd) {
|
|
815
929
|
continue;
|
|
@@ -846,16 +960,13 @@ function computeResourceLayout(resources, usages, config, viewport) {
|
|
|
846
960
|
function isLaneFree(laneEnd, start, hourMode) {
|
|
847
961
|
return hourMode ? diffHours(laneEnd, start) >= 0 : diffDays(laneEnd, start) > 0;
|
|
848
962
|
}
|
|
849
|
-
function minDate2(dates) {
|
|
850
|
-
return new Date(Math.min(...dates.map((date) => date.getTime())));
|
|
851
|
-
}
|
|
852
963
|
|
|
853
964
|
// src/engines/computeWorkload.ts
|
|
854
965
|
function computeWorkload(tasks, people, departments = [], range) {
|
|
855
966
|
const dated = range ?? inferRange(tasks);
|
|
856
967
|
if (!dated) return { dates: [], departments: [], ungrouped: [] };
|
|
857
968
|
const dates = datesBetween(dated.start, dated.end);
|
|
858
|
-
const
|
|
969
|
+
const dateIndex = new Map(dates.map((date, index) => [date, index]));
|
|
859
970
|
const rows = new Map(people.map((person) => [person.id, createPerson(person, dates)]));
|
|
860
971
|
for (const task of tasks) {
|
|
861
972
|
if (task.type === "summary" || task.type === "milestone") continue;
|
|
@@ -865,21 +976,32 @@ function computeWorkload(tasks, people, departments = [], range) {
|
|
|
865
976
|
for (const personId of ids) {
|
|
866
977
|
const row = rows.get(personId);
|
|
867
978
|
if (!row) continue;
|
|
868
|
-
for (const [date, hours] of Object.entries(values))
|
|
979
|
+
for (const [date, hours] of Object.entries(values)) {
|
|
980
|
+
const index = dateIndex.get(date);
|
|
981
|
+
if (index !== void 0) row.days[index].hours += hours;
|
|
982
|
+
}
|
|
869
983
|
}
|
|
870
984
|
}
|
|
871
985
|
for (const row of rows.values()) finalize(row);
|
|
872
986
|
const grouped = /* @__PURE__ */ new Map();
|
|
873
987
|
const ungrouped = [];
|
|
874
|
-
for (const row of rows.values())
|
|
988
|
+
for (const row of rows.values()) {
|
|
989
|
+
if (row.person.departmentId) {
|
|
990
|
+
const members = grouped.get(row.person.departmentId);
|
|
991
|
+
if (members) members.push(row);
|
|
992
|
+
else grouped.set(row.person.departmentId, [row]);
|
|
993
|
+
} else {
|
|
994
|
+
ungrouped.push(row);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
875
997
|
const departmentMap = new Map(departments.map((item) => [item.id, item]));
|
|
876
998
|
const result = [...grouped].map(([id, members]) => aggregateDepartment(departmentMap.get(id) ?? { id, name: id }, members, dates));
|
|
877
999
|
return { dates, departments: result, ungrouped };
|
|
878
1000
|
}
|
|
879
1001
|
function inferRange(tasks) {
|
|
880
1002
|
if (!tasks.length) return void 0;
|
|
881
|
-
const
|
|
882
|
-
return { start:
|
|
1003
|
+
const extent = dateExtent(tasks.flatMap((task) => [toDate(task.plan.start), toDate(task.plan.end)]));
|
|
1004
|
+
return extent ? { start: extent.start, end: extent.end } : void 0;
|
|
883
1005
|
}
|
|
884
1006
|
function datesBetween(start, end) {
|
|
885
1007
|
const values = [];
|
|
@@ -952,7 +1074,7 @@ var GanttEngine = class {
|
|
|
952
1074
|
constructor(options = {}) {
|
|
953
1075
|
this.tasks = options.tasks ? options.tasks.map((task) => ({ ...task })) : [];
|
|
954
1076
|
this.links = options.links ? options.links.map((link) => ({ ...link })) : [];
|
|
955
|
-
this.config = { ...defaultConfig, ...options.config };
|
|
1077
|
+
this.config = mergeGanttConfig({ ...defaultConfig }, { ...options.config });
|
|
956
1078
|
this.container = options.container ?? null;
|
|
957
1079
|
this.collapsedIds = new Set(options.collapsedIds ?? []);
|
|
958
1080
|
this.markers = options.markers ? options.markers.map((marker) => ({ ...marker })) : [];
|
|
@@ -986,22 +1108,22 @@ var GanttEngine = class {
|
|
|
986
1108
|
setTasks(tasks) {
|
|
987
1109
|
this.assertNotDestroyed();
|
|
988
1110
|
this.tasks = tasks.map((task) => ({ ...task }));
|
|
989
|
-
this.emit("taskschange", this.
|
|
1111
|
+
this.emit("taskschange", this.tasks);
|
|
990
1112
|
}
|
|
991
1113
|
setLinks(links) {
|
|
992
1114
|
this.assertNotDestroyed();
|
|
993
1115
|
this.links = links.map((link) => ({ ...link }));
|
|
994
|
-
this.emit("linkschange", this.
|
|
1116
|
+
this.emit("linkschange", this.links);
|
|
995
1117
|
}
|
|
996
1118
|
setMarkers(markers) {
|
|
997
1119
|
this.assertNotDestroyed();
|
|
998
1120
|
this.markers = markers.map((marker) => ({ ...marker }));
|
|
999
|
-
this.emit("markerschange", this.
|
|
1121
|
+
this.emit("markerschange", this.markers);
|
|
1000
1122
|
}
|
|
1001
1123
|
/** 合并配置 patch,等价于 setConfig(mergeConfig(patch)) */
|
|
1002
1124
|
mergeConfig(patch) {
|
|
1003
1125
|
this.assertNotDestroyed();
|
|
1004
|
-
this.config =
|
|
1126
|
+
this.config = mergeGanttConfig(this.config, patch);
|
|
1005
1127
|
this.emit("configchange", this.getConfig());
|
|
1006
1128
|
}
|
|
1007
1129
|
setConfig(config) {
|
|
@@ -1121,10 +1243,8 @@ var GanttEngine = class {
|
|
|
1121
1243
|
const today = toDate(/* @__PURE__ */ new Date());
|
|
1122
1244
|
return { start: today, end: addDays(today, 30) };
|
|
1123
1245
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
end: new Date(Math.max(...dates.map((d) => d.getTime())))
|
|
1127
|
-
};
|
|
1246
|
+
const extent = dateExtent(dates);
|
|
1247
|
+
return extent ?? { start: dates[0], end: dates[0] };
|
|
1128
1248
|
}
|
|
1129
1249
|
getTimeScale() {
|
|
1130
1250
|
const range = this.getDateRange();
|
|
@@ -1289,12 +1409,14 @@ function createGanttEngine(options = {}) {
|
|
|
1289
1409
|
0 && (module.exports = {
|
|
1290
1410
|
DAY_MS,
|
|
1291
1411
|
DEFAULT_HOUR_COLORS,
|
|
1412
|
+
DEFAULT_RESOURCE_COLORS,
|
|
1292
1413
|
DEFAULT_TASK_COLORS,
|
|
1293
1414
|
EDITOR_COLOR_OPTIONS,
|
|
1294
1415
|
GanttEngine,
|
|
1295
1416
|
HOUR_MS,
|
|
1296
1417
|
OWNER_COLOR_PALETTE,
|
|
1297
1418
|
RESOURCE_COLOR_PALETTE,
|
|
1419
|
+
RESOURCE_EDITOR_COLOR_OPTIONS,
|
|
1298
1420
|
addDays,
|
|
1299
1421
|
addHours,
|
|
1300
1422
|
addPlannedDuration,
|
|
@@ -1305,8 +1427,10 @@ function createGanttEngine(options = {}) {
|
|
|
1305
1427
|
computeLayout,
|
|
1306
1428
|
computeResourceLayout,
|
|
1307
1429
|
computeTimeScale,
|
|
1430
|
+
computeVisibleWindow,
|
|
1308
1431
|
computeWorkload,
|
|
1309
1432
|
createGanttEngine,
|
|
1433
|
+
dateExtent,
|
|
1310
1434
|
defaultConfig,
|
|
1311
1435
|
diffDays,
|
|
1312
1436
|
diffHours,
|
|
@@ -1316,15 +1440,18 @@ function createGanttEngine(options = {}) {
|
|
|
1316
1440
|
hasTimeComponent,
|
|
1317
1441
|
inclusiveDays,
|
|
1318
1442
|
isValidDate,
|
|
1443
|
+
mergeGanttConfig,
|
|
1319
1444
|
mergeTaskPatch,
|
|
1320
1445
|
normalizeLinks,
|
|
1321
1446
|
plannedDurationBetween,
|
|
1447
|
+
resolveGanttConfig,
|
|
1322
1448
|
resolveResourceColor,
|
|
1323
1449
|
resolveUsageColor,
|
|
1324
1450
|
resolveUsageTimes,
|
|
1325
1451
|
resultInvalidDate,
|
|
1326
1452
|
scheduleByDependencies,
|
|
1327
1453
|
shiftTask,
|
|
1454
|
+
sliceRangeItems,
|
|
1328
1455
|
startOfDay,
|
|
1329
1456
|
subtractPlannedDuration,
|
|
1330
1457
|
toDate,
|