@pisell/pisellos 1.0.113 → 1.0.115

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.
@@ -674,7 +674,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
674
674
  // 收集该折扣卡适用的商品(排除被其他专属折扣卡占用的商品)
675
675
  var applicableProducts = [];
676
676
  sortedFlattenedList.forEach(function (flatItem) {
677
- var _flatItem$parentProdu2;
677
+ var _flatItem$parentProdu2, _product$price, _ref5, _flatItem$original_pr;
678
678
  // 🔥 检查该商品是否被其他专属折扣卡占用
679
679
  var occupyingDiscountId = occupiedItems.get(flatItem._id);
680
680
  if (occupyingDiscountId !== undefined && occupyingDiscountId !== discount.id) {
@@ -700,10 +700,14 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
700
700
  // 对于 bundle 子商品,quantity 需要乘以主商品的购买数量
701
701
  var quantity = flatItem.type === 'main' ? product.quantity || 1 : (product.num || 1) * (((_flatItem$parentProdu2 = flatItem.parentProduct) === null || _flatItem$parentProdu2 === void 0 ? void 0 : _flatItem$parentProdu2.quantity) || 1);
702
702
 
703
+ // 对于主商品:使用 price
704
+ // 对于子商品:优先使用 flatItem.original_price,否则使用 flatItem.price
705
+ var originalAmount = flatItem.type === 'main' ? Number((_product$price = product.price) !== null && _product$price !== void 0 ? _product$price : 0) : Number((_ref5 = (_flatItem$original_pr = flatItem.original_price) !== null && _flatItem$original_pr !== void 0 ? _flatItem$original_pr : flatItem.price) !== null && _ref5 !== void 0 ? _ref5 : 0);
706
+
703
707
  // 传递 parentQuantity 用于差值处理时判断是否是真正的"数量为1"
704
708
  var productData = {
705
709
  productId: flatItem._id,
706
- amount: Number(product.price || 0),
710
+ amount: originalAmount,
707
711
  quantity: quantity
708
712
  };
709
713
 
@@ -946,8 +950,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
946
950
  var _product$discount_lis5, _product11, _product11$every;
947
951
  // 主商品:判断自身是否手动折扣
948
952
  isManualDiscount = typeof product.isManualDiscount === 'boolean' ? product.isManualDiscount : product.total != product.origin_total && (product.bundle || []).every(function (item) {
949
- var _ref5;
950
- return !((_ref5 = item.discount_list || []) !== null && _ref5 !== void 0 && _ref5.length);
953
+ var _ref6;
954
+ return !((_ref6 = item.discount_list || []) !== null && _ref6 !== void 0 && _ref6.length);
951
955
  }) && (!((_product$discount_lis5 = product.discount_list) !== null && _product$discount_lis5 !== void 0 && _product$discount_lis5.length) || ((_product11 = product) === null || _product11 === void 0 || (_product11 = _product11.discount_list) === null || _product11 === void 0 || (_product11$every = _product11.every) === null || _product11$every === void 0 ? void 0 : _product11$every.call(_product11, function (item) {
952
956
  return item.type === 'product';
953
957
  })));
@@ -957,8 +961,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
957
961
  if (parentProduct) {
958
962
  var _parentProduct$discou, _parentProduct$discou2, _parentProduct$discou3;
959
963
  isManualDiscount = typeof parentProduct.isManualDiscount === 'boolean' ? parentProduct.isManualDiscount : parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every(function (item) {
960
- var _ref6;
961
- return !((_ref6 = item.discount_list || []) !== null && _ref6 !== void 0 && _ref6.length);
964
+ var _ref7;
965
+ return !((_ref7 = item.discount_list || []) !== null && _ref7 !== void 0 && _ref7.length);
962
966
  }) && (!((_parentProduct$discou = parentProduct.discount_list) !== null && _parentProduct$discou !== void 0 && _parentProduct$discou.length) || (parentProduct === null || parentProduct === void 0 || (_parentProduct$discou2 = parentProduct.discount_list) === null || _parentProduct$discou2 === void 0 || (_parentProduct$discou3 = _parentProduct$discou2.every) === null || _parentProduct$discou3 === void 0 ? void 0 : _parentProduct$discou3.call(_parentProduct$discou2, function (item) {
963
967
  return item.type === 'product';
964
968
  })));
@@ -327,7 +327,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
327
327
  count: number;
328
328
  left: number;
329
329
  summaryCount: number;
330
- status: keyof TimeStatusMap;
330
+ status: "lots_of_space" | "filling_up_fast" | "sold_out";
331
331
  }[];
332
332
  /**
333
333
  * 找到多个资源的公共可用时间段
@@ -392,9 +392,3 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
392
392
  */
393
393
  getContactInfo(params: any): Promise<any>;
394
394
  }
395
- interface TimeStatusMap {
396
- lots_of_space: true;
397
- filling_up_fast: true;
398
- sold_out: true;
399
- }
400
- export {};
@@ -2208,12 +2208,22 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2208
2208
  }
2209
2209
  // 计算容量的辅助函数
2210
2210
  var calculateCapacityFromCartItems = function calculateCapacityFromCartItems(items) {
2211
+ var _items$0$_resourceOri;
2212
+ // 还需要增加一个判断,maxCapacity 必须是我单个人里选择的资源只有同一种的情况下才可以累加,否则单个账号都是 1
2213
+ var firstResource = (_items$0$_resourceOri = items[0]._resourceOrigin) === null || _items$0$_resourceOri === void 0 ? void 0 : _items$0$_resourceOri[0].id;
2214
+ var sameResourceLength = items.filter(function (item) {
2215
+ var _item$_resourceOrigin;
2216
+ return ((_item$_resourceOrigin = item._resourceOrigin) === null || _item$_resourceOrigin === void 0 ? void 0 : _item$_resourceOrigin[0].id) === firstResource;
2217
+ }).length;
2218
+ if (sameResourceLength !== items.length) {
2219
+ return 1;
2220
+ }
2211
2221
  return items.reduce(function (total, item) {
2212
2222
  return total + (getCapacityInfoByCartItem(item).currentCapacity || 0);
2213
2223
  }, 0);
2214
2224
  };
2215
2225
 
2216
- // 如果是多个预约,去要求出几个 holder 下最大的需求容量capacity
2226
+ // 如果是多个人预约,去要求出几个 holder 下最大的商品需求容量capacity
2217
2227
  var maxCapacity = 1;
2218
2228
  if (cartItems !== null && cartItems !== void 0 && cartItems[0].holder_id) {
2219
2229
  accountList.forEach(function (account) {
@@ -2368,6 +2378,16 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2368
2378
  }
2369
2379
  // 计算容量的辅助函数
2370
2380
  calculateCapacityFromCartItems = function calculateCapacityFromCartItems(items) {
2381
+ var _items$0$_resourceOri2;
2382
+ // 还需要增加一个判断,maxCapacity 必须是我单个人里选择的资源只有同一种的情况下才可以累加,否则单个账号都是 1
2383
+ var firstResource = (_items$0$_resourceOri2 = items[0]._resourceOrigin) === null || _items$0$_resourceOri2 === void 0 ? void 0 : _items$0$_resourceOri2[0].id;
2384
+ var sameResourceLength = items.filter(function (item) {
2385
+ var _item$_resourceOrigin2;
2386
+ return ((_item$_resourceOrigin2 = item._resourceOrigin) === null || _item$_resourceOrigin2 === void 0 ? void 0 : _item$_resourceOrigin2[0].id) === firstResource;
2387
+ }).length;
2388
+ if (sameResourceLength !== items.length) {
2389
+ return 1;
2390
+ }
2371
2391
  return items.reduce(function (total, item) {
2372
2392
  return total + (getCapacityInfoByCartItem(item).currentCapacity || 0);
2373
2393
  }, 0);
@@ -2674,7 +2694,6 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2674
2694
  value: function getTimeslotBySchedule(_ref11) {
2675
2695
  var _this$store$currentPr2,
2676
2696
  _targetProductData$pr,
2677
- _targetProductData$pr2,
2678
2697
  _this15 = this;
2679
2698
  var date = _ref11.date,
2680
2699
  scheduleIds = _ref11.scheduleIds,
@@ -2713,29 +2732,35 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2713
2732
  if (!aIsCombined && bIsCombined) return -1;
2714
2733
  return 0;
2715
2734
  });
2716
-
2717
- // 找到当前商品下第一个启用的资源id
2718
- var firstEnabledResourceId = targetProductData === null || targetProductData === void 0 || (_targetProductData$pr = targetProductData.product_resource) === null || _targetProductData$pr === void 0 || (_targetProductData$pr = _targetProductData$pr.resources) === null || _targetProductData$pr === void 0 || (_targetProductData$pr = _targetProductData$pr.find(function (n) {
2735
+ var enabledResourceTypeConfigs = (targetProductData === null || targetProductData === void 0 || (_targetProductData$pr = targetProductData.product_resource) === null || _targetProductData$pr === void 0 || (_targetProductData$pr = _targetProductData$pr.resources) === null || _targetProductData$pr === void 0 ? void 0 : _targetProductData$pr.filter(function (n) {
2719
2736
  return n.status === 1;
2720
- })) === null || _targetProductData$pr === void 0 ? void 0 : _targetProductData$pr.id;
2721
- var firstEnabledResourceConfig = targetProductData === null || targetProductData === void 0 || (_targetProductData$pr2 = targetProductData.product_resource) === null || _targetProductData$pr2 === void 0 || (_targetProductData$pr2 = _targetProductData$pr2.resources) === null || _targetProductData$pr2 === void 0 ? void 0 : _targetProductData$pr2.find(function (n) {
2722
- return n.status === 1 && n.id === firstEnabledResourceId;
2723
- });
2724
- var isMultipleBooking = (firstEnabledResourceConfig === null || firstEnabledResourceConfig === void 0 ? void 0 : firstEnabledResourceConfig.type) === 'multiple';
2737
+ })) || [];
2738
+ var resourceTypeConfigById = new Map(enabledResourceTypeConfigs.map(function (n) {
2739
+ return [n.id, n];
2740
+ }));
2741
+
2725
2742
  // 计算每个日程切片下日程可用的资源的容量总和
2726
2743
  var formatScheduleTimeSlots = scheduleTimeSlots.map(function (item) {
2727
2744
  // 用来计算资源的可使用情况,针对单个schedule 时间片
2728
2745
  var resourcesUseableMap = {};
2729
- var count = 0;
2730
- var bookingLeft = 0;
2731
- var summaryCount = 0;
2732
- var summaryConfigCount = 0;
2746
+ var statsByResourceType = {};
2747
+ enabledResourceTypeConfigs.forEach(function (cfg) {
2748
+ statsByResourceType[cfg.id] = {
2749
+ count: 0,
2750
+ left: 0,
2751
+ summaryCount: 0,
2752
+ summaryConfigCount: 0
2753
+ };
2754
+ });
2755
+
2733
2756
  // 遍历所有资源
2734
2757
  allProductResources === null || allProductResources === void 0 || allProductResources.forEach(function (m) {
2758
+ var currentResourceTypeConfig = resourceTypeConfigById.get(m.form_id);
2759
+ if (!currentResourceTypeConfig) return;
2760
+
2735
2761
  // 遍历所有资源的上工时间片
2736
- var currentResourcesCount = 0;
2737
- var currentResourcesSummaryCount = 0;
2738
- var currentResourcesTimeSlotCanUsedArr = [];
2762
+ var currentResourceMaxRemainingCapacity = 0;
2763
+ var isAllTimeSlicesUsable = true;
2739
2764
  // m.times 需要做个过滤,假设 timeSlice.start_at 是 09:30 timeSlice.end_at 是 11:30
2740
2765
  // time 是 time.start_at = 2025-05-26 10:30, time.end_at = 2025-05-26 12:30
2741
2766
  // 需要判断 time 的开始结束时间 是否包含timeSlice的开始结束时间
@@ -2751,6 +2776,18 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2751
2776
  if (mTimes.length === 0) {
2752
2777
  return;
2753
2778
  }
2779
+
2780
+ // 统计该资源类型在这个时间片的“配置容量”(无占用),只统计上工的资源
2781
+ if (!m.onlyComputed) {
2782
+ var _currentStats = statsByResourceType[m.form_id] || {
2783
+ count: 0,
2784
+ left: 0,
2785
+ summaryCount: 0,
2786
+ summaryConfigCount: 0
2787
+ };
2788
+ if (currentResourceTypeConfig.type === 'multiple') _currentStats.summaryConfigCount += m.capacity;else _currentStats.summaryConfigCount += 1;
2789
+ statsByResourceType[m.form_id] = _currentStats;
2790
+ }
2754
2791
  mTimes.forEach(function (childTiem) {
2755
2792
  // 挨个去匹配某个工作时间段结合当前日程时间,资源能不能用,有多少容量能用
2756
2793
  var res = getIsUsableByTimeItem({
@@ -2769,40 +2806,41 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2769
2806
  if ((resourcesUseableMap === null || resourcesUseableMap === void 0 ? void 0 : resourcesUseableMap[m.id]) !== false && res.reason !== 'capacityOnly') {
2770
2807
  resourcesUseableMap[m.id] = res.usable;
2771
2808
  }
2772
- if (res.usable && res.remainingCapacity >= count && !m.onlyComputed) {
2773
- currentResourcesCount = res.remainingCapacity;
2774
- }
2775
- if (res.usable && !m.onlyComputed && res.remainingCapacity >= currentResourcesSummaryCount) {
2776
- currentResourcesSummaryCount = res.remainingCapacity;
2809
+ if (!res.usable) isAllTimeSlicesUsable = false;
2810
+ if (res.usable && !m.onlyComputed) {
2811
+ if (res.remainingCapacity > currentResourceMaxRemainingCapacity) currentResourceMaxRemainingCapacity = res.remainingCapacity;
2777
2812
  }
2778
- currentResourcesTimeSlotCanUsedArr.push(res.usable);
2779
2813
  });
2780
- if (m.form_id === firstEnabledResourceId) {
2781
- // 确认当前资源是单个预约还是多个预约,单个预约则只需要计数,多个预约才添加容量
2782
- if (isMultipleBooking) {
2783
- summaryConfigCount += m.capacity;
2784
- } else {
2785
- summaryConfigCount += 1;
2786
- }
2787
- }
2788
- // 在已经选定时间的情况下,只要canUseTime如果有一个 false 那就不可用
2789
- if (!currentResourcesTimeSlotCanUsedArr.some(function (n) {
2790
- return n === false;
2791
- }) &&
2792
- // 只统计第一种资源的容量和 left
2793
- m.form_id === firstEnabledResourceId) {
2794
- if (currentResourcesCount >= count) {
2795
- count = currentResourcesCount;
2796
- }
2797
- if (!m.onlyComputed) {
2798
- bookingLeft += 1;
2799
- summaryCount += currentResourcesSummaryCount;
2800
- }
2814
+ if (!isAllTimeSlicesUsable) return;
2815
+ if (m.onlyComputed) return;
2816
+ var currentStats = statsByResourceType[m.form_id] || {
2817
+ count: 0,
2818
+ left: 0,
2819
+ summaryCount: 0,
2820
+ summaryConfigCount: 0
2821
+ };
2822
+ currentStats.left += 1;
2823
+ if (currentResourceTypeConfig.type === 'multiple') {
2824
+ currentStats.summaryCount += currentResourceMaxRemainingCapacity;
2825
+ if (currentResourceMaxRemainingCapacity > currentStats.count) currentStats.count = currentResourceMaxRemainingCapacity;
2826
+ } else {
2827
+ // 单个预约:一个资源只计 1,不关心剩余容量
2828
+ currentStats.summaryCount += 1;
2829
+ if (currentStats.count < 1) currentStats.count = 1;
2801
2830
  }
2831
+ statsByResourceType[m.form_id] = currentStats;
2802
2832
  });
2803
2833
  // 容量检测
2804
2834
  var cartItems = _this15.store.cart.getItems();
2805
2835
  productResources.forEach(function (n) {
2836
+ var currentResourceTypeConfig = resourceTypeConfigById.get(n.id);
2837
+ if (!currentResourceTypeConfig) return;
2838
+ var currentStats = statsByResourceType[n.id] || {
2839
+ count: 0,
2840
+ left: 0,
2841
+ summaryCount: 0
2842
+ };
2843
+
2806
2844
  // 单个预约检测规则:
2807
2845
  // 1、跟我一样的商品同一时间在购物车里不可以超过我最少的那种资源的关联的资源个数
2808
2846
  // 2、跟我不一样的商品,只需要跟我当前商品有同一种类型的资源的同一时间的,她配置了几个资源的个数+我配置了几个资源的个数,然后购物车里有几个这样的商品,对应的资源做一个去重,不超过这个去重以后的总数
@@ -2813,10 +2851,10 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2813
2851
  var _m$_productOrigin, _targetProductData$id;
2814
2852
  return ((_m$_productOrigin = m._productOrigin) === null || _m$_productOrigin === void 0 || (_m$_productOrigin = _m$_productOrigin.id) === null || _m$_productOrigin === void 0 ? void 0 : _m$_productOrigin.toString()) === (targetProductData === null || targetProductData === void 0 || (_targetProductData$id = targetProductData.id) === null || _targetProductData$id === void 0 ? void 0 : _targetProductData$id.toString()) && "".concat(m.start_date, " ").concat(m.start_time) === item.start && "".concat(m.start_date, " ").concat(m.end_time) === item.end;
2815
2853
  });
2816
- if (sameCartItems.length > 0 && sameCartItems.length >= currentResourcesSet.size || sameCartItems.length > bookingLeft) {
2817
- bookingLeft = 0;
2818
- count = 0;
2819
- summaryCount = 0;
2854
+ if (sameCartItems.length > 0 && sameCartItems.length >= currentResourcesSet.size || sameCartItems.length > currentStats.left) {
2855
+ currentStats.left = 0;
2856
+ currentStats.count = 0;
2857
+ currentStats.summaryCount = 0;
2820
2858
  }
2821
2859
  // 规则 2
2822
2860
  var otherCartItems = cartItems.filter(function (m) {
@@ -2853,9 +2891,9 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2853
2891
  }
2854
2892
  });
2855
2893
  if (currentResourcesSet.size > 0 && otherCartItems.length + sameCartItems.length >= currentResourcesSet.size) {
2856
- bookingLeft = 0;
2857
- count = 0;
2858
- summaryCount = 0;
2894
+ currentStats.left = 0;
2895
+ currentStats.count = 0;
2896
+ currentStats.summaryCount = 0;
2859
2897
  }
2860
2898
  } else {
2861
2899
  // 多个预约的检测规则:
@@ -2871,9 +2909,9 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2871
2909
  return !curr.onlyComputed ? acc + curr.capacity || 0 : acc;
2872
2910
  }, 0);
2873
2911
  if (sameCartNeedCapacity >= currentProductResourcesCapacity) {
2874
- bookingLeft = 0;
2875
- count = 0;
2876
- summaryCount = 0;
2912
+ currentStats.left = 0;
2913
+ currentStats.count = 0;
2914
+ currentStats.summaryCount = 0;
2877
2915
  }
2878
2916
  // 规则2、不管是不是跟我一样的商品,只需要跟我当前商品有同一种类型的资源的同一时间的,把所有购物车的 capacity 之和 和 所有当前类型资源的 capacity 之和比较,如果超过了resourcesCapacity,则不可用
2879
2917
  // const otherCartItems = cartItems.filter((m) => m._productOrigin?.id?.toString() !== targetProductData?.id?.toString() && m.start_time === item.start && m.end_time === item.end);
@@ -2935,45 +2973,61 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2935
2973
  }, 0);
2936
2974
  // 如果已使用容量超过了当前类型资源的容量,则不可用
2937
2975
  if (otherCartNeedCapacity + usedCapacity >= currentTypeResourcesCapacity) {
2938
- bookingLeft = 0;
2939
- count = 0;
2940
- summaryCount = 0;
2976
+ currentStats.left = 0;
2977
+ currentStats.count = 0;
2978
+ currentStats.summaryCount = 0;
2941
2979
  }
2942
2980
  }
2981
+ statsByResourceType[n.id] = currentStats;
2943
2982
  });
2944
2983
  var startDayJs = dayjs(item.start);
2945
2984
  var endDayJs = dayjs(item.end);
2946
2985
 
2947
- // 状态
2948
- // 如果是isMultipleBooking
2949
- // lots_of_space: summaryCount / summaryConfigCount > 0.5
2950
- // filling_up_fast: summaryCount / summaryConfigCount <= 0.5 && summaryCount > 0
2951
- // sold_out: bookingLeft = 0
2952
- // 如果不是isMultipleBooking
2953
- // lots_of_space: bookingLeft / summaryConfigCount > 0.5
2954
- // filling_up_fast: bookingLeft / summaryConfigCount <= 0.5 && count > 0
2955
- // sold_out: bookingLeft = 0
2956
- var timeStatus = 'sold_out';
2957
- if (bookingLeft === 0) timeStatus = 'sold_out';else if (isMultipleBooking) {
2958
- if (summaryConfigCount === 0) timeStatus = 'sold_out';else {
2959
- var usageRatio = summaryCount / summaryConfigCount;
2960
- if (usageRatio > 0.5) timeStatus = 'lots_of_space';else if (summaryCount > 0) timeStatus = 'filling_up_fast';else timeStatus = 'sold_out';
2986
+ // 选择“瓶颈资源类型”:multiple 取 summaryCount 最小,single 取 left 最小
2987
+ var bottleneckResourceTypeId;
2988
+ var bottleneckValue = Infinity;
2989
+ enabledResourceTypeConfigs.forEach(function (cfg) {
2990
+ var stats = statsByResourceType[cfg.id] || {
2991
+ count: 0,
2992
+ left: 0,
2993
+ summaryCount: 0,
2994
+ summaryConfigCount: 0
2995
+ };
2996
+ var value = cfg.type === 'multiple' ? stats.summaryCount : stats.left;
2997
+ if (value < bottleneckValue) {
2998
+ bottleneckValue = value;
2999
+ bottleneckResourceTypeId = cfg.id;
2961
3000
  }
3001
+ });
3002
+ var bottleneckStats = bottleneckResourceTypeId !== undefined ? statsByResourceType[bottleneckResourceTypeId] || {
3003
+ count: 0,
3004
+ left: 0,
3005
+ summaryCount: 0,
3006
+ summaryConfigCount: 0
3007
+ } : {
3008
+ count: 0,
3009
+ left: 0,
3010
+ summaryCount: 0,
3011
+ summaryConfigCount: 0
3012
+ };
3013
+ var bottleneckConfig = bottleneckResourceTypeId !== undefined ? resourceTypeConfigById.get(bottleneckResourceTypeId) : undefined;
3014
+ var status = 'sold_out';
3015
+ if (bottleneckStats.left === 0) status = 'sold_out';else if (!bottleneckConfig || bottleneckStats.summaryConfigCount === 0) status = 'sold_out';else if (bottleneckConfig.type === 'multiple') {
3016
+ var usageRatio = bottleneckStats.summaryCount / bottleneckStats.summaryConfigCount;
3017
+ if (usageRatio > 0.5) status = 'lots_of_space';else if (bottleneckStats.summaryCount > 0) status = 'filling_up_fast';else status = 'sold_out';
2962
3018
  } else {
2963
- if (summaryConfigCount === 0) timeStatus = 'sold_out';else {
2964
- var _usageRatio = bookingLeft / summaryConfigCount;
2965
- if (_usageRatio > 0.5) timeStatus = 'lots_of_space';else if (count > 0) timeStatus = 'filling_up_fast';else timeStatus = 'sold_out';
2966
- }
3019
+ var _usageRatio = bottleneckStats.left / bottleneckStats.summaryConfigCount;
3020
+ if (_usageRatio > 0.5) status = 'lots_of_space';else if (bottleneckStats.count > 0) status = 'filling_up_fast';else status = 'sold_out';
2967
3021
  }
2968
3022
  return {
2969
3023
  start_time: startDayJs.format('HH:mm'),
2970
3024
  end_time: endDayJs.format('HH:mm'),
2971
3025
  start_at: startDayJs,
2972
3026
  end_at: endDayJs,
2973
- count: count,
2974
- left: bookingLeft,
2975
- summaryCount: summaryCount,
2976
- status: timeStatus
3027
+ count: bottleneckStats.count,
3028
+ left: bottleneckStats.left,
3029
+ summaryCount: bottleneckStats.summaryCount,
3030
+ status: status
2977
3031
  };
2978
3032
  });
2979
3033
  return formatScheduleTimeSlots;
@@ -444,6 +444,10 @@ export var getTimeSlicesByResource = function getTimeSlicesByResource(_ref5) {
444
444
  // 解析开始和结束时间
445
445
  var startTime = dayjs("".concat(time.start_at));
446
446
  var endTime = dayjs("".concat(time.end_at));
447
+ // 结束时间要做修复,如果time.end_at 是超过了 currentDate 的那一天,则把 end_at 设置为 currentDate 那一天的 23:59:59
448
+ if (endTime.isAfter(dayjs(currentDate).endOf('day'))) {
449
+ endTime = dayjs(currentDate).endOf('day');
450
+ }
447
451
 
448
452
  // 当前切片的开始时间
449
453
  var currentStart = startTime;
@@ -484,9 +484,10 @@ var RulesModule = class extends import_BaseModule.BaseModule {
484
484
  };
485
485
  }
486
486
  const quantity = flatItem.type === "main" ? product.quantity || 1 : (product.num || 1) * (((_a = flatItem.parentProduct) == null ? void 0 : _a.quantity) || 1);
487
+ const originalAmount = flatItem.type === "main" ? Number(product.price ?? 0) : Number(flatItem.original_price ?? flatItem.price ?? 0);
487
488
  const productData = {
488
489
  productId: flatItem._id,
489
- amount: Number(product.price || 0),
490
+ amount: originalAmount,
490
491
  quantity
491
492
  };
492
493
  if (flatItem.type === "bundle") {
@@ -327,7 +327,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
327
327
  count: number;
328
328
  left: number;
329
329
  summaryCount: number;
330
- status: keyof TimeStatusMap;
330
+ status: "lots_of_space" | "filling_up_fast" | "sold_out";
331
331
  }[];
332
332
  /**
333
333
  * 找到多个资源的公共可用时间段
@@ -392,9 +392,3 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
392
392
  */
393
393
  getContactInfo(params: any): Promise<any>;
394
394
  }
395
- interface TimeStatusMap {
396
- lots_of_space: true;
397
- filling_up_fast: true;
398
- sold_out: true;
399
- }
400
- export {};
@@ -1530,6 +1530,15 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
1530
1530
  }, 0);
