@pisell/pisellos 2.1.129 → 2.1.130

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.
Files changed (44) hide show
  1. package/dist/modules/Order/index.d.ts +4 -0
  2. package/dist/modules/Order/index.js +18 -1
  3. package/dist/modules/Order/types.d.ts +9 -1
  4. package/dist/modules/Order/utils.d.ts +7 -0
  5. package/dist/modules/Order/utils.js +27 -11
  6. package/dist/solution/ScanOrder/index.d.ts +27 -3
  7. package/dist/solution/ScanOrder/index.js +865 -481
  8. package/dist/solution/ScanOrder/types.d.ts +34 -24
  9. package/dist/solution/ScanOrder/types.js +5 -1
  10. package/dist/solution/ScanOrder/utils.d.ts +13 -1
  11. package/dist/solution/ScanOrder/utils.js +45 -6
  12. package/dist/solution/VenueBooking/index.d.ts +28 -5
  13. package/dist/solution/VenueBooking/index.js +428 -193
  14. package/dist/solution/VenueBooking/types.d.ts +23 -0
  15. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -1
  16. package/dist/solution/VenueBooking/utils/dateSummary.js +1 -1
  17. package/dist/solution/VenueBooking/utils/resource.d.ts +11 -1
  18. package/dist/solution/VenueBooking/utils/resource.js +57 -21
  19. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
  20. package/dist/solution/VenueBooking/utils/slotMerge.js +33 -12
  21. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
  22. package/dist/solution/VenueBooking/utils/timeSlot.js +259 -62
  23. package/lib/modules/Order/index.d.ts +4 -0
  24. package/lib/modules/Order/index.js +14 -1
  25. package/lib/modules/Order/types.d.ts +9 -1
  26. package/lib/modules/Order/utils.d.ts +7 -0
  27. package/lib/modules/Order/utils.js +22 -12
  28. package/lib/solution/ScanOrder/index.d.ts +27 -3
  29. package/lib/solution/ScanOrder/index.js +409 -114
  30. package/lib/solution/ScanOrder/types.d.ts +34 -24
  31. package/lib/solution/ScanOrder/utils.d.ts +13 -1
  32. package/lib/solution/ScanOrder/utils.js +37 -0
  33. package/lib/solution/VenueBooking/index.d.ts +28 -5
  34. package/lib/solution/VenueBooking/index.js +193 -45
  35. package/lib/solution/VenueBooking/types.d.ts +23 -0
  36. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -1
  37. package/lib/solution/VenueBooking/utils/dateSummary.js +1 -1
  38. package/lib/solution/VenueBooking/utils/resource.d.ts +11 -1
  39. package/lib/solution/VenueBooking/utils/resource.js +15 -4
  40. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
  41. package/lib/solution/VenueBooking/utils/slotMerge.js +29 -12
  42. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
  43. package/lib/solution/VenueBooking/utils/timeSlot.js +182 -43
  44. package/package.json +1 -1
@@ -36,14 +36,31 @@ export interface VenueTimeSlot {
36
36
  resourceFormId: number | string;
37
37
  capacity: number | null;
38
38
  remainingCapacity: number | null;
39
+ /** per-product sub-row slot 上带的 productId;外层合并 slot 不写 */
40
+ productId?: number;
41
+ }
42
+ export interface VenueResourceSubRow {
43
+ productId: number;
44
+ productTitle: string;
45
+ price: string;
46
+ slots: VenueTimeSlot[];
47
+ }
48
+ export interface VenueResourceCombinedInfo {
49
+ resourceIds: Array<number | string>;
39
50
  }
40
51
  export interface VenueResourceRow {
41
52
  resourceId: number | string;
42
53
  resourceFormId: number | string;
43
54
  resourceName: string;
55
+ /** 单商品时取唯一 mapping.productId;多商品时取第一个 mapping(兼容字段) */
44
56
  productId: number;
45
57
  productTitle: string;
46
58
  slots: VenueTimeSlot[];
59
+ /** 多商品共享同一场地时的子行;单商品不输出 */
60
+ products?: VenueResourceSubRow[];
61
+ hasMultipleProducts?: boolean;
62
+ /** 当前资源是 combined_resource.status===1 时输出 */
63
+ combinedResource?: VenueResourceCombinedInfo;
47
64
  }
