@pisell/pisellos 2.2.122 → 2.2.124

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.
@@ -1,3 +1,7 @@
1
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
2
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
4
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
1
5
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
6
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
7
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
@@ -41,6 +45,8 @@ import { filterBookingsFromOrders, sortBookings } from "./modules/order/utils/fi
41
45
 
42
46
  /** 预约列表查询订阅者 */
43
47
 
48
+ /** 非当天(远端)预约查询订阅者 */
49
+
44
50
  /** 平面图 GET 查询订阅者(列表 / id 详情 / code 详情) */
45
51
  /**
46
52
  * Server 类
@@ -78,6 +84,10 @@ var Server = /*#__PURE__*/function () {
78
84
  // ---- 订单 / 预约列表查询订阅者 ----
79
85
  _defineProperty(this, "orderQuerySubscribers", new Map());
80
86
  _defineProperty(this, "bookingQuerySubscribers", new Map());
87
+ _defineProperty(this, "bookingRemoteQuerySubscribers", new Map());
88
+ _defineProperty(this, "bookingRemoteCache", new Map());
89
+ _defineProperty(this, "BOOKING_REMOTE_CACHE_TTL_MS", 5 * 60 * 1000);
90
+ _defineProperty(this, "BOOKING_REMOTE_CACHE_MAX_ENTRIES", 80);
81
91
  _defineProperty(this, "floorPlanQuerySubscribers", new Map());
82
92
  // 模块注册表 - 定义所有可用的模块配置
83
93
  _defineProperty(this, "moduleRegistry", {
@@ -235,7 +245,7 @@ var Server = /*#__PURE__*/function () {
235
245
  */
236
246
  _defineProperty(this, "handleOrderList", /*#__PURE__*/function () {
237
247
  var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(_ref7) {
238
- var url, method, data, config, queryPayload, _ref9, callback, subscriberId;
248
+ var url, method, data, config, queryPayload, _ref9, callback, subscriberId, useLocal;
239
249
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
240
250
  while (1) switch (_context3.prev = _context3.next) {
241
251
  case 0:
@@ -243,9 +253,15 @@ var Server = /*#__PURE__*/function () {
243
253
  console.log('[Server] handleOrderList:', url, method, data, config);
244
254
  queryPayload = data && _typeof(data) === 'object' ? _objectSpread({}, data) : {};
245
255
  _ref9 = config || {}, callback = _ref9.callback, subscriberId = _ref9.subscriberId;
256
+ useLocal = _this.shouldUseLocalOrderQuery(queryPayload);
246
257
  _this.logInfo('handleOrderList: 开始处理订单列表请求', {
247
- data: queryPayload
258
+ data: queryPayload,
259
+ useLocal: useLocal
248
260
  });
261
+ if (!useLocal) {
262
+ _context3.next = 9;
263
+ break;
264
+ }
249
265
  if (subscriberId && typeof callback === 'function') {
250
266
  _this.orderQuerySubscribers.set(subscriberId, {
251
267
  callback: callback,
@@ -257,7 +273,16 @@ var Server = /*#__PURE__*/function () {
257
273
  });
258
274
  }
259
275
  return _context3.abrupt("return", _this.computeOrderQueryResult(queryPayload));
260
- case 7:
276
+ case 9:
277
+ if (subscriberId) {
278
+ _this.orderQuerySubscribers.delete(subscriberId);
279
+ _this.logInfo('handleOrderList: 已清理订阅者(走远端)', {
280
+ subscriberId: subscriberId,
281
+ remaining: _this.orderQuerySubscribers.size
282
+ });
283
+ }
284
+ return _context3.abrupt("return", _this.fetchOrderListFromAPI(queryPayload));
285
+ case 11:
261
286
  case "end":
262
287
  return _context3.stop();
263
288
  }
@@ -300,13 +325,18 @@ var Server = /*#__PURE__*/function () {
300
325
  return _ref11.apply(this, arguments);
301
326
  };
302
327
  }());
328
+ /**
329
+ * 日历(compact_fields)场景下要直接在 SSE 层排除的订单类型:
330
+ * 这些类型不会出现在日历上,拉取它们只会浪费带宽并增加前端过滤成本。
331
+ */
332
+ _defineProperty(this, "BOOKING_SALES_COMPACT_EXCLUDE_TYPES", ['virtual', 'shipping', 'delivery', 'pickup']);
303
333
  /**
304
334
  * 处理预约列表查询
305
335
  * 今天:注册订阅者 + 本地数据筛选;非今天:清理订阅者 + 走真实 API
306
336
  */
307
337
  _defineProperty(this, "handleBookingList", /*#__PURE__*/function () {
308
338
  var _ref14 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(_ref13) {
309
- var url, method, data, config, queryPayload, _ref15, callback, subscriberId, isToday;
339
+ var url, method, data, config, queryPayload, _ref15, callback, subscriberId, useLocal, withFields, requestPayload, cacheKey;
310
340
  return _regeneratorRuntime().wrap(function _callee5$(_context5) {
311
341
  while (1) switch (_context5.prev = _context5.next) {
312
342
  case 0:
@@ -314,15 +344,18 @@ var Server = /*#__PURE__*/function () {
314
344
  console.log('[Server] handleBookingList:', url, method, data, config);
315
345
  queryPayload = data && _typeof(data) === 'object' ? _objectSpread({}, data) : {};
316
346
  _ref15 = config || {}, callback = _ref15.callback, subscriberId = _ref15.subscriberId;
317
- isToday = _this.isBookingQueryForToday(queryPayload);
347
+ useLocal = _this.shouldUseLocalBookingQuery(queryPayload);
318
348
  _this.logInfo('handleBookingList: 开始处理预约列表请求', {
319
349
  data: queryPayload,
320
- isToday: isToday
350
+ useLocal: useLocal
321
351
  });
322
- if (!isToday) {
323
- _context5.next = 11;
352
+ if (!useLocal) {
353
+ _context5.next = 12;
324
354
  break;
325
355
  }
356
+ if (subscriberId) {
357
+ _this.bookingRemoteQuerySubscribers.delete(subscriberId);
358
+ }
326
359
  if (subscriberId && typeof callback === 'function') {
327
360
  _this.bookingQuerySubscribers.set(subscriberId, {
328
361
  callback: callback,
@@ -334,16 +367,33 @@ var Server = /*#__PURE__*/function () {
334
367
  });
335
368
  }
336
369
  return _context5.abrupt("return", _this.computeBookingQueryResult(queryPayload));
337
- case 11:
370
+ case 12:
338
371
  if (subscriberId) {
339
372
  _this.bookingQuerySubscribers.delete(subscriberId);
373
+ }
374
+ if (subscriberId && typeof callback === 'function') {
375
+ withFields = _this.resolveBookingSalesWith(queryPayload);
376
+ requestPayload = _this.normalizeBookingRemoteQueryPayload(queryPayload, withFields);
377
+ cacheKey = _this.buildBookingRemoteCacheKey(requestPayload);
378
+ _this.bookingRemoteQuerySubscribers.set(subscriberId, {
379
+ callback: callback,
380
+ context: queryPayload,
381
+ cacheKey: cacheKey
382
+ });
383
+ _this.logInfo('handleBookingList: 已注册订阅者(非今天)', {
384
+ subscriberId: subscriberId,
385
+ cacheKey: cacheKey,
386
+ totalSubscribers: _this.bookingRemoteQuerySubscribers.size
387
+ });
388
+ }
389
+ if (subscriberId) {
340
390
  _this.logInfo('handleBookingList: 已清理订阅者(非今天)', {
341
391
  subscriberId: subscriberId,
342
392
  remaining: _this.bookingQuerySubscribers.size
343
393
  });
344
394
  }
345
395
  return _context5.abrupt("return", _this.fetchBookingListFromAPI(queryPayload));
346
- case 13:
396
+ case 16:
347
397
  case "end":
348
398
  return _context5.stop();
349
399
  }
@@ -470,9 +520,11 @@ var Server = /*#__PURE__*/function () {
470
520
  _ref23 = data || {}, subscriberId = _ref23.subscriberId;
471
521
  if (subscriberId) {
472
522
  _this.bookingQuerySubscribers.delete(subscriberId);
523
+ _this.bookingRemoteQuerySubscribers.delete(subscriberId);
473
524
  _this.logInfo('handleUnsubscribeBookingQuery: 已移除订阅者', {
474
525
  subscriberId: subscriberId,
475
- remaining: _this.bookingQuerySubscribers.size
526
+ remainingLocal: _this.bookingQuerySubscribers.size,
527
+ remainingRemote: _this.bookingRemoteQuerySubscribers.size
476
528
  });
477
529
  }
478
530
  return _context8.abrupt("return", {
@@ -1115,6 +1167,7 @@ var Server = /*#__PURE__*/function () {
1115
1167
  this.core.effects.on(OrderHooks.onOrdersChanged, function () {
1116
1168
  _this3.recomputeAndNotifyOrderQuery();
1117
1169
  _this3.recomputeAndNotifyBookingQuery();
1170
+ _this3.syncBookingRemoteCacheFromOrderChanges();
1118
1171
  });
1119
1172
  duration = Date.now() - startTime;
1120
1173
  this.logInfo('Server 初始化完成', {
@@ -1539,28 +1592,401 @@ var Server = /*#__PURE__*/function () {
1539
1592
  }
1540
1593
  }
1541
1594
  }, {
1542
- key: "isBookingQueryForToday",
1595
+ key: "extractQueryDate",
1543
1596
  value:
1544
1597
  /**
1545
- * 判断预约查询的 sales_time_between 起始日期是否为今天
1598
+ * 从查询值中提取 YYYY-MM-DD 日期串。
1599
+ *
1600
+ * @example
1601
+ * this.extractQueryDate('2026-04-15 09:58:00') // => '2026-04-15'
1546
1602
  */
1547
- function isBookingQueryForToday(data) {
1603
+ function extractQueryDate(raw) {
1604
+ if (raw == null) return null;
1605
+ var date = dayjs(raw);
1606
+ if (date.isValid()) {
1607
+ return date.format('YYYY-MM-DD');
1608
+ }
1609
+ var text = String(raw).trim();
1610
+ if (!text) return null;
1611
+ return text.split('T')[0].split(' ')[0] || null;
1612
+ }
1613
+
1614
+ /**
1615
+ * 判断时间范围是否「开始和结束都不是今天」。
1616
+ *
1617
+ * @example
1618
+ * this.isRangeBothNotToday('2026-04-13', '2026-04-14') // => true
1619
+ */
1620
+ }, {
1621
+ key: "isRangeBothNotToday",
1622
+ value: function isRangeBothNotToday(startRaw, endRaw) {
1623
+ var startDate = this.extractQueryDate(startRaw);
1624
+ var endDate = this.extractQueryDate(endRaw);
1625
+ if (!startDate || !endDate) return false;
1626
+ var today = dayjs().format('YYYY-MM-DD');
1627
+ return startDate !== today && endDate !== today;
1628
+ }
1629
+
1630
+ /**
1631
+ * 订单查询是否走本地:
1632
+ * - 当 start_time 与 end_time 都不是今天时,走远端;
1633
+ * - 其余情况走本地。
1634
+ */
1635
+ }, {
1636
+ key: "shouldUseLocalOrderQuery",
1637
+ value: function shouldUseLocalOrderQuery(data) {
1638
+ return !this.isRangeBothNotToday(data === null || data === void 0 ? void 0 : data.start_time, data === null || data === void 0 ? void 0 : data.end_time);
1639
+ }
1640
+
1641
+ /**
1642
+ * 预约查询是否走本地:
1643
+ * - 当 sales_time_between 的开始和结束都不是今天时,走远端;
1644
+ * - 其余情况走本地。
1645
+ */
1646
+ }, {
1647
+ key: "shouldUseLocalBookingQuery",
1648
+ value: function shouldUseLocalBookingQuery(data) {
1548
1649
  var range = data === null || data === void 0 ? void 0 : data.sales_time_between;
1549
- if (!Array.isArray(range) || range.length < 1) return true;
1550
- var startDateStr = String(range[0]).split('T')[0].split(' ')[0];
1551
- var todayStr = dayjs().format('YYYY-MM-DD');
1552
- return startDateStr === todayStr;
1650
+ if (!Array.isArray(range) || range.length < 2) return true;
1651
+ return !this.isRangeBothNotToday(range[0], range[1]);
1553
1652
  }
1554
1653
 
1555
1654
  /**
1556
- * 非今天的预约查询:通过真实 API 获取数据,再做 flattenOrdersToBookings 拆分
1655
+ * 日历 SSE 精简 with:由调用方显式声明 compact_fields 决定
1656
+ * - compact_fields === true → 精简字段(周/月视图)
1657
+ * - 其余(false / 未传)→ ['all'](日视图/表格/平面图合并)
1557
1658
  */
1558
1659
  }, {
1559
- key: "fetchBookingListFromAPI",
1660
+ key: "resolveBookingSalesWith",
1661
+ value: function resolveBookingSalesWith(queryPayload) {
1662
+ if ((queryPayload === null || queryPayload === void 0 ? void 0 : queryPayload.compact_fields) === true) {
1663
+ return ['bookings:booking_id,start_date,start_time,end_date,end_time,holder,metadata,parent_id,item_type', 'customer:id,display_name,phone', 'products'
1664
+ // 'resources'
1665
+ ];
1666
+ }
1667
+ return ['all'];
1668
+ }
1669
+
1670
+ /**
1671
+ * 日历 SSE 精简 select:渲染 + filterBookingsFromOrders 所需的主表字段
1672
+ * business_code / payment_status 不直接用于渲染,但 matchOrder 过滤依赖
1673
+ */
1674
+ }, {
1675
+ key: "resolveBookingSalesSelect",
1676
+ value: function resolveBookingSalesSelect() {
1677
+ return 'status,payment_status,business_code,phone,customer_name,schedule_date,created_at,metadata';
1678
+ }
1679
+ }, {
1680
+ key: "normalizeBookingRemoteQueryPayload",
1681
+ value: function normalizeBookingRemoteQueryPayload(data, withFields) {
1682
+ var isFullWith = withFields.length === 1 && withFields[0] === 'all';
1683
+ var isCompact = (data === null || data === void 0 ? void 0 : data.compact_fields) === true;
1684
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, data), {}, {
1685
+ form_record_ids: undefined,
1686
+ enable_remote_memory_cache: undefined,
1687
+ compact_fields: undefined,
1688
+ with: withFields
1689
+ }, isFullWith ? {} : {
1690
+ select: this.resolveBookingSalesSelect()
1691
+ }), isCompact ? {
1692
+ exclude_types: this.BOOKING_SALES_COMPACT_EXCLUDE_TYPES
1693
+ } : {}), {}, {
1694
+ chunk_size: 50
1695
+ });
1696
+ }
1697
+
1698
+ /**
1699
+ * 远端预约查询内存缓存开关:默认 false,仅显式 true 才启用。
1700
+ */
1701
+ }, {
1702
+ key: "isBookingRemoteMemoryCacheEnabled",
1703
+ value: function isBookingRemoteMemoryCacheEnabled(queryPayload) {
1704
+ return (queryPayload === null || queryPayload === void 0 ? void 0 : queryPayload.enable_remote_memory_cache) === true;
1705
+ }
1706
+ }, {
1707
+ key: "stableSerialize",
1708
+ value: function stableSerialize(value) {
1709
+ var _this5 = this;
1710
+ if (value === null || value === undefined) return 'null';
1711
+ if (Array.isArray(value)) {
1712
+ return "[".concat(value.map(function (item) {
1713
+ return _this5.stableSerialize(item);
1714
+ }).join(','), "]");
1715
+ }
1716
+ if (_typeof(value) === 'object') {
1717
+ var obj = value;
1718
+ var keys = Object.keys(obj).filter(function (k) {
1719
+ return obj[k] !== undefined;
1720
+ }).sort();
1721
+ return "{".concat(keys.map(function (k) {
1722
+ return "".concat(JSON.stringify(k), ":").concat(_this5.stableSerialize(obj[k]));
1723
+ }).join(','), "}");
1724
+ }
1725
+ return JSON.stringify(value);
1726
+ }
1727
+ }, {
1728
+ key: "buildBookingRemoteCacheKey",
1729
+ value: function buildBookingRemoteCacheKey(payload) {
1730
+ return this.stableSerialize(payload);
1731
+ }
1732
+ }, {
1733
+ key: "parseBookingSalesRangeMeta",
1734
+ value: function parseBookingSalesRangeMeta(payload) {
1735
+ var range = payload === null || payload === void 0 ? void 0 : payload.sales_time_between;
1736
+ if (!Array.isArray(range) || range.length < 2) return null;
1737
+ var startAtMs = dayjs(range[0]).valueOf();
1738
+ var endAtMs = dayjs(range[1]).valueOf();
1739
+ if (!Number.isFinite(startAtMs) || !Number.isFinite(endAtMs)) return null;
1740
+ if (endAtMs <= startAtMs) return null;
1741
+ return {
1742
+ startAtMs: startAtMs,
1743
+ endAtMs: endAtMs
1744
+ };
1745
+ }
1746
+ }, {
1747
+ key: "readBookingRemoteCache",
1748
+ value: function readBookingRemoteCache(cacheKey) {
1749
+ var entry = this.bookingRemoteCache.get(cacheKey);
1750
+ if (!entry) return null;
1751
+ if (entry.stale) {
1752
+ this.bookingRemoteCache.delete(cacheKey);
1753
+ return null;
1754
+ }
1755
+ var now = Date.now();
1756
+ if (now - entry.updatedAt > this.BOOKING_REMOTE_CACHE_TTL_MS) {
1757
+ this.bookingRemoteCache.delete(cacheKey);
1758
+ return null;
1759
+ }
1760
+ return entry;
1761
+ }
1762
+ }, {
1763
+ key: "writeBookingRemoteCache",
1764
+ value: function writeBookingRemoteCache(entry) {
1765
+ this.bookingRemoteCache.set(entry.key, entry);
1766
+ if (this.bookingRemoteCache.size <= this.BOOKING_REMOTE_CACHE_MAX_ENTRIES) {
1767
+ return;
1768
+ }
1769
+ var oldestKey = null;
1770
+ var oldestTime = Number.POSITIVE_INFINITY;
1771
+ var _iterator5 = _createForOfIteratorHelper(this.bookingRemoteCache.entries()),
1772
+ _step5;
1773
+ try {
1774
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
1775
+ var _step5$value = _slicedToArray(_step5.value, 2),
1776
+ key = _step5$value[0],
1777
+ cache = _step5$value[1];
1778
+ if (cache.updatedAt < oldestTime) {
1779
+ oldestTime = cache.updatedAt;
1780
+ oldestKey = key;
1781
+ }
1782
+ }
1783
+ } catch (err) {
1784
+ _iterator5.e(err);
1785
+ } finally {
1786
+ _iterator5.f();
1787
+ }
1788
+ if (oldestKey) this.bookingRemoteCache.delete(oldestKey);
1789
+ }
1790
+ }, {
1791
+ key: "toOrderIdKey",
1792
+ value: function toOrderIdKey(order) {
1793
+ if (!order || _typeof(order) !== 'object') return null;
1794
+ var raw = order.order_id;
1795
+ if (raw === undefined || raw === null || raw === '') return null;
1796
+ return String(raw);
1797
+ }
1798
+ }, {
1799
+ key: "markBookingRemoteCacheAllStale",
1800
+ value: function markBookingRemoteCacheAllStale(reason) {
1801
+ if (this.bookingRemoteCache.size === 0) return;
1802
+ var _iterator6 = _createForOfIteratorHelper(this.bookingRemoteCache.values()),
1803
+ _step6;
1804
+ try {
1805
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
1806
+ var entry = _step6.value;
1807
+ entry.stale = true;
1808
+ }
1809
+ } catch (err) {
1810
+ _iterator6.e(err);
1811
+ } finally {
1812
+ _iterator6.f();
1813
+ }
1814
+ this.logWarning('bookingRemoteCache: 全量标记失效', {
1815
+ reason: reason,
1816
+ cacheSize: this.bookingRemoteCache.size
1817
+ });
1818
+ }
1819
+ }, {
1820
+ key: "buildBookingResponse",
1821
+ value: function buildBookingResponse(bookingResult, extra) {
1822
+ return {
1823
+ code: 200,
1824
+ data: _objectSpread(_objectSpread({}, extra !== null && extra !== void 0 ? extra : {}), {}, {
1825
+ list: bookingResult.list || [],
1826
+ count: bookingResult.count || 0,
1827
+ size: bookingResult.size || 0,
1828
+ skip: bookingResult.skip || 0
1829
+ }),
1830
+ message: '',
1831
+ status: true
1832
+ };
1833
+ }
1834
+ }, {
1835
+ key: "notifyBookingRemoteSubscribersByCacheKey",
1836
+ value: function notifyBookingRemoteSubscribersByCacheKey(cacheKey, entry, reason) {
1837
+ if (this.bookingRemoteQuerySubscribers.size === 0) return;
1838
+ var _iterator7 = _createForOfIteratorHelper(this.bookingRemoteQuerySubscribers.entries()),
1839
+ _step7;
1840
+ try {
1841
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
1842
+ var _step7$value = _slicedToArray(_step7.value, 2),
1843
+ subscriberId = _step7$value[0],
1844
+ subscriber = _step7$value[1];
1845
+ if (subscriber.cacheKey !== cacheKey) continue;
1846
+ try {
1847
+ var callbackStartAt = Date.now();
1848
+ subscriber.callback(this.buildBookingResponse(entry.bookingResult, {
1849
+ cache_hit: true,
1850
+ from_cache_sync: true,
1851
+ sync_reason: reason
1852
+ }));
1853
+ var callbackEndAt = Date.now();
1854
+ this.logInfo('notifyBookingRemoteSubscribersByCacheKey: 已推送', {
1855
+ subscriberId: subscriberId,
1856
+ cacheKey: cacheKey,
1857
+ reason: reason,
1858
+ callbackDurationMs: callbackEndAt - callbackStartAt
1859
+ });
1860
+ } catch (error) {
1861
+ var errMsg = error instanceof Error ? error.message : String(error);
1862
+ this.logError('notifyBookingRemoteSubscribersByCacheKey: 推送失败', {
1863
+ subscriberId: subscriberId,
1864
+ cacheKey: cacheKey,
1865
+ reason: reason,
1866
+ error: errMsg
1867
+ });
1868
+ }
1869
+ }
1870
+ } catch (err) {
1871
+ _iterator7.e(err);
1872
+ } finally {
1873
+ _iterator7.f();
1874
+ }
1875
+ }
1876
+ }, {
1877
+ key: "syncBookingRemoteCacheFromOrderChanges",
1878
+ value: function syncBookingRemoteCacheFromOrderChanges() {
1879
+ var _this$order$getOrders, _this$order, _this$order$getOrders2;
1880
+ if (this.bookingRemoteCache.size === 0) return;
1881
+ var syncStartAt = Date.now();
1882
+ var latestOrders = (_this$order$getOrders = (_this$order = this.order) === null || _this$order === void 0 || (_this$order$getOrders2 = _this$order.getOrders) === null || _this$order$getOrders2 === void 0 ? void 0 : _this$order$getOrders2.call(_this$order)) !== null && _this$order$getOrders !== void 0 ? _this$order$getOrders : [];
1883
+ if (!Array.isArray(latestOrders) || latestOrders.length === 0) {
1884
+ this.markBookingRemoteCacheAllStale('orderStoreEmptyAfterChange');
1885
+ return;
1886
+ }
1887
+ var syncedEntryCount = 0;
1888
+ var _iterator8 = _createForOfIteratorHelper(this.bookingRemoteCache.entries()),
1889
+ _step8;
1890
+ try {
1891
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
1892
+ var _step8$value = _slicedToArray(_step8.value, 2),
1893
+ cacheKey = _step8$value[0],
1894
+ entry = _step8$value[1];
1895
+ if (entry.stale) {
1896
+ this.bookingRemoteCache.delete(cacheKey);
1897
+ continue;
1898
+ }
1899
+ try {
1900
+ var queryPayload = entry.queryPayload;
1901
+ var orderMap = new Map();
1902
+ var _iterator9 = _createForOfIteratorHelper(entry.rawOrders),
1903
+ _step9;
1904
+ try {
1905
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
1906
+ var order = _step9.value;
1907
+ var key = this.toOrderIdKey(order);
1908
+ if (key) orderMap.set(key, order);
1909
+ }
1910
+ } catch (err) {
1911
+ _iterator9.e(err);
1912
+ } finally {
1913
+ _iterator9.f();
1914
+ }
1915
+ var changed = false;
1916
+ var _iterator10 = _createForOfIteratorHelper(latestOrders),
1917
+ _step10;
1918
+ try {
1919
+ for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
1920
+ var latest = _step10.value;
1921
+ var _key = this.toOrderIdKey(latest);
1922
+ if (!_key) continue;
1923
+ if (orderMap.has(_key)) {
1924
+ orderMap.set(_key, latest);
1925
+ changed = true;
1926
+ continue;
1927
+ }
1928
+ orderMap.set(_key, latest);
1929
+ changed = true;
1930
+ }
1931
+ } catch (err) {
1932
+ _iterator10.e(err);
1933
+ } finally {
1934
+ _iterator10.f();
1935
+ }
1936
+ if (!changed) continue;
1937
+ var mergedOrders = _toConsumableArray(orderMap.values());
1938
+ var filterStartAt = Date.now();
1939
+ var bookingResult = sortBookings(filterBookingsFromOrders(mergedOrders, queryPayload), queryPayload);
1940
+ var filterEndAt = Date.now();
1941
+ var nextEntry = _objectSpread(_objectSpread({}, entry), {}, {
1942
+ rawOrders: mergedOrders,
1943
+ bookingResult: bookingResult,
1944
+ updatedAt: Date.now(),
1945
+ stale: false
1946
+ });
1947
+ this.writeBookingRemoteCache(nextEntry);
1948
+ this.notifyBookingRemoteSubscribersByCacheKey(cacheKey, nextEntry, 'orders_changed');
1949
+ syncedEntryCount += 1;
1950
+ this.logInfo('bookingRemoteCache: 单条缓存同步完成', {
1951
+ cacheKey: cacheKey,
1952
+ mergedOrderCount: mergedOrders.length,
1953
+ filteredBookingCount: bookingResult.count,
1954
+ filterDurationMs: filterEndAt - filterStartAt
1955
+ });
1956
+ } catch (error) {
1957
+ var errMsg = error instanceof Error ? error.message : String(error);
1958
+ this.logWarning('bookingRemoteCache: 同步失败并标记失效', {
1959
+ cacheKey: cacheKey,
1960
+ error: errMsg
1961
+ });
1962
+ var current = this.bookingRemoteCache.get(cacheKey);
1963
+ if (current) current.stale = true;
1964
+ }
1965
+ }
1966
+ } catch (err) {
1967
+ _iterator8.e(err);
1968
+ } finally {
1969
+ _iterator8.f();
1970
+ }
1971
+ var syncEndAt = Date.now();
1972
+ if (syncedEntryCount > 0) {
1973
+ this.logInfo('bookingRemoteCache: 已同步 Ably 变更', {
1974
+ syncedEntryCount: syncedEntryCount,
1975
+ cacheSize: this.bookingRemoteCache.size,
1976
+ totalSyncDurationMs: syncEndAt - syncStartAt
1977
+ });
1978
+ }
1979
+ }
1980
+
1981
+ /**
1982
+ * 非本地窗口的订单查询:走真实 API。
1983
+ */
1984
+ }, {
1985
+ key: "fetchOrderListFromAPI",
1560
1986
  value: (function () {
1561
- var _fetchBookingListFromAPI = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee18(data) {
1987
+ var _fetchOrderListFromAPI = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee18(data) {
1562
1988
  var _this$app2;
1563
- var _ref26, _response$data$list, _response$data, response, rawList, list, errorMessage;
1989
+ var _response$data, response, payload, list, count, errorMessage;
1564
1990
  return _regeneratorRuntime().wrap(function _callee18$(_context18) {
1565
1991
  while (1) switch (_context18.prev = _context18.next) {
1566
1992
  case 0:
@@ -1568,7 +1994,7 @@ var Server = /*#__PURE__*/function () {
1568
1994
  _context18.next = 3;
1569
1995
  break;
1570
1996
  }
1571
- this.logError('fetchBookingListFromAPI: app.request 不可用');
1997
+ this.logError('fetchOrderListFromAPI: app.request 不可用');
1572
1998
  return _context18.abrupt("return", {
1573
1999
  code: 500,
1574
2000
  message: 'app.request 不可用',
@@ -1581,24 +2007,19 @@ var Server = /*#__PURE__*/function () {
1581
2007
  case 3:
1582
2008
  _context18.prev = 3;
1583
2009
  _context18.next = 6;
1584
- return this.app.request.get('/shop/order/sales', _objectSpread(_objectSpread({}, data), {}, {
1585
- form_record_ids: undefined,
1586
- with: ["all"]
1587
- }), {
2010
+ return this.app.request.post('/shop/order/v2/list', data, {
1588
2011
  isShopApi: true
1589
2012
  });
1590
2013
  case 6:
1591
2014
  response = _context18.sent;
1592
- rawList = (_ref26 = (_response$data$list = response === null || response === void 0 || (_response$data = response.data) === null || _response$data === void 0 ? void 0 : _response$data.list) !== null && _response$data$list !== void 0 ? _response$data$list : response === null || response === void 0 ? void 0 : response.list) !== null && _ref26 !== void 0 ? _ref26 : [];
1593
- list = filterBookingsFromOrders(rawList, data);
1594
- this.logInfo('fetchBookingListFromAPI: API 返回并拆分完成', {
1595
- rawCount: rawList.length,
1596
- flattenedCount: list.count
1597
- });
2015
+ payload = (_response$data = response === null || response === void 0 ? void 0 : response.data) !== null && _response$data !== void 0 ? _response$data : response;
2016
+ list = Array.isArray(payload === null || payload === void 0 ? void 0 : payload.list) ? payload.list : [];
2017
+ count = typeof (payload === null || payload === void 0 ? void 0 : payload.count) === 'number' ? payload.count : list.length;
1598
2018
  return _context18.abrupt("return", {
1599
2019
  code: 200,
1600
- data: _objectSpread(_objectSpread({}, response.data), {}, {
1601
- list: (list === null || list === void 0 ? void 0 : list.list) || []
2020
+ data: _objectSpread(_objectSpread({}, payload), {}, {
2021
+ list: list,
2022
+ count: count
1602
2023
  }),
1603
2024
  message: '',
1604
2025
  status: true
@@ -1607,7 +2028,7 @@ var Server = /*#__PURE__*/function () {
1607
2028
  _context18.prev = 13;
1608
2029
  _context18.t0 = _context18["catch"](3);
1609
2030
  errorMessage = _context18.t0 instanceof Error ? _context18.t0.message : String(_context18.t0);
1610
- this.logError('fetchBookingListFromAPI: 请求失败', {
2031
+ this.logError('fetchOrderListFromAPI: 请求失败', {
1611
2032
  error: errorMessage
1612
2033
  });
1613
2034
  return _context18.abrupt("return", {
@@ -1625,7 +2046,135 @@ var Server = /*#__PURE__*/function () {
1625
2046
  }
1626
2047
  }, _callee18, this, [[3, 13]]);
1627
2048
  }));
1628
- function fetchBookingListFromAPI(_x21) {
2049
+ function fetchOrderListFromAPI(_x21) {
2050
+ return _fetchOrderListFromAPI.apply(this, arguments);
2051
+ }
2052
+ return fetchOrderListFromAPI;
2053
+ }()
2054
+ /**
2055
+ * 非今天的预约查询:通过 SSE 流式拉取订单,再做本地 booking 筛选展开
2056
+ */
2057
+ )
2058
+ }, {
2059
+ key: "fetchBookingListFromAPI",
2060
+ value: (function () {
2061
+ var _fetchBookingListFromAPI = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee19(data) {
2062
+ var memoryCacheEnabled, withFields, requestPayload, cacheKey, cached, rawList, bookingResult, _bookingResult$list, errorMessage;
2063
+ return _regeneratorRuntime().wrap(function _callee19$(_context19) {
2064
+ while (1) switch (_context19.prev = _context19.next) {
2065
+ case 0:
2066
+ if (this.order) {
2067
+ _context19.next = 3;
2068
+ break;
2069
+ }
2070
+ this.logError('fetchBookingListFromAPI: Order 模块不可用');
2071
+ return _context19.abrupt("return", {
2072
+ code: 500,
2073
+ message: 'Order 模块不可用',
2074
+ data: {
2075
+ list: [],
2076
+ count: 0
2077
+ },
2078
+ status: false
2079
+ });
2080
+ case 3:
2081
+ _context19.prev = 3;
2082
+ memoryCacheEnabled = this.isBookingRemoteMemoryCacheEnabled(data);
2083
+ withFields = this.resolveBookingSalesWith(data);
2084
+ requestPayload = this.normalizeBookingRemoteQueryPayload(data, withFields);
2085
+ cacheKey = this.buildBookingRemoteCacheKey(requestPayload);
2086
+ if (!memoryCacheEnabled) {
2087
+ _context19.next = 13;
2088
+ break;
2089
+ }
2090
+ cached = this.readBookingRemoteCache(cacheKey);
2091
+ if (!cached) {
2092
+ _context19.next = 13;
2093
+ break;
2094
+ }
2095
+ this.logInfo('fetchBookingListFromAPI: 命中内存缓存', {
2096
+ cacheKey: cacheKey,
2097
+ listCount: cached.bookingResult.count,
2098
+ withFields: cached.withFields
2099
+ });
2100
+ return _context19.abrupt("return", this.buildBookingResponse(cached.bookingResult, {
2101
+ cache_hit: true
2102
+ }));
2103
+ case 13:
2104
+ _context19.next = 15;
2105
+ return this.order.fetchOrdersBySSE(requestPayload);
2106
+ case 15:
2107
+ rawList = _context19.sent;
2108
+ bookingResult = sortBookings(filterBookingsFromOrders(rawList, data), data); // DEBUG: 挂到 window 上方便排查 SSE → 日历数据丢失问题
2109
+ if (typeof globalThis !== 'undefined') {
2110
+ globalThis.__SSE_BOOKING_DEBUG__ = {
2111
+ ts: new Date().toISOString(),
2112
+ sseRequestPayload: requestPayload,
2113
+ calendarFilters: data,
2114
+ rawOrderCount: rawList.length,
2115
+ rawOrderSample: rawList.slice(0, 2).map(function (o) {
2116
+ var _o$bookings, _o$bookings2, _o$bookings$0$resourc;
2117
+ return {
2118
+ order_id: o === null || o === void 0 ? void 0 : o.order_id,
2119
+ business_code: o === null || o === void 0 ? void 0 : o.business_code,
2120
+ status: o === null || o === void 0 ? void 0 : o.status,
2121
+ payment_status: o === null || o === void 0 ? void 0 : o.payment_status,
2122
+ bookingsCount: o === null || o === void 0 || (_o$bookings = o.bookings) === null || _o$bookings === void 0 ? void 0 : _o$bookings.length,
2123
+ firstBooking: o !== null && o !== void 0 && (_o$bookings2 = o.bookings) !== null && _o$bookings2 !== void 0 && _o$bookings2[0] ? {
2124
+ start_date: o.bookings[0].start_date,
2125
+ start_time: o.bookings[0].start_time,
2126
+ parent_id: o.bookings[0].parent_id,
2127
+ item_type: o.bookings[0].item_type,
2128
+ resourcesCount: (_o$bookings$0$resourc = o.bookings[0].resources) === null || _o$bookings$0$resourc === void 0 ? void 0 : _o$bookings$0$resourc.length
2129
+ } : null
2130
+ };
2131
+ }),
2132
+ filteredBookingCount: bookingResult.count,
2133
+ filteredListLength: (_bookingResult$list = bookingResult.list) === null || _bookingResult$list === void 0 ? void 0 : _bookingResult$list.length
2134
+ };
2135
+ }
2136
+ if (memoryCacheEnabled) {
2137
+ this.writeBookingRemoteCache({
2138
+ key: cacheKey,
2139
+ queryPayload: data,
2140
+ withFields: withFields,
2141
+ rawOrders: Array.isArray(rawList) ? rawList : [],
2142
+ bookingResult: bookingResult,
2143
+ updatedAt: Date.now(),
2144
+ stale: false,
2145
+ rangeMeta: this.parseBookingSalesRangeMeta(requestPayload)
2146
+ });
2147
+ }
2148
+ this.logInfo('fetchBookingListFromAPI: SSE 返回并拆分完成', {
2149
+ rawCount: rawList.length,
2150
+ flattenedCount: bookingResult.count,
2151
+ cacheKey: cacheKey,
2152
+ withFields: withFields
2153
+ });
2154
+ return _context19.abrupt("return", this.buildBookingResponse(bookingResult));
2155
+ case 23:
2156
+ _context19.prev = 23;
2157
+ _context19.t0 = _context19["catch"](3);
2158
+ errorMessage = _context19.t0 instanceof Error ? _context19.t0.message : String(_context19.t0);
2159
+ this.logError('fetchBookingListFromAPI: SSE 请求失败', {
2160
+ error: errorMessage
2161
+ });
2162
+ return _context19.abrupt("return", {
2163
+ code: 500,
2164
+ message: errorMessage,
2165
+ data: {
2166
+ list: [],
2167
+ count: 0
2168
+ },
2169
+ status: false
2170
+ });
2171
+ case 28:
2172
+ case "end":
2173
+ return _context19.stop();
2174
+ }
2175
+ }, _callee19, this, [[3, 23]]);
2176
+ }));
2177
+ function fetchBookingListFromAPI(_x22) {
1629
2178
  return _fetchBookingListFromAPI.apply(this, arguments);
1630
2179
  }
1631
2180
  return fetchBookingListFromAPI;
@@ -1740,24 +2289,24 @@ var Server = /*#__PURE__*/function () {
1740
2289
  }, {
1741
2290
  key: "recomputeAndNotifyFloorPlanQuery",
1742
2291
  value: (function () {
1743
- var _recomputeAndNotifyFloorPlanQuery = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee19() {
1744
- var _iterator5, _step5, _step5$value, subscriberId, sub, result, errorMessage;
1745
- return _regeneratorRuntime().wrap(function _callee19$(_context19) {
1746
- while (1) switch (_context19.prev = _context19.next) {
2292
+ var _recomputeAndNotifyFloorPlanQuery = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee20() {
2293
+ var _iterator11, _step11, _step11$value, subscriberId, sub, result, errorMessage;
2294
+ return _regeneratorRuntime().wrap(function _callee20$(_context20) {
2295
+ while (1) switch (_context20.prev = _context20.next) {
1747
2296
  case 0:
1748
2297
  if (!(this.floorPlanQuerySubscribers.size === 0)) {
1749
- _context19.next = 2;
2298
+ _context20.next = 2;
1750
2299
  break;
1751
2300
  }
1752
- return _context19.abrupt("return");
2301
+ return _context20.abrupt("return");
1753
2302
  case 2:
1754
2303
  this.logInfo('recomputeAndNotifyFloorPlanQuery: 开始推送', {
1755
2304
  subscriberCount: this.floorPlanQuerySubscribers.size
1756
2305
  });
1757
- _iterator5 = _createForOfIteratorHelper(this.floorPlanQuerySubscribers.entries());
2306
+ _iterator11 = _createForOfIteratorHelper(this.floorPlanQuerySubscribers.entries());
1758
2307
  try {
1759
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
1760
- _step5$value = _slicedToArray(_step5.value, 2), subscriberId = _step5$value[0], sub = _step5$value[1];
2308
+ for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) {
2309
+ _step11$value = _slicedToArray(_step11.value, 2), subscriberId = _step11$value[0], sub = _step11$value[1];
1761
2310
  try {
1762
2311
  result = this.computeFloorPlanQueryResult(sub.context);
1763
2312
  sub.callback(result);
@@ -1773,15 +2322,15 @@ var Server = /*#__PURE__*/function () {
1773
2322
  }
1774
2323
  }
1775
2324
  } catch (err) {
1776
- _iterator5.e(err);
2325
+ _iterator11.e(err);
1777
2326
  } finally {
1778
- _iterator5.f();
2327
+ _iterator11.f();
1779
2328
  }
1780
2329
  case 5:
1781
2330
  case "end":
1782
- return _context19.stop();
2331
+ return _context20.stop();
1783
2332
  }
1784
- }, _callee19, this);
2333
+ }, _callee20, this);
1785
2334
  }));
1786
2335
  function recomputeAndNotifyFloorPlanQuery() {
1787
2336
  return _recomputeAndNotifyFloorPlanQuery.apply(this, arguments);
@@ -1811,21 +2360,21 @@ var Server = /*#__PURE__*/function () {
1811
2360
  * filter 逻辑暂为 mock,仅记录参数
1812
2361
  */
1813
2362
  function () {
1814
- var _computeOrderQueryResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee20(data) {
2363
+ var _computeOrderQueryResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee21(data) {
1815
2364
  var rawList, result;
1816
- return _regeneratorRuntime().wrap(function _callee20$(_context20) {
1817
- while (1) switch (_context20.prev = _context20.next) {
2365
+ return _regeneratorRuntime().wrap(function _callee21$(_context21) {
2366
+ while (1) switch (_context21.prev = _context21.next) {
1818
2367
  case 0:
1819
2368
  this.logInfo('computeOrderQueryResult: 开始过滤', {
1820
2369
  data: data
1821
2370
  });
1822
2371
  console.log('[Server] computeOrderQueryResult', data);
1823
2372
  if (this.order) {
1824
- _context20.next = 5;
2373
+ _context21.next = 5;
1825
2374
  break;
1826
2375
  }
1827
2376
  this.logError('computeOrderQueryResult: Order 模块未注册');
1828
- return _context20.abrupt("return", {
2377
+ return _context21.abrupt("return", {
1829
2378
  code: 500,
1830
2379
  message: 'Order 模块未注册',
1831
2380
  data: {
@@ -1848,7 +2397,7 @@ var Server = /*#__PURE__*/function () {
1848
2397
  size: result.size,
1849
2398
  skip: result.skip
1850
2399
  });
1851
- return _context20.abrupt("return", {
2400
+ return _context21.abrupt("return", {
1852
2401
  code: 200,
1853
2402
  data: result,
1854
2403
  message: '',
@@ -1856,11 +2405,11 @@ var Server = /*#__PURE__*/function () {
1856
2405
  });
1857
2406
  case 10:
1858
2407
  case "end":
1859
- return _context20.stop();
2408
+ return _context21.stop();
1860
2409
  }
1861
- }, _callee20, this);
2410
+ }, _callee21, this);
1862
2411
  }));
1863
- function computeOrderQueryResult(_x22) {
2412
+ function computeOrderQueryResult(_x23) {
1864
2413
  return _computeOrderQueryResult.apply(this, arguments);
1865
2414
  }
1866
2415
  return computeOrderQueryResult;
@@ -1873,17 +2422,17 @@ var Server = /*#__PURE__*/function () {
1873
2422
  }, {
1874
2423
  key: "computeBookingQueryResult",
1875
2424
  value: (function () {
1876
- var _computeBookingQueryResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee21(data) {
2425
+ var _computeBookingQueryResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee22(data) {
1877
2426
  var rawOrders, result;
1878
- return _regeneratorRuntime().wrap(function _callee21$(_context21) {
1879
- while (1) switch (_context21.prev = _context21.next) {
2427
+ return _regeneratorRuntime().wrap(function _callee22$(_context22) {
2428
+ while (1) switch (_context22.prev = _context22.next) {
1880
2429
  case 0:
1881
2430
  if (this.order) {
1882
- _context21.next = 3;
2431
+ _context22.next = 3;
1883
2432
  break;
1884
2433
  }
1885
2434
  this.logError('computeBookingQueryResult: Order 模块未注册');
1886
- return _context21.abrupt("return", {
2435
+ return _context22.abrupt("return", {
1887
2436
  code: 500,
1888
2437
  message: 'Order 模块未注册',
1889
2438
  data: {
@@ -1902,7 +2451,7 @@ var Server = /*#__PURE__*/function () {
1902
2451
  size: result.size,
1903
2452
  skip: result.skip
1904
2453
  });
1905
- return _context21.abrupt("return", {
2454
+ return _context22.abrupt("return", {
1906
2455
  code: 200,
1907
2456
  data: result,
1908
2457
  message: '',
@@ -1910,11 +2459,11 @@ var Server = /*#__PURE__*/function () {
1910
2459
  });
1911
2460
  case 8:
1912
2461
  case "end":
1913
- return _context21.stop();
2462
+ return _context22.stop();
1914
2463
  }
1915
- }, _callee21, this);
2464
+ }, _callee22, this);
1916
2465
  }));
1917
- function computeBookingQueryResult(_x23) {
2466
+ function computeBookingQueryResult(_x24) {
1918
2467
  return _computeBookingQueryResult.apply(this, arguments);
1919
2468
  }
1920
2469
  return computeBookingQueryResult;
@@ -1930,12 +2479,12 @@ var Server = /*#__PURE__*/function () {
1930
2479
  }, {
1931
2480
  key: "computeProductQueryResult",
1932
2481
  value: (function () {
1933
- var _computeProductQueryResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee22(context, options) {
2482
+ var _computeProductQueryResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee23(context, options) {
1934
2483
  var _menu_list_ids$length3,
1935
- _this5 = this;
2484
+ _this6 = this;
1936
2485
  var tTotal, menu_list_ids, schedule_date, schedule_datetime, activeMenuList, tMenu, menuList, tPrice, allProductsWithPrice, tFilter, filteredProducts, tStatus, beforeStatusCount, tSort;
1937
- return _regeneratorRuntime().wrap(function _callee22$(_context22) {
1938
- while (1) switch (_context22.prev = _context22.next) {
2486
+ return _regeneratorRuntime().wrap(function _callee23$(_context23) {
2487
+ while (1) switch (_context23.prev = _context23.next) {
1939
2488
  case 0:
1940
2489
  tTotal = performance.now();
1941
2490
  menu_list_ids = context.menu_list_ids, schedule_date = context.schedule_date, schedule_datetime = context.schedule_datetime;
@@ -1946,11 +2495,11 @@ var Server = /*#__PURE__*/function () {
1946
2495
  changedIds: options === null || options === void 0 ? void 0 : options.changedIds
1947
2496
  });
1948
2497
  if (this.products) {
1949
- _context22.next = 6;
2498
+ _context23.next = 6;
1950
2499
  break;
1951
2500
  }
1952
2501
  this.logError('computeProductQueryResult: Products 模块未注册');
1953
- return _context22.abrupt("return", {
2502
+ return _context23.abrupt("return", {
1954
2503
  message: 'Products 模块未注册',
1955
2504
  data: {
1956
2505
  list: [],
@@ -1959,11 +2508,11 @@ var Server = /*#__PURE__*/function () {
1959
2508
  });
1960
2509
  case 6:
1961
2510
  if (this.menu) {
1962
- _context22.next = 9;
2511
+ _context23.next = 9;
1963
2512
  break;
1964
2513
  }
1965
2514
  this.logError('computeProductQueryResult: Menu 模块未注册');
1966
- return _context22.abrupt("return", {
2515
+ return _context23.abrupt("return", {
1967
2516
  message: 'Menu 模块未注册',
1968
2517
  data: {
1969
2518
  list: [],
@@ -1972,11 +2521,11 @@ var Server = /*#__PURE__*/function () {
1972
2521
  });
1973
2522
  case 9:
1974
2523
  if (this.schedule) {
1975
- _context22.next = 12;
2524
+ _context23.next = 12;
1976
2525
  break;
1977
2526
  }
1978
2527
  this.logError('computeProductQueryResult: Schedule 模块未注册');
1979
- return _context22.abrupt("return", {
2528
+ return _context23.abrupt("return", {
1980
2529
  message: 'Schedule 模块未注册',
1981
2530
  data: {
1982
2531
  list: [],
@@ -1989,8 +2538,8 @@ var Server = /*#__PURE__*/function () {
1989
2538
  tMenu = performance.now();
1990
2539
  menuList = this.menu.getMenuByIds(menu_list_ids);
1991
2540
  activeMenuList = menuList.filter(function (menu) {
1992
- var _this5$schedule;
1993
- return ((_this5$schedule = _this5.schedule) === null || _this5$schedule === void 0 ? void 0 : _this5$schedule.getDateIsInSchedule(schedule_datetime, menu.schedule)) || false;
2541
+ var _this6$schedule;
2542
+ return ((_this6$schedule = _this6.schedule) === null || _this6$schedule === void 0 ? void 0 : _this6$schedule.getDateIsInSchedule(schedule_datetime, menu.schedule)) || false;
1994
2543
  });
1995
2544
  perfMark('computeQuery.filterActiveMenu', performance.now() - tMenu, {
1996
2545
  totalMenu: menuList.length,
@@ -1998,14 +2547,14 @@ var Server = /*#__PURE__*/function () {
1998
2547
  });
1999
2548
  }
2000
2549
  tPrice = performance.now();
2001
- _context22.next = 17;
2550
+ _context23.next = 17;
2002
2551
  return this.products.getProductsWithPrice(schedule_date, {
2003
2552
  scheduleModule: this.getSchedule()
2004
2553
  }, {
2005
2554
  changedIds: options === null || options === void 0 ? void 0 : options.changedIds
2006
2555
  });
2007
2556
  case 17:
2008
- allProductsWithPrice = _context22.sent;
2557
+ allProductsWithPrice = _context23.sent;
2009
2558
  perfMark('computeQuery.getProductsWithPrice', performance.now() - tPrice, {
2010
2559
  count: allProductsWithPrice.length
2011
2560
  });
@@ -2043,7 +2592,7 @@ var Server = /*#__PURE__*/function () {
2043
2592
  filteredCount: filteredProducts.length,
2044
2593
  activeMenuCount: activeMenuList.length
2045
2594
  });
2046
- return _context22.abrupt("return", {
2595
+ return _context23.abrupt("return", {
2047
2596
  code: 200,
2048
2597
  data: {
2049
2598
  list: filteredProducts,
@@ -2054,11 +2603,11 @@ var Server = /*#__PURE__*/function () {
2054
2603
  });
2055
2604
  case 32:
2056
2605
  case "end":
2057
- return _context22.stop();
2606
+ return _context23.stop();
2058
2607
  }
2059
- }, _callee22, this);
2608
+ }, _callee23, this);
2060
2609
  }));
2061
- function computeProductQueryResult(_x24, _x25) {
2610
+ function computeProductQueryResult(_x25, _x26) {
2062
2611
  return _computeProductQueryResult.apply(this, arguments);
2063
2612
  }
2064
2613
  return computeProductQueryResult;
@@ -2073,72 +2622,72 @@ var Server = /*#__PURE__*/function () {
2073
2622
  }, {
2074
2623
  key: "recomputeAndNotifyProductQuery",
2075
2624
  value: (function () {
2076
- var _recomputeAndNotifyProductQuery = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee23(options) {
2077
- var _iterator6, _step6, _step6$value, subscriberId, subscriber, result, errorMessage;
2078
- return _regeneratorRuntime().wrap(function _callee23$(_context23) {
2079
- while (1) switch (_context23.prev = _context23.next) {
2625
+ var _recomputeAndNotifyProductQuery = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee24(options) {
2626
+ var _iterator12, _step12, _step12$value, subscriberId, subscriber, result, errorMessage;
2627
+ return _regeneratorRuntime().wrap(function _callee24$(_context24) {
2628
+ while (1) switch (_context24.prev = _context24.next) {
2080
2629
  case 0:
2081
2630
  if (!(this.productQuerySubscribers.size === 0)) {
2082
- _context23.next = 2;
2631
+ _context24.next = 2;
2083
2632
  break;
2084
2633
  }
2085
- return _context23.abrupt("return");
2634
+ return _context24.abrupt("return");
2086
2635
  case 2:
2087
2636
  this.logInfo('recomputeAndNotifyProductQuery: 开始推送', {
2088
2637
  subscriberCount: this.productQuerySubscribers.size,
2089
2638
  changedIds: options === null || options === void 0 ? void 0 : options.changedIds
2090
2639
  });
2091
- _iterator6 = _createForOfIteratorHelper(this.productQuerySubscribers.entries());
2092
- _context23.prev = 4;
2093
- _iterator6.s();
2640
+ _iterator12 = _createForOfIteratorHelper(this.productQuerySubscribers.entries());
2641
+ _context24.prev = 4;
2642
+ _iterator12.s();
2094
2643
  case 6:
2095
- if ((_step6 = _iterator6.n()).done) {
2096
- _context23.next = 22;
2644
+ if ((_step12 = _iterator12.n()).done) {
2645
+ _context24.next = 22;
2097
2646
  break;
2098
2647
  }
2099
- _step6$value = _slicedToArray(_step6.value, 2), subscriberId = _step6$value[0], subscriber = _step6$value[1];
2100
- _context23.prev = 8;
2101
- _context23.next = 11;
2648
+ _step12$value = _slicedToArray(_step12.value, 2), subscriberId = _step12$value[0], subscriber = _step12$value[1];
2649
+ _context24.prev = 8;
2650
+ _context24.next = 11;
2102
2651
  return this.computeProductQueryResult(subscriber.context, {
2103
2652
  changedIds: options === null || options === void 0 ? void 0 : options.changedIds
2104
2653
  });
2105
2654
  case 11:
2106
- result = _context23.sent;
2655
+ result = _context24.sent;
2107
2656
  subscriber.callback(result);
2108
2657
  this.logInfo('recomputeAndNotifyProductQuery: 已推送', {
2109
2658
  subscriberId: subscriberId
2110
2659
  });
2111
- _context23.next = 20;
2660
+ _context24.next = 20;
2112
2661
  break;
2113
2662
  case 16:
2114
- _context23.prev = 16;
2115
- _context23.t0 = _context23["catch"](8);
2116
- errorMessage = _context23.t0 instanceof Error ? _context23.t0.message : String(_context23.t0);
2663
+ _context24.prev = 16;
2664
+ _context24.t0 = _context24["catch"](8);
2665
+ errorMessage = _context24.t0 instanceof Error ? _context24.t0.message : String(_context24.t0);
2117
2666
  this.logError('recomputeAndNotifyProductQuery: 推送失败', {
2118
2667
  subscriberId: subscriberId,
2119
2668
  error: errorMessage
2120
2669
  });
2121
2670
  case 20:
2122
- _context23.next = 6;
2671
+ _context24.next = 6;
2123
2672
  break;
2124
2673
  case 22:
2125
- _context23.next = 27;
2674
+ _context24.next = 27;
2126
2675
  break;
2127
2676
  case 24:
2128
- _context23.prev = 24;
2129
- _context23.t1 = _context23["catch"](4);
2130
- _iterator6.e(_context23.t1);
2677
+ _context24.prev = 24;
2678
+ _context24.t1 = _context24["catch"](4);
2679
+ _iterator12.e(_context24.t1);
2131
2680
  case 27:
2132
- _context23.prev = 27;
2133
- _iterator6.f();
2134
- return _context23.finish(27);
2681
+ _context24.prev = 27;
2682
+ _iterator12.f();
2683
+ return _context24.finish(27);
2135
2684
  case 30:
2136
2685
  case "end":
2137
- return _context23.stop();
2686
+ return _context24.stop();
2138
2687
  }
2139
- }, _callee23, this, [[4, 24, 27, 30], [8, 16]]);
2688
+ }, _callee24, this, [[4, 24, 27, 30], [8, 16]]);
2140
2689
  }));
2141
- function recomputeAndNotifyProductQuery(_x26) {
2690
+ function recomputeAndNotifyProductQuery(_x27) {
2142
2691
  return _recomputeAndNotifyProductQuery.apply(this, arguments);
2143
2692
  }
2144
2693
  return recomputeAndNotifyProductQuery;
@@ -2150,67 +2699,82 @@ var Server = /*#__PURE__*/function () {
2150
2699
  }, {
2151
2700
  key: "recomputeAndNotifyOrderQuery",
2152
2701
  value: (function () {
2153
- var _recomputeAndNotifyOrderQuery = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee24() {
2154
- var _iterator7, _step7, _step7$value, subscriberId, subscriber, result, errorMessage;
2155
- return _regeneratorRuntime().wrap(function _callee24$(_context24) {
2156
- while (1) switch (_context24.prev = _context24.next) {
2702
+ var _recomputeAndNotifyOrderQuery = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee25() {
2703
+ var notifyStartAt, _iterator13, _step13, _step13$value, subscriberId, subscriber, computeStartAt, result, computeEndAt, callbackStartAt, callbackEndAt, errorMessage, notifyEndAt;
2704
+ return _regeneratorRuntime().wrap(function _callee25$(_context25) {
2705
+ while (1) switch (_context25.prev = _context25.next) {
2157
2706
  case 0:
2158
2707
  if (!(this.orderQuerySubscribers.size === 0)) {
2159
- _context24.next = 2;
2708
+ _context25.next = 2;
2160
2709
  break;
2161
2710
  }
2162
- return _context24.abrupt("return");
2711
+ return _context25.abrupt("return");
2163
2712
  case 2:
2713
+ notifyStartAt = Date.now();
2164
2714
  this.logInfo('recomputeAndNotifyOrderQuery: 开始推送', {
2165
- subscriberCount: this.orderQuerySubscribers.size
2715
+ subscriberCount: this.orderQuerySubscribers.size,
2716
+ notifyStartAt: new Date(notifyStartAt).toISOString()
2166
2717
  });
2167
- _iterator7 = _createForOfIteratorHelper(this.orderQuerySubscribers.entries());
2168
- _context24.prev = 4;
2169
- _iterator7.s();
2170
- case 6:
2171
- if ((_step7 = _iterator7.n()).done) {
2172
- _context24.next = 22;
2718
+ _iterator13 = _createForOfIteratorHelper(this.orderQuerySubscribers.entries());
2719
+ _context25.prev = 5;
2720
+ _iterator13.s();
2721
+ case 7:
2722
+ if ((_step13 = _iterator13.n()).done) {
2723
+ _context25.next = 27;
2173
2724
  break;
2174
2725
  }
2175
- _step7$value = _slicedToArray(_step7.value, 2), subscriberId = _step7$value[0], subscriber = _step7$value[1];
2176
- _context24.prev = 8;
2177
- _context24.next = 11;
2726
+ _step13$value = _slicedToArray(_step13.value, 2), subscriberId = _step13$value[0], subscriber = _step13$value[1];
2727
+ _context25.prev = 9;
2728
+ computeStartAt = Date.now();
2729
+ _context25.next = 13;
2178
2730
  return this.computeOrderQueryResult(subscriber.context);
2179
- case 11:
2180
- result = _context24.sent;
2731
+ case 13:
2732
+ result = _context25.sent;
2733
+ computeEndAt = Date.now();
2734
+ callbackStartAt = Date.now();
2181
2735
  subscriber.callback(result);
2736
+ callbackEndAt = Date.now();
2182
2737
  this.logInfo('recomputeAndNotifyOrderQuery: 已推送', {
2183
- subscriberId: subscriberId
2738
+ subscriberId: subscriberId,
2739
+ computeDurationMs: computeEndAt - computeStartAt,
2740
+ callbackDurationMs: callbackEndAt - callbackStartAt,
2741
+ totalDurationMs: callbackEndAt - computeStartAt
2184
2742
  });
2185
- _context24.next = 20;
2743
+ _context25.next = 25;
2186
2744
  break;
2187
- case 16:
2188
- _context24.prev = 16;
2189
- _context24.t0 = _context24["catch"](8);
2190
- errorMessage = _context24.t0 instanceof Error ? _context24.t0.message : String(_context24.t0);
2745
+ case 21:
2746
+ _context25.prev = 21;
2747
+ _context25.t0 = _context25["catch"](9);
2748
+ errorMessage = _context25.t0 instanceof Error ? _context25.t0.message : String(_context25.t0);
2191
2749
  this.logError('recomputeAndNotifyOrderQuery: 推送失败', {
2192
2750
  subscriberId: subscriberId,
2193
2751
  error: errorMessage
2194
2752
  });
2195
- case 20:
2196
- _context24.next = 6;
2197
- break;
2198
- case 22:
2199
- _context24.next = 27;
2753
+ case 25:
2754
+ _context25.next = 7;
2200
2755
  break;
2201
- case 24:
2202
- _context24.prev = 24;
2203
- _context24.t1 = _context24["catch"](4);
2204
- _iterator7.e(_context24.t1);
2205
2756
  case 27:
2206
- _context24.prev = 27;
2207
- _iterator7.f();
2208
- return _context24.finish(27);
2209
- case 30:
2757
+ _context25.next = 32;
2758
+ break;
2759
+ case 29:
2760
+ _context25.prev = 29;
2761
+ _context25.t1 = _context25["catch"](5);
2762
+ _iterator13.e(_context25.t1);
2763
+ case 32:
2764
+ _context25.prev = 32;
2765
+ _iterator13.f();
2766
+ return _context25.finish(32);
2767
+ case 35:
2768
+ notifyEndAt = Date.now();
2769
+ this.logInfo('recomputeAndNotifyOrderQuery: 推送完成', {
2770
+ subscriberCount: this.orderQuerySubscribers.size,
2771
+ totalNotifyDurationMs: notifyEndAt - notifyStartAt
2772
+ });
2773
+ case 37:
2210
2774
  case "end":
2211
- return _context24.stop();
2775
+ return _context25.stop();
2212
2776
  }
2213
- }, _callee24, this, [[4, 24, 27, 30], [8, 16]]);
2777
+ }, _callee25, this, [[5, 29, 32, 35], [9, 21]]);
2214
2778
  }));
2215
2779
  function recomputeAndNotifyOrderQuery() {
2216
2780
  return _recomputeAndNotifyOrderQuery.apply(this, arguments);
@@ -2224,67 +2788,67 @@ var Server = /*#__PURE__*/function () {
2224
2788
  }, {
2225
2789
  key: "recomputeAndNotifyBookingQuery",
2226
2790
  value: (function () {
2227
- var _recomputeAndNotifyBookingQuery = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee25() {
2228
- var _iterator8, _step8, _step8$value, subscriberId, subscriber, result, errorMessage;
2229
- return _regeneratorRuntime().wrap(function _callee25$(_context25) {
2230
- while (1) switch (_context25.prev = _context25.next) {
2791
+ var _recomputeAndNotifyBookingQuery = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee26() {
2792
+ var _iterator14, _step14, _step14$value, subscriberId, subscriber, result, errorMessage;
2793
+ return _regeneratorRuntime().wrap(function _callee26$(_context26) {
2794
+ while (1) switch (_context26.prev = _context26.next) {
2231
2795
  case 0:
2232
2796
  if (!(this.bookingQuerySubscribers.size === 0)) {
2233
- _context25.next = 2;
2797
+ _context26.next = 2;
2234
2798
  break;
2235
2799
  }
2236
- return _context25.abrupt("return");
2800
+ return _context26.abrupt("return");
2237
2801
  case 2:
2238
2802
  this.logInfo('recomputeAndNotifyBookingQuery: 开始推送', {
2239
2803
  subscriberCount: this.bookingQuerySubscribers.size
2240
2804
  });
2241
- _iterator8 = _createForOfIteratorHelper(this.bookingQuerySubscribers.entries());
2242
- _context25.prev = 4;
2243
- _iterator8.s();
2805
+ _iterator14 = _createForOfIteratorHelper(this.bookingQuerySubscribers.entries());
2806
+ _context26.prev = 4;
2807
+ _iterator14.s();
2244
2808
  case 6:
2245
- if ((_step8 = _iterator8.n()).done) {
2246
- _context25.next = 22;
2809
+ if ((_step14 = _iterator14.n()).done) {
2810
+ _context26.next = 22;
2247
2811
  break;
2248
2812
  }
2249
- _step8$value = _slicedToArray(_step8.value, 2), subscriberId = _step8$value[0], subscriber = _step8$value[1];
2250
- _context25.prev = 8;
2251
- _context25.next = 11;
2813
+ _step14$value = _slicedToArray(_step14.value, 2), subscriberId = _step14$value[0], subscriber = _step14$value[1];
2814
+ _context26.prev = 8;
2815
+ _context26.next = 11;
2252
2816
  return this.computeBookingQueryResult(subscriber.context);
2253
2817
  case 11:
2254
- result = _context25.sent;
2818
+ result = _context26.sent;
2255
2819
  subscriber.callback(result);
2256
2820
  this.logInfo('recomputeAndNotifyBookingQuery: 已推送', {
2257
2821
  subscriberId: subscriberId
2258
2822
  });
2259
- _context25.next = 20;
2823
+ _context26.next = 20;
2260
2824
  break;
2261
2825
  case 16:
2262
- _context25.prev = 16;
2263
- _context25.t0 = _context25["catch"](8);
2264
- errorMessage = _context25.t0 instanceof Error ? _context25.t0.message : String(_context25.t0);
2826
+ _context26.prev = 16;
2827
+ _context26.t0 = _context26["catch"](8);
2828
+ errorMessage = _context26.t0 instanceof Error ? _context26.t0.message : String(_context26.t0);
2265
2829
  this.logError('recomputeAndNotifyBookingQuery: 推送失败', {
2266
2830
  subscriberId: subscriberId,
2267
2831
  error: errorMessage
2268
2832
  });
2269
2833
  case 20:
2270
- _context25.next = 6;
2834
+ _context26.next = 6;
2271
2835
  break;
2272
2836
  case 22:
2273
- _context25.next = 27;
2837
+ _context26.next = 27;
2274
2838
  break;
2275
2839
  case 24:
2276
- _context25.prev = 24;
2277
- _context25.t1 = _context25["catch"](4);
2278
- _iterator8.e(_context25.t1);
2840
+ _context26.prev = 24;
2841
+ _context26.t1 = _context26["catch"](4);
2842
+ _iterator14.e(_context26.t1);
2279
2843
  case 27:
2280
- _context25.prev = 27;
2281
- _iterator8.f();
2282
- return _context25.finish(27);
2844
+ _context26.prev = 27;
2845
+ _iterator14.f();
2846
+ return _context26.finish(27);
2283
2847
  case 30:
2284
2848
  case "end":
2285
- return _context25.stop();
2849
+ return _context26.stop();
2286
2850
  }
2287
- }, _callee25, this, [[4, 24, 27, 30], [8, 16]]);
2851
+ }, _callee26, this, [[4, 24, 27, 30], [8, 16]]);
2288
2852
  }));
2289
2853
  function recomputeAndNotifyBookingQuery() {
2290
2854
  return _recomputeAndNotifyBookingQuery.apply(this, arguments);
@@ -2316,11 +2880,11 @@ var Server = /*#__PURE__*/function () {
2316
2880
  var allowedProductIds = new Set();
2317
2881
  var allowedCollectionIds = new Set();
2318
2882
  var hasProductAll = false;
2319
- var _iterator9 = _createForOfIteratorHelper(activeMenuList),
2320
- _step9;
2883
+ var _iterator15 = _createForOfIteratorHelper(activeMenuList),
2884
+ _step15;
2321
2885
  try {
2322
- for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
2323
- var menu = _step9.value;
2886
+ for (_iterator15.s(); !(_step15 = _iterator15.n()).done;) {
2887
+ var menu = _step15.value;
2324
2888
  var config = menu.partyroom_package;
2325
2889
  if (!config) {
2326
2890
  console.warn('[Server] 餐牌缺少 partyroom_package 配置:', menu);
@@ -2380,9 +2944,9 @@ var Server = /*#__PURE__*/function () {
2380
2944
 
2381
2945
  // 如果有餐牌允许所有商品,返回所有商品
2382
2946
  } catch (err) {
2383
- _iterator9.e(err);
2947
+ _iterator15.e(err);
2384
2948
  } finally {
2385
- _iterator9.f();
2949
+ _iterator15.f();
2386
2950
  }
2387
2951
  if (hasProductAll) {
2388
2952
  this.logInfo('filterProductsByMenuConfig: 返回所有商品(product_all)', {