1531
1531
  }
1532
1532
  const calculateCapacityFromCartItems = (items) => {
1533
+ var _a2;
1534
+ const firstResource = (_a2 = items[0]._resourceOrigin) == null ? void 0 : _a2[0].id;
1535
+ const sameResourceLength = items.filter((item) => {
1536
+ var _a3;
1537
+ return ((_a3 = item._resourceOrigin) == null ? void 0 : _a3[0].id) === firstResource;
1538
+ }).length;
1539
+ if (sameResourceLength !== items.length) {
1540
+ return 1;
1541
+ }
1533
1542
  return items.reduce((total, item) => {
1534
1543
  return total + ((0, import_capacity.getCapacityInfoByCartItem)(item).currentCapacity || 0);
1535
1544
  }, 0);
@@ -1656,6 +1665,15 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
1656
1665
  }, 0);
1657
1666
  }
1658
1667
  const calculateCapacityFromCartItems = (items) => {
1668
+ var _a2;
1669
+ const firstResource = (_a2 = items[0]._resourceOrigin) == null ? void 0 : _a2[0].id;
1670
+ const sameResourceLength = items.filter((item) => {
1671
+ var _a3;
1672
+ return ((_a3 = item._resourceOrigin) == null ? void 0 : _a3[0].id) === firstResource;
1673
+ }).length;
1674
+ if (sameResourceLength !== items.length) {
1675
+ return 1;
1676
+ }
1659
1677
  return items.reduce((total, item) => {
1660
1678
  return total + ((0, import_capacity.getCapacityInfoByCartItem)(item).currentCapacity || 0);
1661
1679
  }, 0);
@@ -1865,7 +1883,7 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
1865
1883
  resources,
1866
1884
  product
1867
1885
  }) {
1868
- var _a, _b, _c, _d, _e, _f, _g;
1886
+ var _a, _b, _c, _d;
1869
1887
  const targetProduct = this.store.currentProduct;
1870
1888
  const targetProductData = product || targetProduct;
1871
1889
  let targetSchedules = [];
@@ -1908,29 +1926,48 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
1908
1926
  return -1;
1909
1927
  return 0;
1910
1928
  });
