@pisell/pisellos 1.0.57 → 1.0.58
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.
|
@@ -95,71 +95,122 @@ export function findFastestAvailableResource(_ref2) {
|
|
|
95
95
|
var currentTime = dayjs();
|
|
96
96
|
var fastestTime = null;
|
|
97
97
|
var fastestResources = [];
|
|
98
|
+
console.log('[TimeslotUtils] 查找最快可用资源:', {
|
|
99
|
+
currentTime: currentTime.format('YYYY-MM-DD HH:mm:ss'),
|
|
100
|
+
resourceCount: resources.length,
|
|
101
|
+
currentCapacity: currentCapacity,
|
|
102
|
+
countMap: countMap
|
|
103
|
+
});
|
|
98
104
|
|
|
99
105
|
// 遍历所有资源,找到最快可用的时间点
|
|
100
106
|
var _iterator2 = _createForOfIteratorHelper(resources),
|
|
101
107
|
_step2;
|
|
102
108
|
try {
|
|
103
109
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
104
|
-
var
|
|
105
|
-
//
|
|
106
|
-
var todayTimes =
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
// 按开始时间排序
|
|
112
|
-
todayTimes.sort(function (a, b) {
|
|
113
|
-
return dayjs(a.start_at).diff(dayjs(b.start_at));
|
|
110
|
+
var resource = _step2.value;
|
|
111
|
+
// 获取资源当天且还在工作时间内的时间段
|
|
112
|
+
var todayTimes = resource.times.filter(function (time) {
|
|
113
|
+
var isToday = dayjs(time.start_at).isSame(currentTime, 'day');
|
|
114
|
+
var isStillWorking = dayjs(time.end_at).isAfter(currentTime);
|
|
115
|
+
return isToday && isStillWorking;
|
|
114
116
|
});
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
if (todayTimes.length === 0) {
|
|
118
|
+
console.log("[TimeslotUtils] \u8D44\u6E90 ".concat(resource.id, "(").concat(resource.main_field, ") \u4ECA\u65E5\u65E0\u53EF\u7528\u65F6\u95F4\u6BB5"));
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
117
121
|
var _iterator3 = _createForOfIteratorHelper(todayTimes),
|
|
118
122
|
_step3;
|
|
119
123
|
try {
|
|
120
124
|
var _loop = function _loop() {
|
|
125
|
+
var _time$event_list, _time$event_list2;
|
|
121
126
|
var time = _step3.value;
|
|
122
|
-
var
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
127
|
+
var workStartTime = dayjs(time.start_at);
|
|
128
|
+
var workEndTime = dayjs(time.end_at);
|
|
129
|
+
|
|
130
|
+
// 确定检查的起始时间(当前时间 vs 工作开始时间)
|
|
131
|
+
var nextAvailableTime = currentTime.isBefore(workStartTime) ? workStartTime : currentTime;
|
|
132
|
+
console.log("[TimeslotUtils] \u68C0\u67E5\u8D44\u6E90 ".concat(resource.id, "(").concat(resource.main_field, "):"), {
|
|
133
|
+
workTime: "".concat(workStartTime.format('HH:mm'), "-").concat(workEndTime.format('HH:mm')),
|
|
134
|
+
checkStartTime: nextAvailableTime.format('HH:mm:ss'),
|
|
135
|
+
eventCount: ((_time$event_list = time.event_list) === null || _time$event_list === void 0 ? void 0 : _time$event_list.length) || 0
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// 获取所有影响的预约事件(当前时间之后的)
|
|
139
|
+
var relevantEvents = ((_time$event_list2 = time.event_list) === null || _time$event_list2 === void 0 ? void 0 : _time$event_list2.filter(function (event) {
|
|
140
|
+
var eventEnd = dayjs(event.end_at);
|
|
141
|
+
return eventEnd.isAfter(nextAvailableTime);
|
|
142
|
+
})) || [];
|
|
143
|
+
|
|
144
|
+
// 按开始时间排序
|
|
145
|
+
relevantEvents.sort(function (a, b) {
|
|
146
|
+
return dayjs(a.start_at).diff(dayjs(b.start_at));
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// 检查从 nextAvailableTime 开始的可用性
|
|
150
|
+
var finalAvailableTime = nextAvailableTime;
|
|
151
|
+
var _iterator4 = _createForOfIteratorHelper(relevantEvents),
|
|
152
|
+
_step4;
|
|
153
|
+
try {
|
|
154
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
155
|
+
var event = _step4.value;
|
|
156
|
+
var eventStart = dayjs(event.start_at);
|
|
157
|
+
var eventEnd = dayjs(event.end_at);
|
|
158
|
+
console.log("[TimeslotUtils] \u68C0\u67E5\u4E8B\u4EF6\u51B2\u7A81:", {
|
|
159
|
+
resourceId: resource.id,
|
|
160
|
+
eventTime: "".concat(eventStart.format('HH:mm'), "-").concat(eventEnd.format('HH:mm')),
|
|
161
|
+
checkTime: finalAvailableTime.format('HH:mm:ss'),
|
|
162
|
+
pax: event.pax || 1
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// 检查资源类型和容量
|
|
166
|
+
if (resource.resourceType === 'single' || (resource.capacity || 1) === 1) {
|
|
167
|
+
// 单人预约资源:检查时间冲突
|
|
168
|
+
if (finalAvailableTime.isBefore(eventEnd) && eventStart.isBefore(finalAvailableTime.add(30, 'minute'))) {
|
|
169
|
+
// 有冲突,使用事件结束时间
|
|
170
|
+
finalAvailableTime = eventEnd;
|
|
171
|
+
console.log("[TimeslotUtils] \u53D1\u73B0\u65F6\u95F4\u51B2\u7A81\uFF0C\u8C03\u6574\u5230: ".concat(finalAvailableTime.format('HH:mm:ss')));
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
// 多人预约资源:检查容量
|
|
175
|
+
var totalCapacity = resource.capacity || 0;
|
|
176
|
+
var currentUsedCapacity = countMap[resource.id] || 0;
|
|
177
|
+
var eventUsedCapacity = event.pax || 1;
|
|
178
|
+
|
|
179
|
+
// 如果在事件时间范围内,检查容量是否足够
|
|
180
|
+
if (finalAvailableTime.isBefore(eventEnd) && eventStart.isBefore(finalAvailableTime.add(30, 'minute'))) {
|
|
181
|
+
var totalRequiredCapacity = currentUsedCapacity + currentCapacity + eventUsedCapacity;
|
|
182
|
+
if (totalRequiredCapacity > totalCapacity) {
|
|
183
|
+
// 容量不足,使用事件结束时间
|
|
184
|
+
finalAvailableTime = eventEnd;
|
|
185
|
+
console.log("[TimeslotUtils] \u5BB9\u91CF\u4E0D\u8DB3\uFF0C\u8C03\u6574\u5230: ".concat(finalAvailableTime.format('HH:mm:ss')));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
159
188
|
}
|
|
160
|
-
return 1; // break
|
|
161
189
|
}
|
|
190
|
+
|
|
191
|
+
// 确保可用时间在工作时间内
|
|
192
|
+
} catch (err) {
|
|
193
|
+
_iterator4.e(err);
|
|
194
|
+
} finally {
|
|
195
|
+
_iterator4.f();
|
|
196
|
+
}
|
|
197
|
+
if (finalAvailableTime.isAfter(workEndTime)) {
|
|
198
|
+
console.log("[TimeslotUtils] \u8D44\u6E90 ".concat(resource.id, " \u53EF\u7528\u65F6\u95F4\u8D85\u51FA\u5DE5\u4F5C\u65F6\u95F4\uFF0C\u8DF3\u8FC7"));
|
|
199
|
+
return 0; // continue
|
|
162
200
|
}
|
|
201
|
+
console.log("[TimeslotUtils] \u8D44\u6E90 ".concat(resource.id, "(").concat(resource.main_field, ") \u6700\u5FEB\u53EF\u7528\u65F6\u95F4: ").concat(finalAvailableTime.format('HH:mm:ss')));
|
|
202
|
+
|
|
203
|
+
// 更新最快可用时间和资源
|
|
204
|
+
if (!fastestTime || finalAvailableTime.isBefore(fastestTime)) {
|
|
205
|
+
fastestTime = finalAvailableTime;
|
|
206
|
+
fastestResources = [resource];
|
|
207
|
+
console.log("[TimeslotUtils] \u66F4\u65B0\u6700\u5FEB\u65F6\u95F4: ".concat(fastestTime.format('HH:mm:ss'), ", \u8D44\u6E90: ").concat(resource.main_field));
|
|
208
|
+
} else if (finalAvailableTime.isSame(fastestTime)) {
|
|
209
|
+
fastestResources.push(resource);
|
|
210
|
+
console.log("[TimeslotUtils] \u6DFB\u52A0\u76F8\u540C\u65F6\u95F4\u8D44\u6E90: ".concat(resource.main_field));
|
|
211
|
+
}
|
|
212
|
+
return 1; // break
|
|
213
|
+
// 每个资源只需要计算一次
|
|
163
214
|
},
|
|
164
215
|
_ret;
|
|
165
216
|
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
@@ -180,31 +231,22 @@ export function findFastestAvailableResource(_ref2) {
|
|
|
180
231
|
} finally {
|
|
181
232
|
_iterator2.f();
|
|
182
233
|
}
|
|
183
|
-
if (!fastestTime || fastestResources.length === 0)
|
|
234
|
+
if (!fastestTime || fastestResources.length === 0) {
|
|
235
|
+
console.log('[TimeslotUtils] 未找到可用资源');
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
console.log("[TimeslotUtils] \u627E\u5230 ".concat(fastestResources.length, " \u4E2A\u6700\u5FEB\u53EF\u7528\u8D44\u6E90\uFF0C\u65F6\u95F4: ").concat(fastestTime.format('HH:mm:ss')));
|
|
184
239
|
|
|
185
240
|
// 如果只有一个最快可用的资源,直接返回
|
|
186
|
-
if (fastestResources.length === 1)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
var maxIdleTime = 0;
|
|
190
|
-
var selectedResource = null;
|
|
191
|
-
for (var _i2 = 0, _fastestResources = fastestResources; _i2 < _fastestResources.length; _i2++) {
|
|
192
|
-
var resource = _fastestResources[_i2];
|
|
193
|
-
var idleTime = calculateResourceAvailableTime({
|
|
194
|
-
resource: resource,
|
|
195
|
-
timeSlots: {
|
|
196
|
-
start_time: fastestTime.format('HH:mm'),
|
|
197
|
-
end_time: fastestTime.format('HH:mm'),
|
|
198
|
-
start_at: fastestTime,
|
|
199
|
-
end_at: fastestTime
|
|
200
|
-
},
|
|
201
|
-
currentCapacity: (countMap[resource.id] || 0) + currentCapacity
|
|
202
|
-
});
|
|
203
|
-
if (idleTime > maxIdleTime) {
|
|
204
|
-
maxIdleTime = idleTime;
|
|
205
|
-
selectedResource = resource;
|
|
206
|
-
}
|
|
241
|
+
if (fastestResources.length === 1) {
|
|
242
|
+
console.log("[TimeslotUtils] \u8FD4\u56DE\u552F\u4E00\u6700\u5FEB\u8D44\u6E90: ".concat(fastestResources[0].main_field));
|
|
243
|
+
return fastestResources[0];
|
|
207
244
|
}
|
|
245
|
+
|
|
246
|
+
// 如果有多个最快可用的资源,选择第一个或根据其他逻辑选择
|
|
247
|
+
// 这里简化处理,直接返回第一个
|
|
248
|
+
var selectedResource = fastestResources[0];
|
|
249
|
+
console.log("[TimeslotUtils] \u8FD4\u56DE\u591A\u4E2A\u8D44\u6E90\u4E2D\u7684\u7B2C\u4E00\u4E2A: ".concat(selectedResource.main_field));
|
|
208
250
|
return selectedResource;
|
|
209
251
|
}
|
|
210
252
|
|
|
@@ -83,74 +83,93 @@ function findFastestAvailableResource({
|
|
|
83
83
|
const currentTime = (0, import_dayjs.default)();
|
|
84
84
|
let fastestTime = null;
|
|
85
85
|
let fastestResources = [];
|
|
86
|
+
console.log("[TimeslotUtils] 查找最快可用资源:", {
|
|
87
|
+
currentTime: currentTime.format("YYYY-MM-DD HH:mm:ss"),
|
|
88
|
+
resourceCount: resources.length,
|
|
89
|
+
currentCapacity,
|
|
90
|
+
countMap
|
|
91
|
+
});
|
|
86
92
|
for (const resource of resources) {
|
|
87
93
|
const todayTimes = resource.times.filter((time) => {
|
|
88
|
-
|
|
94
|
+
const isToday = (0, import_dayjs.default)(time.start_at).isSame(currentTime, "day");
|
|
95
|
+
const isStillWorking = (0, import_dayjs.default)(time.end_at).isAfter(currentTime);
|
|
96
|
+
return isToday && isStillWorking;
|
|
89
97
|
});
|
|
90
|
-
if (todayTimes.length === 0)
|
|
98
|
+
if (todayTimes.length === 0) {
|
|
99
|
+
console.log(`[TimeslotUtils] 资源 ${resource.id}(${resource.main_field}) 今日无可用时间段`);
|
|
91
100
|
continue;
|
|
92
|
-
|
|
93
|
-
return (0, import_dayjs.default)(a.start_at).diff((0, import_dayjs.default)(b.start_at));
|
|
94
|
-
});
|
|
101
|
+
}
|
|
95
102
|
for (const time of todayTimes) {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
const workStartTime = (0, import_dayjs.default)(time.start_at);
|
|
104
|
+
const workEndTime = (0, import_dayjs.default)(time.end_at);
|
|
105
|
+
let nextAvailableTime = currentTime.isBefore(workStartTime) ? workStartTime : currentTime;
|
|
106
|
+
console.log(`[TimeslotUtils] 检查资源 ${resource.id}(${resource.main_field}):`, {
|
|
107
|
+
workTime: `${workStartTime.format("HH:mm")}-${workEndTime.format("HH:mm")}`,
|
|
108
|
+
checkStartTime: nextAvailableTime.format("HH:mm:ss"),
|
|
109
|
+
eventCount: ((_a = time.event_list) == null ? void 0 : _a.length) || 0
|
|
110
|
+
});
|
|
111
|
+
const relevantEvents = ((_b = time.event_list) == null ? void 0 : _b.filter((event) => {
|
|
112
|
+
const eventEnd = (0, import_dayjs.default)(event.end_at);
|
|
113
|
+
return eventEnd.isAfter(nextAvailableTime);
|
|
114
|
+
})) || [];
|
|
115
|
+
relevantEvents.sort(
|
|
116
|
+
(a, b) => (0, import_dayjs.default)(a.start_at).diff((0, import_dayjs.default)(b.start_at))
|
|
117
|
+
);
|
|
118
|
+
let finalAvailableTime = nextAvailableTime;
|
|
119
|
+
for (const event of relevantEvents) {
|
|
120
|
+
const eventStart = (0, import_dayjs.default)(event.start_at);
|
|
121
|
+
const eventEnd = (0, import_dayjs.default)(event.end_at);
|
|
122
|
+
console.log(`[TimeslotUtils] 检查事件冲突:`, {
|
|
123
|
+
resourceId: resource.id,
|
|
124
|
+
eventTime: `${eventStart.format("HH:mm")}-${eventEnd.format("HH:mm")}`,
|
|
125
|
+
checkTime: finalAvailableTime.format("HH:mm:ss"),
|
|
126
|
+
pax: event.pax || 1
|
|
102
127
|
});
|
|
103
|
-
if (
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
} else if (startTime.isBefore(fastestTime)) {
|
|
108
|
-
fastestTime = startTime;
|
|
109
|
-
fastestResources = [resource];
|
|
128
|
+
if (resource.resourceType === "single" || (resource.capacity || 1) === 1) {
|
|
129
|
+
if (finalAvailableTime.isBefore(eventEnd) && eventStart.isBefore(finalAvailableTime.add(30, "minute"))) {
|
|
130
|
+
finalAvailableTime = eventEnd;
|
|
131
|
+
console.log(`[TimeslotUtils] 发现时间冲突,调整到: ${finalAvailableTime.format("HH:mm:ss")}`);
|
|
110
132
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
fastestTime = startTime;
|
|
122
|
-
fastestResources.push(resource);
|
|
123
|
-
} else if (startTime.isBefore(fastestTime)) {
|
|
124
|
-
fastestTime = startTime;
|
|
125
|
-
fastestResources = [resource];
|
|
133
|
+
} else {
|
|
134
|
+
const totalCapacity = resource.capacity || 0;
|
|
135
|
+
const currentUsedCapacity = countMap[resource.id] || 0;
|
|
136
|
+
const eventUsedCapacity = event.pax || 1;
|
|
137
|
+
if (finalAvailableTime.isBefore(eventEnd) && eventStart.isBefore(finalAvailableTime.add(30, "minute"))) {
|
|
138
|
+
const totalRequiredCapacity = currentUsedCapacity + currentCapacity + eventUsedCapacity;
|
|
139
|
+
if (totalRequiredCapacity > totalCapacity) {
|
|
140
|
+
finalAvailableTime = eventEnd;
|
|
141
|
+
console.log(`[TimeslotUtils] 容量不足,调整到: ${finalAvailableTime.format("HH:mm:ss")}`);
|
|
142
|
+
}
|
|
126
143
|
}
|
|
127
|
-
break;
|
|
128
144
|
}
|
|
129
145
|
}
|
|
146
|
+
if (finalAvailableTime.isAfter(workEndTime)) {
|
|
147
|
+
console.log(`[TimeslotUtils] 资源 ${resource.id} 可用时间超出工作时间,跳过`);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
console.log(`[TimeslotUtils] 资源 ${resource.id}(${resource.main_field}) 最快可用时间: ${finalAvailableTime.format("HH:mm:ss")}`);
|
|
151
|
+
if (!fastestTime || finalAvailableTime.isBefore(fastestTime)) {
|
|
152
|
+
fastestTime = finalAvailableTime;
|
|
153
|
+
fastestResources = [resource];
|
|
154
|
+
console.log(`[TimeslotUtils] 更新最快时间: ${fastestTime.format("HH:mm:ss")}, 资源: ${resource.main_field}`);
|
|
155
|
+
} else if (finalAvailableTime.isSame(fastestTime)) {
|
|
156
|
+
fastestResources.push(resource);
|
|
157
|
+
console.log(`[TimeslotUtils] 添加相同时间资源: ${resource.main_field}`);
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
130
160
|
}
|
|
131
161
|
}
|
|
132
|
-
if (!fastestTime || fastestResources.length === 0)
|
|
162
|
+
if (!fastestTime || fastestResources.length === 0) {
|
|
163
|
+
console.log("[TimeslotUtils] 未找到可用资源");
|
|
133
164
|
return null;
|
|
134
|
-
|
|
165
|
+
}
|
|
166
|
+
console.log(`[TimeslotUtils] 找到 ${fastestResources.length} 个最快可用资源,时间: ${fastestTime.format("HH:mm:ss")}`);
|
|
167
|
+
if (fastestResources.length === 1) {
|
|
168
|
+
console.log(`[TimeslotUtils] 返回唯一最快资源: ${fastestResources[0].main_field}`);
|
|
135
169
|
return fastestResources[0];
|
|
136
|
-
let maxIdleTime = 0;
|
|
137
|
-
let selectedResource = null;
|
|
138
|
-
for (const resource of fastestResources) {
|
|
139
|
-
const idleTime = calculateResourceAvailableTime({
|
|
140
|
-
resource,
|
|
141
|
-
timeSlots: {
|
|
142
|
-
start_time: fastestTime.format("HH:mm"),
|
|
143
|
-
end_time: fastestTime.format("HH:mm"),
|
|
144
|
-
start_at: fastestTime,
|
|
145
|
-
end_at: fastestTime
|
|
146
|
-
},
|
|
147
|
-
currentCapacity: (countMap[resource.id] || 0) + currentCapacity
|
|
148
|
-
});
|
|
149
|
-
if (idleTime > maxIdleTime) {
|
|
150
|
-
maxIdleTime = idleTime;
|
|
151
|
-
selectedResource = resource;
|
|
152
|
-
}
|
|
153
170
|
}
|
|
171
|
+
const selectedResource = fastestResources[0];
|
|
172
|
+
console.log(`[TimeslotUtils] 返回多个资源中的第一个: ${selectedResource.main_field}`);
|
|
154
173
|
return selectedResource;
|
|
155
174
|
}
|
|
156
175
|
function filterConditionTimeSlots(times, startTime, endTime) {
|