48
65
  export interface VenueTimeSlotGrid {
49
66
  date: string;
@@ -57,6 +74,10 @@ export interface VenueDateSummaryItem {
57
74
  totalSlots: number;
58
75
  availableSlots: number;
59
76
  }
77
+ export interface VenueResourceCombinedRaw {
78
+ status: number;
79
+ resource_ids: Array<number | string>;
80
+ }
60
81
  export interface VenueResourceRawData {
61
82
  resourceId: number | string;
62
83
  formId: number | string;
@@ -69,6 +90,7 @@ export interface VenueResourceRawData {
69
90
  end_at: string;
70
91
  [key: string]: any;
71
92
  }>;
93
+ combined_resource?: VenueResourceCombinedRaw;
72
94
  [key: string]: any;
73
95
  }
74
96
  export interface ResourceProductMapping {
@@ -81,6 +103,7 @@ export interface ResourceProductMapping {
81
103
  }
82
104
  export interface VenueSlotSelection {
83
105
  resourceId: number | string;
106
+ productId: number;
84
107
  startTime: string;
85
108
  endTime: string;
86
109
  price: string;
@@ -5,7 +5,7 @@ export declare function buildDateRangeSummary(params: {
5
5
  endDate: string;
6
6
  config: VenueBookingSlotConfig;
7
7
  rawResources: VenueResourceRawData[];
8
- resourceProductMap: Map<number | string, ResourceProductMapping>;
8
+ resourceProductMap: Map<number | string, ResourceProductMapping[]>;
9
9
  quotationModule?: QuotationModule;
10
10
  resolveConfig?: (date: string) => VenueBookingSlotConfig;
11
11
  }): VenueDateSummaryItem[];
@@ -45,7 +45,7 @@ function buildDateRangeSummary(params) {
45
45
  resolveConfig
46
46
  } = params;
47
47
  const result = [];
48
- const productIds = quotationModule ? [...new Set([...resourceProductMap.values()].map((m) => m.productId))] : [];
48
+ const productIds = quotationModule ? [...new Set([...resourceProductMap.values()].flat().map((m) => m.productId))] : [];
49
49
  let cursor = (0, import_dayjs.default)(startDate);
50
50
  const end = (0, import_dayjs.default)(endDate);
51
51
  while (!cursor.isAfter(end)) {
@@ -1,4 +1,14 @@
1
1
  import type { ProductData } from '../../../modules/Product/types';
2
2
  import type { ResourceProductMapping } from '../types';
3
+ /**
4
+ * 从商品列表里抽取所有 resource_id:
5
+ * - 商品绑定的 default_resource / optional_resource
6
+ * - 以及这些资源上声明的 combined_resource.resource_ids(若可从 product_resource 读取)
7
+ * 用于一次性拉到子资源数据,判定组合资源的可用性。
8
+ */
3
9
  export declare function extractResourceIds(products: ProductData[]): number[];
4
- export declare function buildResourceProductMap(products: ProductData[]): Map<number | string, ResourceProductMapping>;
10
+ /**
11
+ * 每个 resourceId 可以被多个商品共享(同一场地关联多种运动商品)。
12
+ * Map 的 value 改为 ResourceProductMapping[],按商品出现顺序保留。
13
+ */
14
+ export declare function buildResourceProductMap(products: ProductData[]): Map<number | string, ResourceProductMapping[]>;
@@ -39,6 +39,13 @@ function extractResourceIds(products) {
39
39
  if (typeof id === "number" && id > 0)
40
40
  ids.add(id);
41
41
  }
42
+ const combined = resource.combined_resource;
43
+ if (combined && combined.status === 1 && Array.isArray(combined.resource_ids)) {
44
+ for (const id of combined.resource_ids) {
45
+ if (typeof id === "number" && id > 0)
46
+ ids.add(id);
47
+ }
48
+ }
42
49
  }
43
50
  }
44
51
  return Array.from(ids);
@@ -58,16 +65,20 @@ function buildResourceProductMap(products) {
58
65
  ...resource.optional_resource || []
59
66
  ];
60
67
  for (const resId of allResourceIds) {
61
- if (map.has(resId))
62
- continue;
63
- map.set(resId, {
68
+ const existing = map.get(resId);
69
+ const mapping = {
64
70
  productId: product.id,
65
71
  productTitle: product.title,
66
72
  resourceName: resource.title,
67
73
  formId: resource.id,
68
74
  price: product.price || "0.00",
69
75
  resourceType: resource.type || "single"
70
- });
76
+ };
77
+ if (!existing) {
78
+ map.set(resId, [mapping]);
79
+ } else if (!existing.some((m) => m.productId === mapping.productId)) {
80
+ existing.push(mapping);
81
+ }
71
82
  }
72
83
  }
73
84
  }