1911
- const firstEnabledResourceId = (_e = (_d = (_c = targetProductData == null ? void 0 : targetProductData.product_resource) == null ? void 0 : _c.resources) == null ? void 0 : _d.find(
1929
+ const enabledResourceTypeConfigs = ((_d = (_c = targetProductData == null ? void 0 : targetProductData.product_resource) == null ? void 0 : _c.resources) == null ? void 0 : _d.filter(
1912
1930
  (n) => n.status === 1
1913
- )) == null ? void 0 : _e.id;
1914
- const firstEnabledResourceConfig = (_g = (_f = targetProductData == null ? void 0 : targetProductData.product_resource) == null ? void 0 : _f.resources) == null ? void 0 : _g.find(
1915
- (n) => n.status === 1 && n.id === firstEnabledResourceId
1931
+ )) || [];
1932
+ const resourceTypeConfigById = new Map(
1933
+ enabledResourceTypeConfigs.map((n) => [n.id, n])
1916
1934
  );
1917
- const isMultipleBooking = (firstEnabledResourceConfig == null ? void 0 : firstEnabledResourceConfig.type) === "multiple";
1918
1935
  const formatScheduleTimeSlots = scheduleTimeSlots.map((item) => {
1919
1936
  const resourcesUseableMap = {};
1920
- let count = 0;
1921
- let bookingLeft = 0;
1922
- let summaryCount = 0;
1923
- let summaryConfigCount = 0;
1937
+ const statsByResourceType = {};
1938
+ enabledResourceTypeConfigs.forEach((cfg) => {
1939
+ statsByResourceType[cfg.id] = {
1940
+ count: 0,
1941
+ left: 0,
1942
+ summaryCount: 0,
1943
+ summaryConfigCount: 0
1944
+ };
1945
+ });
1924
1946
  allProductResources == null ? void 0 : allProductResources.forEach((m) => {
1925
- let currentResourcesCount = 0;
1926
- let currentResourcesSummaryCount = 0;
1927
- const currentResourcesTimeSlotCanUsedArr = [];
1947
+ const currentResourceTypeConfig = resourceTypeConfigById.get(m.form_id);
1948
+ if (!currentResourceTypeConfig)
1949
+ return;
1950
+ let currentResourceMaxRemainingCapacity = 0;
1951
+ let isAllTimeSlicesUsable = true;
1928
1952
  const mTimes = m.times.filter((n) => {
1929
1953
  return !(0, import_dayjs.default)(n.start_at).isAfter((0, import_dayjs.default)(item.start), "minute") && !(0, import_dayjs.default)(n.end_at).isBefore((0, import_dayjs.default)(item.end), "minute") || (0, import_dayjs.default)(n.start_at).isBefore((0, import_dayjs.default)(item.end), "minute") && (0, import_dayjs.default)(n.end_at).isAfter((0, import_dayjs.default)(item.start), "minute");
1930
1954
  });
1931
1955
  if (mTimes.length === 0) {
1932
1956
  return;
1933
1957
  }
1958
+ if (!m.onlyComputed) {
1959
+ const currentStats2 = statsByResourceType[m.form_id] || {
1960
+ count: 0,
1961
+ left: 0,
1962
+ summaryCount: 0,
1963
+ summaryConfigCount: 0
1964
+ };
1965
+ if (currentResourceTypeConfig.type === "multiple")
1966
+ currentStats2.summaryConfigCount += m.capacity;
1967
+ else
1968
+ currentStats2.summaryConfigCount += 1;
1969
+ statsByResourceType[m.form_id] = currentStats2;
1970
+ }
1934
1971
  mTimes.forEach((childTiem) => {
1935
1972
  const res = (0, import_resources.getIsUsableByTimeItem)({
1936
1973
  timeSlice: {
@@ -1948,52 +1985,61 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
1948
1985
  if ((resourcesUseableMap == null ? void 0 : resourcesUseableMap[m.id]) !== false && res.reason !== "capacityOnly") {
1949
1986
  resourcesUseableMap[m.id] = res.usable;
1950
1987
  }
1951
- if (res.usable && res.remainingCapacity >= count && !m.onlyComputed) {
1952
- currentResourcesCount = res.remainingCapacity;
1988
+ if (!res.usable)
1989
+ isAllTimeSlicesUsable = false;
1990
+ if (res.usable && !m.onlyComputed) {
1991
+ if (res.remainingCapacity > currentResourceMaxRemainingCapacity)
1992
+ currentResourceMaxRemainingCapacity = res.remainingCapacity;
1953
1993
  }
1954
- if (res.usable && !m.onlyComputed && res.remainingCapacity >= currentResourcesSummaryCount) {
1955
- currentResourcesSummaryCount = res.remainingCapacity;
1956
- }
1957
- currentResourcesTimeSlotCanUsedArr.push(res.usable);
1958
1994
  });
1959
- if (m.form_id === firstEnabledResourceId) {
1960
- if (isMultipleBooking) {
1961
- summaryConfigCount += m.capacity;
1962
- } else {
1963
- summaryConfigCount += 1;
1964
- }
1965
- }
1966
- if (!currentResourcesTimeSlotCanUsedArr.some(
1967
- (n) => n === false
1968
- ) && // 只统计第一种资源的容量和 left
1969
- m.form_id === firstEnabledResourceId) {
1970
- if (currentResourcesCount >= count) {
1971
- count = currentResourcesCount;
1972
- }
1973
- if (!m.onlyComputed) {
1974
- bookingLeft += 1;
1975
- summaryCount += currentResourcesSummaryCount;
1976
- }
1995
+ if (!isAllTimeSlicesUsable)
1996
+ return;
1997
+ if (m.onlyComputed)
1998
+ return;
1999
+ const currentStats = statsByResourceType[m.form_id] || {
2000
+ count: 0,
2001
+ left: 0,
2002
+ summaryCount: 0,
2003
+ summaryConfigCount: 0
2004
+ };
2005
+ currentStats.left += 1;
2006
+ if (currentResourceTypeConfig.type === "multiple") {
2007
+ currentStats.summaryCount += currentResourceMaxRemainingCapacity;
2008
+ if (currentResourceMaxRemainingCapacity > currentStats.count)
2009
+ currentStats.count = currentResourceMaxRemainingCapacity;
2010
+ } else {
2011
+ currentStats.summaryCount += 1;
2012
+ if (currentStats.count < 1)
2013
+ currentStats.count = 1;
1977
2014
  }
2015
+ statsByResourceType[m.form_id] = currentStats;
1978
2016
  });
1979
2017
  const cartItems2 = this.store.cart.getItems();
1980
2018
  productResources.forEach((n) => {
2019
+ const currentResourceTypeConfig = resourceTypeConfigById.get(n.id);
2020
+ if (!currentResourceTypeConfig)
2021
+ return;
2022
+ const currentStats = statsByResourceType[n.id] || {
2023
+ count: 0,
2024
+ left: 0,
2025
+ summaryCount: 0
2026
+ };
1981
2027
  if (n.type === "single") {
1982
2028
  const currentResourcesSet = /* @__PURE__ */ new Set([...n.optional_resource, ...n.default_resource]);
1983
2029
  const sameCartItems = cartItems2.filter((m) => {
1984
2030
  var _a2, _b2, _c2;
1985
2031
  return ((_b2 = (_a2 = m._productOrigin) == null ? void 0 : _a2.id) == null ? void 0 : _b2.toString()) === ((_c2 = targetProductData == null ? void 0 : targetProductData.id) == null ? void 0 : _c2.toString()) && `${m.start_date} ${m.start_time}` === item.start && `${m.start_date} ${m.end_time}` === item.end;
1986
2032
  });
1987
- if (sameCartItems.length > 0 && sameCartItems.length >= currentResourcesSet.size || sameCartItems.length > bookingLeft) {
1988
- bookingLeft = 0;
1989
- count = 0;
1990
- summaryCount = 0;
2033
+ if (sameCartItems.length > 0 && sameCartItems.length >= currentResourcesSet.size || sameCartItems.length > currentStats.left) {
2034
+ currentStats.left = 0;
2035
+ currentStats.count = 0;
2036
+ currentStats.summaryCount = 0;
1991
2037
  }
1992
2038
  let otherCartItems = cartItems2.filter(
1993
2039
  (m) => {
1994
- var _a2, _b2, _c2, _d2, _e2, _f2;
2040
+ var _a2, _b2, _c2, _d2, _e, _f;
1995
2041
  const isTimeMatch = ((_b2 = (_a2 = m._productOrigin) == null ? void 0 : _a2.id) == null ? void 0 : _b2.toString()) !== ((_c2 = targetProductData == null ? void 0 : targetProductData.id) == null ? void 0 : _c2.toString()) && `${m.start_date} ${m.start_time}` === item.start && `${m.start_date} ${m.end_time}` === item.end;
1996
- const isResourceMatch = (_f2 = (_e2 = (_d2 = m._productOrigin) == null ? void 0 : _d2.product_resource) == null ? void 0 : _e2.resources) == null ? void 0 : _f2.find((m2) => m2.type === n.type && m2.status === 1);
2042
+ const isResourceMatch = (_f = (_e = (_d2 = m._productOrigin) == null ? void 0 : _d2.product_resource) == null ? void 0 : _e.resources) == null ? void 0 : _f.find((m2) => m2.type === n.type && m2.status === 1);
1997
2043
  return isTimeMatch && isResourceMatch;
1998
2044
  }
1999
2045
  );
@@ -2015,9 +2061,9 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
2015
2061
  }
2016
2062
  });
2017
2063
  if (currentResourcesSet.size > 0 && otherCartItems.length + sameCartItems.length >= currentResourcesSet.size) {
2018
- bookingLeft = 0;
2019
- count = 0;
2020
- summaryCount = 0;
2064
+ currentStats.left = 0;
2065
+ currentStats.count = 0;
2066
+ currentStats.summaryCount = 0;
2021
2067
  }
2022
2068
  } else {
2023
2069
  const sameCartItems = cartItems2.filter((m) => {
@@ -2027,9 +2073,9 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
2027
2073
  const sameCartNeedCapacity = sameCartItems.reduce((acc, curr) => acc + (0, import_capacity.getCapacityInfoByCartItem)(curr).currentCapacity, 0);
2028
2074
  const currentProductResourcesCapacity = n.renderList.reduce((acc, curr) => !curr.onlyComputed ? acc + curr.capacity || 0 : acc, 0);
2029
2075
  if (sameCartNeedCapacity >= currentProductResourcesCapacity) {
2030
- bookingLeft = 0;
2031
- count = 0;
2032
- summaryCount = 0;
2076
+ currentStats.left = 0;
2077
+ currentStats.count = 0;
2078
+ currentStats.summaryCount = 0;
2033
2079
  }
2034
2080
  const otherSameTimesCartItems = cartItems2.filter((m) => `${m.start_date} ${m.start_time}` === item.start && `${m.start_date} ${m.end_time}` === item.end);
2035
2081
  const otherCartNeedCapacity = otherSameTimesCartItems.reduce((acc, curr) => acc + (0, import_capacity.getCapacityInfoByCartItem)(curr).currentCapacity, 0);
@@ -2072,51 +2118,68 @@ var BookingByStepImpl = class extends import_BaseModule.BaseModule {
2072
2118
  return acc;
2073
2119
  }, 0);
2074
2120
  if (otherCartNeedCapacity + usedCapacity >= currentTypeResourcesCapacity) {
2075
- bookingLeft = 0;
2076
- count = 0;
2077
- summaryCount = 0;
2121
+ currentStats.left = 0;
2122
+ currentStats.count = 0;
2123
+ currentStats.summaryCount = 0;
2078
2124
  }
2079
2125
  }
2126
+ statsByResourceType[n.id] = currentStats;
2080
2127
  });
2081
2128
  const startDayJs = (0, import_dayjs.default)(item.start);
2082
2129
  const endDayJs = (0, import_dayjs.default)(item.end);
2083
- let timeStatus = "sold_out";
2084
- if (bookingLeft === 0)
2085
- timeStatus = "sold_out";
2086
- else if (isMultipleBooking) {
2087
- if (summaryConfigCount === 0)
2088
- timeStatus = "sold_out";
2089
- else {
2090
- const usageRatio = summaryCount / summaryConfigCount;
2091
- if (usageRatio > 0.5)
2092
- timeStatus = "lots_of_space";
2093
- else if (summaryCount > 0)
2094
- timeStatus = "filling_up_fast";
2095
- else
2096
- timeStatus = "sold_out";
2130
+ let bottleneckResourceTypeId;
2131
+ let bottleneckValue = Infinity;
2132
+ enabledResourceTypeConfigs.forEach((cfg) => {
2133
+ const stats = statsByResourceType[cfg.id] || {
2134
+ count: 0,
2135
+ left: 0,
2136
+ summaryCount: 0,
2137
+ summaryConfigCount: 0
2138
+ };
2139
+ const value = cfg.type === "multiple" ? stats.summaryCount : stats.left;
2140
+ if (value < bottleneckValue) {
2141
+ bottleneckValue = value;
2142
+ bottleneckResourceTypeId = cfg.id;
2097
2143
  }
2144
+ });
2145
+ const bottleneckStats = bottleneckResourceTypeId !== void 0 ? statsByResourceType[bottleneckResourceTypeId] || {
2146
+ count: 0,
2147
+ left: 0,
2148
+ summaryCount: 0,
2149
+ summaryConfigCount: 0
2150
+ } : { count: 0, left: 0, summaryCount: 0, summaryConfigCount: 0 };
2151
+ const bottleneckConfig = bottleneckResourceTypeId !== void 0 ? resourceTypeConfigById.get(bottleneckResourceTypeId) : void 0;
2152
+ let status = "sold_out";
2153
+ if (bottleneckStats.left === 0)
2154
+ status = "sold_out";
2155
+ else if (!bottleneckConfig || bottleneckStats.summaryConfigCount === 0)
2156
+ status = "sold_out";
2157
+ else if (bottleneckConfig.type === "multiple") {
2158
+ const usageRatio = bottleneckStats.summaryCount / bottleneckStats.summaryConfigCount;
2159
+ if (usageRatio > 0.5)
2160
+ status = "lots_of_space";
2161
+ else if (bottleneckStats.summaryCount > 0)
2162
+ status = "filling_up_fast";
2163
+ else
2164
+ status = "sold_out";
2098
2165
  } else {
2099
- if (summaryConfigCount === 0)
2100
- timeStatus = "sold_out";
2101
- else {
2102
- const usageRatio = bookingLeft / summaryConfigCount;
2103
- if (usageRatio > 0.5)
2104
- timeStatus = "lots_of_space";
2105
- else if (count > 0)
2106
- timeStatus = "filling_up_fast";
2107
- else
2108
- timeStatus = "sold_out";
2109
- }
2166
+ const usageRatio = bottleneckStats.left / bottleneckStats.summaryConfigCount;
2167
+ if (usageRatio > 0.5)
2168
+ status = "lots_of_space";
2169
+ else if (bottleneckStats.count > 0)
2170
+ status = "filling_up_fast";
2171
+ else
2172
+ status = "sold_out";
2110
2173
  }
2111
2174
  return {
2112
2175
  start_time: startDayJs.format("HH:mm"),
2113
2176
  end_time: endDayJs.format("HH:mm"),
2114
2177
  start_at: startDayJs,
2115
2178
  end_at: endDayJs,
2116
- count,
2117
- left: bookingLeft,
2118
- summaryCount,
2119
- status: timeStatus
2179
+ count: bottleneckStats.count,
2180
+ left: bottleneckStats.left,
2181
+ summaryCount: bottleneckStats.summaryCount,
2182
+ status
2120
2183
  };
2121
2184
  });
2122
2185
  return formatScheduleTimeSlots;
@@ -353,7 +353,10 @@ var getTimeSlicesByResource = ({
353
353
  });
354
354
  times.forEach((time) => {
355
355
  const startTime = (0, import_dayjs.default)(`${time.start_at}`);
356
- const endTime = (0, import_dayjs.default)(`${time.end_at}`);
356
+ let endTime = (0, import_dayjs.default)(`${time.end_at}`);
357
+ if (endTime.isAfter((0, import_dayjs.default)(currentDate).endOf("day"))) {
358
+ endTime = (0, import_dayjs.default)(currentDate).endOf("day");
359
+ }
357
360
  let currentStart = startTime;
358
361
  while (true) {
359
362
  const currentEnd = currentStart.add(duration, "minute");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "1.0.113",
4
+ "version": "1.0.115",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",