UNPKG

@pisell/pisellos

Version:

一个可扩展的前端模块化SDK框架,支持插件系统

221 lines (219 loc) 10.5 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/solution/BookingByStep/utils/timeslots.ts var timeslots_exports = {}; __export(timeslots_exports, { calculateResourceAvailableTime: () => calculateResourceAvailableTime, filterConditionTimeSlots: () => filterConditionTimeSlots, findFastestAvailableResource: () => findFastestAvailableResource }); module.exports = __toCommonJS(timeslots_exports); var import_dayjs = __toESM(require("dayjs")); function calculateResourceAvailableTime({ resource, timeSlots, currentCapacity = 1 }) { const matchingTimes = resource.times.filter((time) => { return (0, import_dayjs.default)(time.start_at).isSame((0, import_dayjs.default)(timeSlots.start_at), "day"); }); if (matchingTimes.length === 0) return 0; const overlaps = []; for (const time of matchingTimes) { const overlapStart = (0, import_dayjs.default)(time.start_at).isAfter((0, import_dayjs.default)(timeSlots.start_at)) ? (0, import_dayjs.default)(time.start_at) : (0, import_dayjs.default)(timeSlots.start_at); const overlapEnd = (0, import_dayjs.default)(time.end_at).isBefore((0, import_dayjs.default)(timeSlots.end_at)) ? (0, import_dayjs.default)(time.end_at) : (0, import_dayjs.default)(timeSlots.end_at); if (overlapStart.isBefore(overlapEnd)) { overlaps.push({ start: overlapStart, end: overlapEnd }); } } if (overlaps.length === 0) return 0; overlaps.sort((a, b) => a.start.diff(b.start)); const merged = []; let current = overlaps[0]; for (let i = 1; i < overlaps.length; i++) { const next = overlaps[i]; if (current.end.isSameOrAfter(next.start)) { current.end = current.end.isAfter(next.end) ? current.end : next.end; } else { merged.push(current); current = next; } } merged.push(current); let totalAvailableMinutes = 0; for (const segment of merged) { totalAvailableMinutes += segment.end.diff(segment.start, "minute"); } return totalAvailableMinutes; } function findFastestAvailableResource({ resources, currentCapacity = 1, countMap = {} }) { var _a, _b, _c; const currentTime = (0, import_dayjs.default)(); let fastestTime = null; let fastestResources = []; console.log("[TimeslotUtils] 查找最快可用资源:", { currentTime: currentTime.format("YYYY-MM-DD HH:mm:ss"), resourceCount: resources.length, currentCapacity, countMap }); for (const resource of resources) { const todayTimes = resource.times.filter((time) => { const isToday = (0, import_dayjs.default)(time.start_at).isSame(currentTime, "day"); const isStillWorking = (0, import_dayjs.default)(time.end_at).isAfter(currentTime); return isToday && isStillWorking; }); if (todayTimes.length === 0) { console.log(`[TimeslotUtils] 资源 ${resource.id}(${resource.main_field}) 今日无可用时间段`); continue; } for (const time of todayTimes) { const workStartTime = (0, import_dayjs.default)(time.start_at); const workEndTime = (0, import_dayjs.default)(time.end_at); let nextAvailableTime = currentTime.isBefore(workStartTime) ? workStartTime : currentTime; console.log(`[TimeslotUtils] 检查资源 ${resource.id}(${resource.main_field}):`, { workTime: `${workStartTime.format("HH:mm")}-${workEndTime.format("HH:mm")}`, checkStartTime: nextAvailableTime.format("HH:mm:ss"), eventCount: ((_a = time.event_list) == null ? void 0 : _a.length) || 0 }); const relevantEvents = ((_b = time.event_list) == null ? void 0 : _b.filter((event) => { const eventEnd = (0, import_dayjs.default)(event.end_at); return eventEnd.isAfter(nextAvailableTime); })) || []; relevantEvents.sort( (a, b) => (0, import_dayjs.default)(a.start_at).diff((0, import_dayjs.default)(b.start_at)) ); let finalAvailableTime = nextAvailableTime; for (const event of relevantEvents) { const eventStart = (0, import_dayjs.default)(event.start_at); const eventEnd = (0, import_dayjs.default)(event.end_at); console.log(`[TimeslotUtils] 检查事件冲突:`, { resourceId: resource.id, eventTime: `${eventStart.format("HH:mm")}-${eventEnd.format("HH:mm")}`, checkTime: finalAvailableTime.format("HH:mm:ss"), pax: event.pax || 1 }); if (resource.resourceType === "single" || (resource.capacity || 1) === 1) { if (finalAvailableTime.isBefore(eventEnd) && eventStart.isBefore(finalAvailableTime.add(30, "minute"))) { finalAvailableTime = eventEnd; console.log(`[TimeslotUtils] 发现时间冲突,调整到: ${finalAvailableTime.format("HH:mm:ss")}`); } } else { const totalCapacity = resource.capacity || 0; const currentUsedCapacity = countMap[resource.id] || 0; const eventUsedCapacity = event.pax || 1; if (finalAvailableTime.isBefore(eventEnd) && eventStart.isBefore(finalAvailableTime.add(30, "minute"))) { const totalRequiredCapacity = currentUsedCapacity + currentCapacity + eventUsedCapacity; if (totalRequiredCapacity > totalCapacity) { finalAvailableTime = eventEnd; console.log(`[TimeslotUtils] 容量不足,调整到: ${finalAvailableTime.format("HH:mm:ss")}`); } } } } if (finalAvailableTime.isAfter(workEndTime)) { console.log(`[TimeslotUtils] 资源 ${resource.id} 可用时间超出工作时间,跳过`); continue; } console.log(`[TimeslotUtils] 资源 ${resource.id}(${resource.main_field}) 最快可用时间: ${finalAvailableTime.format("HH:mm:ss")}`); if (!fastestTime || finalAvailableTime.isBefore(fastestTime)) { fastestTime = finalAvailableTime; fastestResources = [resource]; console.log(`[TimeslotUtils] 更新最快时间: ${fastestTime.format("HH:mm:ss")}, 资源: ${resource.main_field}`); } else if (finalAvailableTime.isSame(fastestTime)) { fastestResources.push(resource); console.log(`[TimeslotUtils] 添加相同时间资源: ${resource.main_field}`); } break; } } if (!fastestTime || fastestResources.length === 0) { console.log("[TimeslotUtils] 未找到可用资源"); return null; } console.log(`[TimeslotUtils] 找到 ${fastestResources.length} 个最快可用资源,时间: ${fastestTime.format("HH:mm:ss")}`); if (fastestResources.length === 1) { console.log(`[TimeslotUtils] 返回唯一最快资源: ${fastestResources[0].main_field}`); return fastestResources[0]; } let selectedResource = fastestResources[0]; let maxIdleTime = 0; console.log(`[TimeslotUtils] 比较 ${fastestResources.length} 个资源的空闲时间:`); for (const resource of fastestResources) { const workingTime = resource.times.find((time) => { const isToday = (0, import_dayjs.default)(time.start_at).isSame(fastestTime, "day"); const isStillWorking = (0, import_dayjs.default)(time.end_at).isAfter(fastestTime); return isToday && isStillWorking; }); if (!workingTime) continue; const workEndTime = (0, import_dayjs.default)(workingTime.end_at); let totalIdleTime = workEndTime.diff(fastestTime, "minute"); const relevantEvents = ((_c = workingTime.event_list) == null ? void 0 : _c.filter((event) => { const eventStart = (0, import_dayjs.default)(event.start_at); const eventEnd = (0, import_dayjs.default)(event.end_at); return eventEnd.isAfter(fastestTime) && eventStart.isAfter(fastestTime); })) || []; for (const event of relevantEvents) { const eventStart = (0, import_dayjs.default)(event.start_at); const eventEnd = (0, import_dayjs.default)(event.end_at); const eventDuration = eventEnd.diff(eventStart, "minute"); totalIdleTime -= eventDuration; } console.log(`[TimeslotUtils] 资源 ${resource.id}(${resource.main_field}):`, { 工作结束时间: workEndTime.format("HH:mm"), 总工作时长: workEndTime.diff(fastestTime, "minute") + "分钟", 预约占用时长: workEndTime.diff(fastestTime, "minute") - totalIdleTime + "分钟", 实际空闲时长: totalIdleTime + "分钟" }); if (totalIdleTime > maxIdleTime) { maxIdleTime = totalIdleTime; selectedResource = resource; console.log(`[TimeslotUtils] 更新最佳选择: ${resource.main_field} (空闲${totalIdleTime}分钟)`); } } console.log(`[TimeslotUtils] 最终选择资源: ${selectedResource.main_field} (最长空闲${maxIdleTime}分钟)`); return selectedResource; } function filterConditionTimeSlots(times, startTime, endTime) { return times.filter((n) => { return !(0, import_dayjs.default)(n.start_at).isAfter((0, import_dayjs.default)(startTime)) && !(0, import_dayjs.default)(n.end_at).isBefore((0, import_dayjs.default)(endTime)); }); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { calculateResourceAvailableTime, filterConditionTimeSlots, findFastestAvailableResource });