@@ -19,6 +19,11 @@ export interface BuildVenueBookingParams {
19
19
  rawResource: VenueResourceRawData | undefined;
20
20
  bookingUuid: string;
21
21
  productUid: string;
22
+ /**
23
+ * 若当前 resource 是组合资源(combined_resource.status === 1),传入其子资源的原始数据,
24
+ * 将作为 resources[0].children 写入 booking,结构与父 resource 保持一致。
25
+ */
26
+ childResources?: VenueResourceRawData[];
22
27
  }
23
28
  export declare function buildVenueBookingEntry(params: BuildVenueBookingParams): Record<string, any>;
24
29
  /**
@@ -107,10 +107,32 @@ function buildPriceBreakdown(params) {
107
107
  return entries;
108
108
  }
109
109
  function buildVenueBookingEntry(params) {
110
- const { group, resourceId, mapping, rawResource, bookingUuid, productUid } = params;
110
+ const { group, resourceId, mapping, rawResource, bookingUuid, productUid, childResources } = params;
111
111
  const startMoment = (0, import_dayjs.default)(group.startTime, "YYYY-MM-DD HH:mm");
112
112
  const endMoment = (0, import_dayjs.default)(group.endTime, "YYYY-MM-DD HH:mm");
113
113
  const duration = endMoment.diff(startMoment, "minute");
114
+ const resourceEntry = {
115
+ relation_type: "form",
116
+ like_status: "common",
117
+ id: resourceId,
118
+ main_field: mapping.resourceName,
119
+ form_id: (rawResource == null ? void 0 : rawResource.form_id) ?? mapping.formId,
120
+ relation_id: resourceId,
121
+ capacity: 1,
122
+ metadata: {}
123
+ };
124
+ if (childResources && childResources.length) {
125
+ resourceEntry.children = childResources.map((child) => ({
126
+ relation_type: "form",
127
+ like_status: "common",
128
+ id: child.resourceId,
129
+ main_field: child.main_field || "",
130
+ form_id: child.form_id ?? child.formId,
131
+ relation_id: child.resourceId,
132
+ capacity: child.capacity ?? 1,
133
+ metadata: {}
134
+ }));
135
+ }
114
136
  return {
115
137
  schedule_event_id: null,
116
138
  appointment_status: "new",
@@ -126,23 +148,15 @@ function buildVenueBookingEntry(params) {
126
148
  is_all: false,
127
149
  schedule_id: 0,
128
150
  product_uid: productUid,
129
- resources: [{
130
- relation_type: "form",
131
- like_status: "common",
132
- id: resourceId,
133
- main_field: mapping.resourceName,
134
- form_id: (rawResource == null ? void 0 : rawResource.form_id) ?? mapping.formId,
135
- relation_id: resourceId,
136
- capacity: 1,
137
- metadata: {}
138
- }],
151
+ resources: [resourceEntry],
139
152
  relation_products: [],
140
153
  relation_forms: [],
141
154
  holder: null,
142
155
  metadata: {
143
156
  unique_identification_number: bookingUuid,
144
157
  venue_booking: true,
145
- resource_id: resourceId
158
+ resource_id: resourceId,
159
+ product_id: mapping.productId
146
160
  }
147
161
  };
148
162
  }
@@ -155,6 +169,7 @@ function expandMergedSlotToIndividual(product, slotDurationMinutes) {
155
169
  const endTime = meta.end_time;
156
170
  if (!startTime || !endTime)
157
171
  return [];
172
+ const productId = Number(product.product_id);
158
173
  const breakdown = meta.price_breakdown;
159
174
  const result = [];
160
175
  let cursor = (0, import_dayjs.default)(startTime, "YYYY-MM-DD HH:mm");
@@ -175,6 +190,7 @@ function expandMergedSlotToIndividual(product, slotDurationMinutes) {
175
190
  const price = priceMap.get(hm) ?? 0;
176
191
  result.push({
177
192
  resourceId,
193
+ productId,
178
194
  startTime: cursor.format("YYYY-MM-DD HH:mm"),
179
195
  endTime: slotEnd.format("YYYY-MM-DD HH:mm"),
180
196
  price: new import_decimal.default(price).toFixed(2)
@@ -189,6 +205,7 @@ function expandMergedSlotToIndividual(product, slotDurationMinutes) {
189
205
  const slotEnd = cursor.add(slotDurationMinutes, "minute");
190
206
  result.push({
191
207
  resourceId,
208
+ productId,
192
209
  startTime: cursor.format("YYYY-MM-DD HH:mm"),
193
210
  endTime: slotEnd.format("YYYY-MM-DD HH:mm"),
194
211
  price: perSlotPrice
@@ -26,7 +26,7 @@ export declare function buildTimeSlotGrid(params: {
26
26
  date: string;
27
27
  config: VenueBookingSlotConfig;
28
28
  rawResources: VenueResourceRawData[];
29
- resourceProductMap: Map<number | string, ResourceProductMapping>;
29
+ resourceProductMap: Map<number | string, ResourceProductMapping[]>;
30
30
  quotationPriceMap?: Map<string, string | null>;
31
31
  }): VenueTimeSlotGrid;
32
32
  export {};
@@ -38,6 +38,7 @@ __export(timeSlot_exports, {
38
38
  });
39
39
  module.exports = __toCommonJS(timeSlot_exports);
40
40
  var import_dayjs = __toESM(require("dayjs"));
41
+ var import_decimal = __toESM(require("decimal.js"));
41
42
  function isBusinessHoursCrossDay(config) {
42
43
  const [startH, startM] = config.businessStartTime.split(":").map(Number);
43
44
  const [endH, endM] = config.businessEndTime.split(":").map(Number);
@@ -122,64 +123,202 @@ function computeSlotStatus(params) {
122
123
  return { status: "partially_occupied", remainingCapacity: remaining };
123
124
  return { status: "available", remainingCapacity: remaining };
124
125
  }
126
+ function mergeSubSlots(subSlots) {
127
+ const priority = {
128
+ available: 5,
129
+ partially_occupied: 4,
130
+ occupied: 3,
131
+ unavailable: 2,
132
+ past: 1
133
+ };
134
+ let best = subSlots[0];
135
+ for (const slot of subSlots) {
136
+ if ((priority[slot.status] ?? 0) > (priority[best.status] ?? 0))
137
+ best = slot;
138
+ }
139
+ let minPrice = null;
140
+ for (const slot of subSlots) {
141
+ if (slot.price == null)
142
+ continue;
143
+ const decimal = new import_decimal.default(slot.price || "0");
144
+ if (!minPrice || decimal.lt(minPrice))
145
+ minPrice = decimal;
146
+ }
147
+ return {
148
+ startTime: best.startTime,
149
+ endTime: best.endTime,
150
+ status: best.status,
151
+ price: minPrice ? minPrice.toFixed(2) : null,
152
+ resourceId: best.resourceId,
153
+ resourceFormId: best.resourceFormId,
154
+ capacity: best.capacity,
155
+ remainingCapacity: best.remainingCapacity
156
+ };
157
+ }
158
+ function buildProductSlots(params) {
159
+ const {
160
+ date,
161
+ config,
162
+ resource,
163
+ mapping,
164
+ timeLabels,
165
+ timesForDate,
166
+ events,
167
+ resCapacity,
168
+ now,
169
+ crossDay,
170
+ quotationPriceMap,
171
+ childRawResources,
172
+ childTimesCache,
173
+ childEventsCache,
174
+ config_businessStartHour
175
+ } = params;
176
+ const slots = [];
177
+ for (const label of timeLabels) {
178
+ const [h] = label.split(":").map(Number);
179
+ const isNextDay = crossDay && h < config_businessStartHour;
180
+ const slotDate = isNextDay ? (0, import_dayjs.default)(date).add(1, "day").format("YYYY-MM-DD") : date;
181
+ const slotStart = (0, import_dayjs.default)(`${slotDate} ${label}`);
182
+ const slotEnd = slotStart.add(config.slotDurationMinutes, "minute");
183
+ let status;
184
+ let remainingCapacity = null;
185
+ if (slotStart.isBefore(now)) {
186
+ status = "past";
187
+ } else if (!isSlotWithinResourceTimes(slotStart, slotEnd, timesForDate)) {
188
+ status = "unavailable";
189
+ } else {
190
+ const result = computeSlotStatus({
191
+ slotStart,
192
+ slotEnd,
193
+ events,
194
+ resourceType: mapping.resourceType,
195
+ capacity: resCapacity
196
+ });
197
+ status = result.status;
198
+ remainingCapacity = result.remainingCapacity;
199
+ if (status !== "occupied" && childRawResources && childRawResources.length) {
200
+ for (let i = 0; i < childRawResources.length; i++) {
201
+ const child = childRawResources[i];
202
+ const childTimes = (childTimesCache == null ? void 0 : childTimesCache[i]) ?? getResourceTimesForDate(child, date, config);
203
+ const childEvents = (childEventsCache == null ? void 0 : childEventsCache[i]) ?? collectEventsForDate(child, date, config);
204
+ if (!isSlotWithinResourceTimes(slotStart, slotEnd, childTimes)) {
205
+ status = "unavailable";
206
+ remainingCapacity = null;
207
+ break;
208
+ }
209
+ const childType = child.type || "single";
210
+ const childResult = computeSlotStatus({
211
+ slotStart,
212
+ slotEnd,
213
+ events: childEvents,
214
+ resourceType: childType,
215
+ capacity: child.capacity ?? 1
216
+ });
217
+ if (childResult.status === "occupied") {
218
+ status = "occupied";
219
+ remainingCapacity = 0;
220
+ break;
221
+ }
222
+ if (childResult.status === "partially_occupied" && status === "available") {
223
+ status = "partially_occupied";
224
+ remainingCapacity = Math.min(
225
+ remainingCapacity ?? childResult.remainingCapacity,
226
+ childResult.remainingCapacity
227
+ );
228
+ }
229
+ }
230
+ }
231
+ }
232
+ const isBookable = status === "available" || status === "partially_occupied";
233
+ const slotStartStr = slotStart.format("YYYY-MM-DD HH:mm");
234
+ slots.push({
235
+ startTime: slotStartStr,
236
+ endTime: slotEnd.format("YYYY-MM-DD HH:mm"),
237
+ status,
238
+ price: isBookable ? (quotationPriceMap == null ? void 0 : quotationPriceMap.get(`${mapping.productId}:${slotStartStr}`)) ?? mapping.price : null,
239
+ resourceId: resource.resourceId,
240
+ resourceFormId: resource.formId,
241
+ capacity: status === "past" || status === "unavailable" ? null : resCapacity,
242
+ remainingCapacity,
243
+ productId: mapping.productId
244
+ });
245
+ }
246
+ return slots;
247
+ }
125
248
  function buildTimeSlotGrid(params) {
126
249
  const { date, config, rawResources, resourceProductMap, quotationPriceMap } = params;
127
250
  const timeLabels = generateTimeLabels(config);
128
251
  const now = (0, import_dayjs.default)();
129
252
  const crossDay = isBusinessHoursCrossDay(config);
253
+ const config_businessStartHour = Number(config.businessStartTime.split(":")[0]);
254
+ const rawResourceById = /* @__PURE__ */ new Map();
255
+ for (const item of rawResources)
256
+ rawResourceById.set(item.resourceId, item);
130
257
  const resources = [];
131
258
  for (const resource of rawResources) {
132
- const mapping = resourceProductMap.get(resource.resourceId);
133
- if (!mapping)
259
+ const mappings = resourceProductMap.get(resource.resourceId);
260
+ if (!mappings || !mappings.length)
134
261
  continue;
135
262
  const timesForDate = getResourceTimesForDate(resource, date, config);
136
263
  const events = collectEventsForDate(resource, date, config);
137
264
  const resCapacity = resource.capacity ?? 1;
138
- const slots = [];
139
- for (const label of timeLabels) {
140
- const [h, m] = label.split(":").map(Number);
141
- const isNextDay = crossDay && h < Number(config.businessStartTime.split(":")[0]);
142
- const slotDate = isNextDay ? (0, import_dayjs.default)(date).add(1, "day").format("YYYY-MM-DD") : date;
143
- const slotStart = (0, import_dayjs.default)(`${slotDate} ${label}`);
144
- const slotEnd = slotStart.add(config.slotDurationMinutes, "minute");
145
- let status;
146
- let remainingCapacity = null;
147
- if (slotStart.isBefore(now)) {
148
- status = "past";
149
- } else if (!isSlotWithinResourceTimes(slotStart, slotEnd, timesForDate)) {
150
- status = "unavailable";
151
- } else {
152
- const result = computeSlotStatus({
153
- slotStart,
154
- slotEnd,
155
- events,
156
- resourceType: mapping.resourceType,
157
- capacity: resCapacity
158
- });
159
- status = result.status;
160
- remainingCapacity = result.remainingCapacity;
161
- }
162
- const isBookable = status === "available" || status === "partially_occupied";
163
- const slotStartStr = slotStart.format("YYYY-MM-DD HH:mm");
164
- slots.push({
165
- startTime: slotStartStr,
166
- endTime: slotEnd.format("YYYY-MM-DD HH:mm"),
167
- status,
168
- price: isBookable ? (quotationPriceMap == null ? void 0 : quotationPriceMap.get(`${mapping.productId}:${slotStartStr}`)) ?? mapping.price : null,
169
- resourceId: resource.resourceId,
170
- resourceFormId: resource.formId,
171
- capacity: status === "past" || status === "unavailable" ? null : resCapacity,
172
- remainingCapacity
265
+ const combined = resource.combined_resource;
266
+ const isCombined = !!(combined && combined.status === 1 && Array.isArray(combined.resource_ids) && combined.resource_ids.length);
267
+ const childRawResources = isCombined ? combined.resource_ids.map((id) => rawResourceById.get(id)).filter((r) => !!r) : void 0;
268
+ const childTimesCache = childRawResources == null ? void 0 : childRawResources.map((child) => getResourceTimesForDate(child, date, config));
269
+ const childEventsCache = childRawResources == null ? void 0 : childRawResources.map((child) => collectEventsForDate(child, date, config));
270
+ const subRows = mappings.map((mapping) => {
271
+ const productSlots = buildProductSlots({
272
+ date,
273
+ config,
274
+ resource,
275
+ mapping,
276
+ timeLabels,
277
+ timesForDate,
278
+ events,
279
+ resCapacity,
280
+ now,
281
+ crossDay,
282
+ quotationPriceMap,
283
+ childRawResources,
284
+ childTimesCache,
285
+ childEventsCache,
286
+ config_businessStartHour
173
287
  });
288
+ return {
289
+ productId: mapping.productId,
290
+ productTitle: mapping.productTitle,
291
+ price: mapping.price,
292
+ slots: productSlots
293
+ };
294
+ });
295
+ const hasMultipleProducts = subRows.length > 1;
296
+ const primary = mappings[0];
297
+ let outerSlots;
298
+ if (hasMultipleProducts) {
299
+ outerSlots = timeLabels.map((_label, slotIndex) => {
300
+ const group = subRows.map((row2) => row2.slots[slotIndex]);
301
+ return mergeSubSlots(group);
302
+ });
303
+ } else {
304
+ outerSlots = subRows[0].slots.map((slot) => ({ ...slot, productId: void 0 }));
174
305
  }
175
- resources.push({
306
+ const row = {
176
307
  resourceId: resource.resourceId,
177
308
  resourceFormId: resource.formId,
178
- resourceName: resource.main_field || mapping.resourceName,
179
- productId: mapping.productId,
180
- productTitle: mapping.productTitle,
181
- slots
182
- });
309
+ resourceName: resource.main_field || primary.resourceName,
310
+ productId: primary.productId,
311
+ productTitle: primary.productTitle,
312
+ slots: outerSlots
313
+ };
314
+ if (hasMultipleProducts) {
315
+ row.products = subRows;
316
+ row.hasMultipleProducts = true;
317
+ }
318
+ if (isCombined && combined) {
319
+ row.combinedResource = { resourceIds: [...combined.resource_ids] };
320
+ }
321
+ resources.push(row);
183
322
  }
184
323
  const productOrder = /* @__PURE__ */ new Map();
185
324
  for (const row of resources) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.1.129",
4
+ "version": "2.1.130",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",