@pisell/pisellos 0.0.479 → 0.0.481

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 (147) hide show
  1. package/dist/core/index.d.ts +3 -2
  2. package/dist/core/index.js +7 -0
  3. package/dist/effects/index.d.ts +2 -2
  4. package/dist/effects/index.js +34 -81
  5. package/dist/model/strategy/adapter/promotion/evaluator.js +99 -26
  6. package/dist/model/strategy/adapter/walletPass/type.d.ts +9 -2
  7. package/dist/model/strategy/adapter/walletPass/utils.d.ts +6 -6
  8. package/dist/model/strategy/adapter/walletPass/utils.js +111 -72
  9. package/dist/modules/Customer/index.js +1 -1
  10. package/dist/modules/Discount/index.d.ts +6 -2
  11. package/dist/modules/Discount/index.js +14 -8
  12. package/dist/modules/Order/index.d.ts +1 -1
  13. package/dist/modules/Order/index.js +18 -13
  14. package/dist/modules/Payment/index.d.ts +4 -0
  15. package/dist/modules/Payment/index.js +774 -649
  16. package/dist/modules/Payment/walletpass.js +44 -17
  17. package/dist/modules/Product/index.d.ts +1 -1
  18. package/dist/modules/Product/types.d.ts +2 -0
  19. package/dist/modules/ProductList/index.d.ts +3 -0
  20. package/dist/modules/ProductList/index.js +9 -7
  21. package/dist/modules/Rules/index.d.ts +2 -2
  22. package/dist/modules/Rules/index.js +37 -31
  23. package/dist/modules/Rules/types.d.ts +2 -2
  24. package/dist/modules/Schedule/index.d.ts +9 -0
  25. package/dist/modules/Schedule/index.js +15 -2
  26. package/dist/plugins/app-types/app/app.d.ts +1 -0
  27. package/dist/plugins/request.d.ts +2 -0
  28. package/dist/server/index.d.ts +107 -2
  29. package/dist/server/index.js +1507 -279
  30. package/dist/server/modules/index.d.ts +6 -0
  31. package/dist/server/modules/index.js +7 -0
  32. package/dist/server/modules/menu/index.d.ts +19 -0
  33. package/dist/server/modules/menu/index.js +221 -71
  34. package/dist/server/modules/order/index.d.ts +87 -0
  35. package/dist/server/modules/order/index.js +916 -0
  36. package/dist/server/modules/order/types.d.ts +530 -0
  37. package/dist/server/modules/order/types.js +141 -0
  38. package/dist/server/modules/order/utils/filterBookings.d.ts +6 -0
  39. package/dist/server/modules/order/utils/filterBookings.js +350 -0
  40. package/dist/server/modules/order/utils/filterOrders.d.ts +15 -0
  41. package/dist/server/modules/order/utils/filterOrders.js +226 -0
  42. package/dist/server/modules/products/index.d.ts +117 -5
  43. package/dist/server/modules/products/index.js +1450 -240
  44. package/dist/server/modules/products/types.d.ts +25 -1
  45. package/dist/server/modules/products/types.js +3 -0
  46. package/dist/server/modules/resource/index.d.ts +86 -0
  47. package/dist/server/modules/resource/index.js +1128 -0
  48. package/dist/server/modules/resource/types.d.ts +121 -0
  49. package/dist/server/modules/resource/types.js +47 -0
  50. package/dist/server/modules/schedule/index.d.ts +19 -0
  51. package/dist/server/modules/schedule/index.js +229 -68
  52. package/dist/server/utils/product.d.ts +5 -0
  53. package/dist/server/utils/product.js +71 -31
  54. package/dist/solution/BookingTicket/index.d.ts +10 -2
  55. package/dist/solution/BookingTicket/index.js +41 -28
  56. package/dist/solution/BookingTicket/utils/scan/index.js +1 -1
  57. package/dist/solution/Checkout/index.d.ts +1 -0
  58. package/dist/solution/Checkout/index.js +286 -188
  59. package/dist/solution/Checkout/utils/index.d.ts +2 -1
  60. package/dist/solution/Checkout/utils/index.js +6 -4
  61. package/dist/solution/RegisterAndLogin/config.js +340 -1
  62. package/dist/solution/Sales/index.d.ts +96 -0
  63. package/dist/solution/Sales/index.js +566 -0
  64. package/dist/solution/Sales/types.d.ts +67 -0
  65. package/dist/solution/Sales/types.js +26 -0
  66. package/dist/solution/ShopDiscount/index.d.ts +1 -0
  67. package/dist/solution/ShopDiscount/index.js +35 -22
  68. package/dist/solution/ShopDiscount/types.d.ts +6 -0
  69. package/dist/solution/ShopDiscount/utils.d.ts +9 -0
  70. package/dist/solution/ShopDiscount/utils.js +21 -27
  71. package/dist/solution/index.d.ts +2 -1
  72. package/dist/solution/index.js +2 -1
  73. package/dist/types/index.d.ts +5 -0
  74. package/lib/core/index.d.ts +3 -2
  75. package/lib/core/index.js +4 -0
  76. package/lib/effects/index.d.ts +2 -2
  77. package/lib/effects/index.js +22 -31
  78. package/lib/model/strategy/adapter/promotion/evaluator.js +57 -8
  79. package/lib/model/strategy/adapter/walletPass/type.d.ts +9 -2
  80. package/lib/model/strategy/adapter/walletPass/utils.d.ts +6 -6
  81. package/lib/model/strategy/adapter/walletPass/utils.js +115 -48
  82. package/lib/modules/Customer/index.js +1 -1
  83. package/lib/modules/Discount/index.d.ts +6 -2
  84. package/lib/modules/Discount/index.js +3 -1
  85. package/lib/modules/Order/index.d.ts +1 -1
  86. package/lib/modules/Order/index.js +20 -18
  87. package/lib/modules/Payment/index.d.ts +4 -0
  88. package/lib/modules/Payment/index.js +134 -66
  89. package/lib/modules/Payment/walletpass.js +23 -4
  90. package/lib/modules/Product/index.d.ts +1 -1
  91. package/lib/modules/Product/types.d.ts +2 -0
  92. package/lib/modules/ProductList/index.d.ts +3 -0
  93. package/lib/modules/ProductList/index.js +2 -2
  94. package/lib/modules/Rules/index.d.ts +2 -2
  95. package/lib/modules/Rules/index.js +69 -73
  96. package/lib/modules/Rules/types.d.ts +2 -2
  97. package/lib/modules/Schedule/index.d.ts +9 -0
  98. package/lib/modules/Schedule/index.js +11 -0
  99. package/lib/plugins/app-types/app/app.d.ts +1 -0
  100. package/lib/plugins/request.d.ts +2 -0
  101. package/lib/server/index.d.ts +107 -2
  102. package/lib/server/index.js +773 -51
  103. package/lib/server/modules/index.d.ts +6 -0
  104. package/lib/server/modules/index.js +16 -2
  105. package/lib/server/modules/menu/index.d.ts +19 -0
  106. package/lib/server/modules/menu/index.js +121 -2
  107. package/lib/server/modules/order/index.d.ts +87 -0
  108. package/lib/server/modules/order/index.js +543 -0
  109. package/lib/server/modules/order/types.d.ts +530 -0
  110. package/lib/server/modules/order/types.js +34 -0
  111. package/lib/server/modules/order/utils/filterBookings.d.ts +6 -0
  112. package/lib/server/modules/order/utils/filterBookings.js +320 -0
  113. package/lib/server/modules/order/utils/filterOrders.d.ts +15 -0
  114. package/lib/server/modules/order/utils/filterOrders.js +197 -0
  115. package/lib/server/modules/products/index.d.ts +117 -5
  116. package/lib/server/modules/products/index.js +799 -62
  117. package/lib/server/modules/products/types.d.ts +25 -1
  118. package/lib/server/modules/products/types.js +1 -0
  119. package/lib/server/modules/resource/index.d.ts +86 -0
  120. package/lib/server/modules/resource/index.js +557 -0
  121. package/lib/server/modules/resource/types.d.ts +121 -0
  122. package/lib/server/modules/resource/types.js +35 -0
  123. package/lib/server/modules/schedule/index.d.ts +19 -0
  124. package/lib/server/modules/schedule/index.js +141 -12
  125. package/lib/server/utils/product.d.ts +5 -0
  126. package/lib/server/utils/product.js +56 -27
  127. package/lib/solution/BookingTicket/index.d.ts +10 -2
  128. package/lib/solution/BookingTicket/index.js +10 -2
  129. package/lib/solution/BookingTicket/utils/scan/index.js +0 -1
  130. package/lib/solution/Checkout/index.d.ts +1 -0
  131. package/lib/solution/Checkout/index.js +399 -331
  132. package/lib/solution/Checkout/utils/index.d.ts +2 -1
  133. package/lib/solution/Checkout/utils/index.js +6 -4
  134. package/lib/solution/RegisterAndLogin/config.js +266 -1
  135. package/lib/solution/Sales/index.d.ts +96 -0
  136. package/lib/solution/Sales/index.js +416 -0
  137. package/lib/solution/Sales/types.d.ts +67 -0
  138. package/lib/solution/Sales/types.js +35 -0
  139. package/lib/solution/ShopDiscount/index.d.ts +1 -0
  140. package/lib/solution/ShopDiscount/index.js +14 -6
  141. package/lib/solution/ShopDiscount/types.d.ts +6 -0
  142. package/lib/solution/ShopDiscount/utils.d.ts +9 -0
  143. package/lib/solution/ShopDiscount/utils.js +6 -10
  144. package/lib/solution/index.d.ts +2 -1
  145. package/lib/solution/index.js +4 -2
  146. package/lib/types/index.d.ts +5 -0
  147. package/package.json +1 -1
@@ -77,7 +77,30 @@ export declare enum ProductsHooks {
77
77
  onProductsLoaded = "products:onProductsLoaded",
78
78
  onProductsChanged = "products:onProductsChanged",
79
79
  onProductSelected = "products:onProductSelected",
80
- onProductsPriceApplied = "products:onProductsPriceApplied"
80
+ onProductsPriceApplied = "products:onProductsPriceApplied",
81
+ /** pubsub 同步批次处理完成后触发,Server 层监听此事件重新计算并推送 */
82
+ onProductsSyncCompleted = "products:onProductsSyncCompleted"
83
+ }
84
+ /** pubsub 商品同步消息结构 */
85
+ export interface ProductSyncMessage {
86
+ shop_id?: number;
87
+ module?: string;
88
+ action?: string;
89
+ id?: number;
90
+ /** 批量操作的商品 ID 列表 */
91
+ ids?: number[];
92
+ /** 完整商品数据(普通字段修改时携带) */
93
+ body?: any;
94
+ /** 操作类型(如 "delete" 表示删除) */
95
+ operation?: string;
96
+ /** 变更字段类型(如 ["price"]、["stock"]) */
97
+ change_types?: string[];
98
+ /** 关联商品 ID(product_collection / product_category / product_quotation 变更时携带) */
99
+ relation_product_ids?: number[];
100
+ message_uuid?: string;
101
+ timestamp?: string;
102
+ /** 内部标记:来源频道 key */
103
+ _channelKey?: string;
81
104
  }
82
105
  /**
83
106
  * 商品格式化器上下文
@@ -86,6 +109,7 @@ export interface ProductFormatterContext {
86
109
  schedule_date: string;
87
110
  priceData?: LoadProductsPriceData[];
88
111
  scheduleModule?: any;
112
+ locale?: string;
89
113
  }
90
114
  /**
91
115
  * 商品格式化器类型
@@ -27,6 +27,7 @@ var ProductsHooks = /* @__PURE__ */ ((ProductsHooks2) => {
27
27
  ProductsHooks2["onProductsChanged"] = "products:onProductsChanged";
28
28
  ProductsHooks2["onProductSelected"] = "products:onProductSelected";
29
29
  ProductsHooks2["onProductsPriceApplied"] = "products:onProductsPriceApplied";
30
+ ProductsHooks2["onProductsSyncCompleted"] = "products:onProductsSyncCompleted";
30
31
  return ProductsHooks2;
31
32
  })(ProductsHooks || {});
32
33
  // Annotate the CommonJS export names for ESM import in node:
@@ -0,0 +1,86 @@
1
+ import { Module, ModuleOptions, PisellCore } from '../../../types';
2
+ import { BaseModule } from '../../../modules/BaseModule';
3
+ import { type ResourceBooking, type ResourceData, type ResourceId, type QueryOptions } from './types';
4
+ /**
5
+ * Resource 模块
6
+ */
7
+ export declare class ResourceModule extends BaseModule implements Module {
8
+ protected defaultName: string;
9
+ protected defaultVersion: string;
10
+ private store;
11
+ private dbManager;
12
+ private logger;
13
+ private resourceDataSource;
14
+ /** 倒排索引: resourceId -> ResourceBooking[] */
15
+ private resourceIdIndex;
16
+ /** 待处理的同步消息队列 */
17
+ private pendingSyncMessages;
18
+ private syncTimer?;
19
+ constructor(name?: string, version?: string);
20
+ initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
21
+ private logInfo;
22
+ private logError;
23
+ preload(): Promise<void>;
24
+ getRoutes(): never[];
25
+ destroy(): void;
26
+ /**
27
+ * 获取所有资源(支持 includeBookings 附加预订信息)
28
+ */
29
+ getResources(queryOptions?: QueryOptions): ResourceData[];
30
+ /**
31
+ * 根据 ID 获取单个资源
32
+ */
33
+ getResourceById(id: ResourceId, queryOptions?: QueryOptions): ResourceData | undefined;
34
+ /**
35
+ * 创建资源
36
+ */
37
+ createResource(data: Partial<ResourceData>): ResourceData;
38
+ /**
39
+ * 更新资源
40
+ */
41
+ updateResource(id: ResourceId, data: Partial<ResourceData>): ResourceData | undefined;
42
+ /**
43
+ * 删除资源
44
+ */
45
+ deleteResource(id: ResourceId): boolean;
46
+ /**
47
+ * 根据资源 ID 获取预订列表
48
+ */
49
+ getBookingsByResourceId(resourceId: ResourceId): ResourceBooking[];
50
+ /**
51
+ * 创建预订
52
+ */
53
+ createBooking(booking: Partial<ResourceBooking>): ResourceBooking;
54
+ /**
55
+ * 更新预订
56
+ */
57
+ updateBooking(id: ResourceId, data: Partial<ResourceBooking>): ResourceBooking | undefined;
58
+ /**
59
+ * 删除预订
60
+ */
61
+ deleteBooking(id: ResourceId): boolean;
62
+ /**
63
+ * 清空缓存
64
+ */
65
+ clear(): Promise<void>;
66
+ private attachBookingsToResource;
67
+ private normalizeResource;
68
+ private safeEmit;
69
+ private syncResourcesMap;
70
+ private syncBookingsIndex;
71
+ private rebuildBookingsIndex;
72
+ private getIdKey;
73
+ private loadResourcesByServer;
74
+ private loadResourcesFromSQLite;
75
+ private saveResourcesToSQLite;
76
+ private initResourceDataSource;
77
+ private setupResourceSync;
78
+ private processSyncMessages;
79
+ private fetchResourcesBySSE;
80
+ private removeResourcesByIds;
81
+ private mergeResourcesToStore;
82
+ private uniqueResourceIds;
83
+ }
84
+ export declare const resourceModule: ResourceModule;
85
+ export type { ResourceData, ResourceBooking, ResourceState, ResourceId, ResourcePageQuery, ResourcePageResult, QueryOptions, ScheduleEventResource, } from './types';
86
+ export { ResourceHooks } from './types';
@@ -0,0 +1,557 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/server/modules/resource/index.ts
20
+ var resource_exports = {};
21
+ __export(resource_exports, {
22
+ ResourceHooks: () => import_types2.ResourceHooks,
23
+ ResourceModule: () => ResourceModule,
24
+ resourceModule: () => resourceModule
25
+ });
26
+ module.exports = __toCommonJS(resource_exports);
27
+ var import_lodash_es = require("lodash-es");
28
+ var import_BaseModule = require("../../../modules/BaseModule");
29
+ var import_types = require("./types");
30
+ var import_types2 = require("./types");
31
+ var RESOURCE_STORE_NAME = "resources";
32
+ var DEFAULT_PAGE_SIZE = 999;
33
+ var RESOURCE_SYNC_DEBOUNCE_MS = 1e4;
34
+ var ResourceModule = class extends import_BaseModule.BaseModule {
35
+ constructor(name, version) {
36
+ super(name, version);
37
+ this.defaultName = "resource";
38
+ this.defaultVersion = "1.0.0";
39
+ /** 倒排索引: resourceId -> ResourceBooking[] */
40
+ this.resourceIdIndex = /* @__PURE__ */ new Map();
41
+ /** 待处理的同步消息队列 */
42
+ this.pendingSyncMessages = [];
43
+ }
44
+ // ─────────────────────────────────────────────────────────────────
45
+ // 初始化 & 生命周期
46
+ // ─────────────────────────────────────────────────────────────────
47
+ async initialize(core, options) {
48
+ var _a, _b;
49
+ this.core = core;
50
+ this.store = options == null ? void 0 : options.store;
51
+ if (Array.isArray((_a = options == null ? void 0 : options.initialState) == null ? void 0 : _a.list)) {
52
+ this.store.list = ((_b = options == null ? void 0 : options.initialState) == null ? void 0 : _b.list).map(
53
+ (item) => this.normalizeResource(item)
54
+ );
55
+ this.syncResourcesMap();
56
+ this.core.effects.emit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
57
+ } else {
58
+ this.store.list = [];
59
+ this.store.map = /* @__PURE__ */ new Map();
60
+ }
61
+ if (!Array.isArray(this.store.bookings)) {
62
+ this.store.bookings = [];
63
+ }
64
+ const appPlugin = core.getPlugin("app");
65
+ if (appPlugin) {
66
+ const app = appPlugin.getApp();
67
+ this.dbManager = app.sqlite || app.dbManager;
68
+ this.logger = app.logger;
69
+ }
70
+ this.initResourceDataSource();
71
+ this.setupResourceSync();
72
+ }
73
+ logInfo(title, metadata) {
74
+ if (this.logger) {
75
+ this.logger.addLog({
76
+ type: "info",
77
+ title: `[ResourceModule] ${title}`,
78
+ metadata: metadata || {}
79
+ });
80
+ }
81
+ }
82
+ logError(title, error, metadata) {
83
+ if (this.logger) {
84
+ this.logger.addLog({
85
+ type: "error",
86
+ title: `[ResourceModule] ${title}`,
87
+ metadata: metadata || {}
88
+ });
89
+ }
90
+ }
91
+ async preload() {
92
+ const cachedResources = await this.loadResourcesFromSQLite();
93
+ if (cachedResources.length > 0) {
94
+ this.store.list = (0, import_lodash_es.cloneDeep)(cachedResources).map((item) => this.normalizeResource(item));
95
+ this.syncResourcesMap();
96
+ await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
97
+ } else {
98
+ const resources = await this.loadResourcesByServer();
99
+ if (resources.length > 0) {
100
+ this.store.list = (0, import_lodash_es.cloneDeep)(resources).map((item) => this.normalizeResource(item));
101
+ this.syncResourcesMap();
102
+ await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
103
+ }
104
+ }
105
+ }
106
+ getRoutes() {
107
+ return [];
108
+ }
109
+ destroy() {
110
+ var _a;
111
+ if (this.syncTimer) {
112
+ clearTimeout(this.syncTimer);
113
+ this.syncTimer = void 0;
114
+ }
115
+ this.pendingSyncMessages = [];
116
+ if ((_a = this.resourceDataSource) == null ? void 0 : _a.destroy)
117
+ this.resourceDataSource.destroy();
118
+ super.destroy();
119
+ }
120
+ // ─────────────────────────────────────────────────────────────────
121
+ // Resource CRUD
122
+ // ─────────────────────────────────────────────────────────────────
123
+ /**
124
+ * 获取所有资源(支持 includeBookings 附加预订信息)
125
+ */
126
+ getResources(queryOptions) {
127
+ this.logInfo("getResources", {
128
+ queryOptions
129
+ });
130
+ if (!(queryOptions == null ? void 0 : queryOptions.includeBookings)) {
131
+ return this.store.list;
132
+ }
133
+ return this.store.list.map((resource) => this.attachBookingsToResource(resource));
134
+ }
135
+ /**
136
+ * 根据 ID 获取单个资源
137
+ */
138
+ getResourceById(id, queryOptions) {
139
+ const resource = this.store.map.get(id);
140
+ if (!resource)
141
+ return void 0;
142
+ if (queryOptions == null ? void 0 : queryOptions.includeBookings) {
143
+ return this.attachBookingsToResource(resource);
144
+ }
145
+ return resource;
146
+ }
147
+ /**
148
+ * 创建资源
149
+ */
150
+ createResource(data) {
151
+ const id = (data == null ? void 0 : data.id) ?? (data == null ? void 0 : data.form_record_id) ?? Date.now();
152
+ const resource = this.normalizeResource({ ...data, id });
153
+ this.store.list.push(resource);
154
+ this.store.map.set(resource.id, resource);
155
+ this.saveResourcesToSQLite(this.store.list).catch(() => {
156
+ });
157
+ this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
158
+ return resource;
159
+ }
160
+ /**
161
+ * 更新资源
162
+ */
163
+ updateResource(id, data) {
164
+ const index = this.store.list.findIndex((r) => this.getIdKey(r.id) === this.getIdKey(id));
165
+ if (index === -1)
166
+ return void 0;
167
+ const updated = this.normalizeResource({ ...this.store.list[index], ...data, id });
168
+ this.store.list[index] = updated;
169
+ this.store.map.set(updated.id, updated);
170
+ this.saveResourcesToSQLite(this.store.list).catch(() => {
171
+ });
172
+ this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
173
+ return updated;
174
+ }
175
+ /**
176
+ * 删除资源
177
+ */
178
+ deleteResource(id) {
179
+ const key = this.getIdKey(id);
180
+ const index = this.store.list.findIndex((r) => this.getIdKey(r.id) === key);
181
+ if (index === -1)
182
+ return false;
183
+ this.store.list.splice(index, 1);
184
+ this.store.map.delete(id);
185
+ this.saveResourcesToSQLite(this.store.list).catch(() => {
186
+ });
187
+ this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
188
+ return true;
189
+ }
190
+ // ─────────────────────────────────────────────────────────────────
191
+ // Booking CRUD
192
+ // ─────────────────────────────────────────────────────────────────
193
+ /**
194
+ * 根据资源 ID 获取预订列表
195
+ */
196
+ getBookingsByResourceId(resourceId) {
197
+ return this.resourceIdIndex.get(resourceId) || [];
198
+ }
199
+ /**
200
+ * 创建预订
201
+ */
202
+ createBooking(booking) {
203
+ const id = (booking == null ? void 0 : booking.id) ?? Date.now();
204
+ const normalized = {
205
+ id,
206
+ ...booking
207
+ };
208
+ this.store.bookings.push(normalized);
209
+ const rid = normalized.resource_id ?? normalized.resourceId;
210
+ if (rid !== void 0) {
211
+ const existing = this.resourceIdIndex.get(rid) || [];
212
+ existing.push(normalized);
213
+ this.resourceIdIndex.set(rid, existing);
214
+ }
215
+ this.safeEmit(import_types.ResourceHooks.onBookingsChanged, this.store.bookings);
216
+ return normalized;
217
+ }
218
+ /**
219
+ * 更新预订
220
+ */
221
+ updateBooking(id, data) {
222
+ const index = this.store.bookings.findIndex((b) => this.getIdKey(b.id) === this.getIdKey(id));
223
+ if (index === -1)
224
+ return void 0;
225
+ const old = this.store.bookings[index];
226
+ const updated = { ...old, ...data, id: old.id };
227
+ this.store.bookings[index] = updated;
228
+ this.rebuildBookingsIndex();
229
+ this.safeEmit(import_types.ResourceHooks.onBookingsChanged, this.store.bookings);
230
+ return updated;
231
+ }
232
+ /**
233
+ * 删除预订
234
+ */
235
+ deleteBooking(id) {
236
+ const index = this.store.bookings.findIndex((b) => this.getIdKey(b.id) === this.getIdKey(id));
237
+ if (index === -1)
238
+ return false;
239
+ this.store.bookings.splice(index, 1);
240
+ this.rebuildBookingsIndex();
241
+ this.safeEmit(import_types.ResourceHooks.onBookingsChanged, this.store.bookings);
242
+ return true;
243
+ }
244
+ /**
245
+ * 清空缓存
246
+ */
247
+ async clear() {
248
+ this.store.list = [];
249
+ this.store.map.clear();
250
+ this.store.bookings = [];
251
+ this.resourceIdIndex.clear();
252
+ if (this.dbManager) {
253
+ try {
254
+ await this.dbManager.clear(RESOURCE_STORE_NAME);
255
+ } catch {
256
+ }
257
+ }
258
+ await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
259
+ await this.safeEmit(import_types.ResourceHooks.onBookingsChanged, this.store.bookings);
260
+ }
261
+ // ─────────────────────────────────────────────────────────────────
262
+ // 内部工具方法
263
+ // ─────────────────────────────────────────────────────────────────
264
+ attachBookingsToResource(resource) {
265
+ return {
266
+ ...resource,
267
+ bookings: this.getBookingsByResourceId(resource.id)
268
+ };
269
+ }
270
+ normalizeResource(resource) {
271
+ const normalized = {
272
+ ...resource,
273
+ id: (resource == null ? void 0 : resource.id) ?? (resource == null ? void 0 : resource.form_record_id) ?? ""
274
+ };
275
+ if (normalized.form_record_id === void 0 && normalized.id !== "") {
276
+ normalized.form_record_id = normalized.id;
277
+ }
278
+ if (normalized.resource_form_id === void 0 || normalized.resource_form_id === null) {
279
+ normalized.resource_form_id = "";
280
+ }
281
+ if (normalized.schedule === void 0 || normalized.schedule === null) {
282
+ normalized.schedule = "";
283
+ }
284
+ if (Array.isArray(normalized.times)) {
285
+ normalized.times = normalized.times.map((timeSlot) => {
286
+ if (!timeSlot || typeof timeSlot !== "object")
287
+ return timeSlot;
288
+ const startAt = timeSlot.start_at ?? timeSlot.start;
289
+ const endAt = timeSlot.end_at ?? timeSlot.end;
290
+ return {
291
+ ...timeSlot,
292
+ start_at: startAt,
293
+ end_at: endAt,
294
+ start: timeSlot.start ?? startAt,
295
+ end: timeSlot.end ?? endAt
296
+ };
297
+ });
298
+ }
299
+ if (Array.isArray(normalized.children)) {
300
+ normalized.children = normalized.children.map((child) => this.normalizeResource(child));
301
+ }
302
+ return normalized;
303
+ }
304
+ async safeEmit(event, payload) {
305
+ try {
306
+ await this.core.effects.emit(event, payload);
307
+ } catch (error) {
308
+ console.error(`[ResourceModule] 事件派发失败: ${event}`, error);
309
+ }
310
+ }
311
+ syncResourcesMap() {
312
+ this.store.map = /* @__PURE__ */ new Map();
313
+ for (const resource of this.store.list) {
314
+ this.store.map.set(resource.id, resource);
315
+ }
316
+ }
317
+ syncBookingsIndex() {
318
+ this.resourceIdIndex.clear();
319
+ for (const booking of this.store.bookings) {
320
+ const rid = booking.resource_id ?? booking.resourceId;
321
+ if (rid === void 0)
322
+ continue;
323
+ const existing = this.resourceIdIndex.get(rid) || [];
324
+ existing.push(booking);
325
+ this.resourceIdIndex.set(rid, existing);
326
+ }
327
+ }
328
+ rebuildBookingsIndex() {
329
+ this.syncBookingsIndex();
330
+ }
331
+ getIdKey(id) {
332
+ return String(id);
333
+ }
334
+ // ─────────────────────────────────────────────────────────────────
335
+ // 数据加载
336
+ // ─────────────────────────────────────────────────────────────────
337
+ async loadResourcesByServer() {
338
+ if (!this.resourceDataSource)
339
+ return [];
340
+ try {
341
+ const response = await this.resourceDataSource.getResourcePage({
342
+ num: DEFAULT_PAGE_SIZE,
343
+ skip: 1
344
+ });
345
+ const resourceList = Array.isArray(response == null ? void 0 : response.list) ? response.list : [];
346
+ const normalizedList = resourceList.map((item) => this.normalizeResource(item));
347
+ await this.saveResourcesToSQLite(normalizedList);
348
+ await this.safeEmit(import_types.ResourceHooks.onResourcesLoaded, normalizedList);
349
+ return normalizedList;
350
+ } catch {
351
+ return [];
352
+ }
353
+ }
354
+ // ─────────────────────────────────────────────────────────────────
355
+ // SQLite 持久化
356
+ // ─────────────────────────────────────────────────────────────────
357
+ async loadResourcesFromSQLite() {
358
+ if (!this.dbManager)
359
+ return [];
360
+ try {
361
+ const resources = await this.dbManager.getAll(RESOURCE_STORE_NAME);
362
+ return resources || [];
363
+ } catch {
364
+ return [];
365
+ }
366
+ }
367
+ async saveResourcesToSQLite(resourceList) {
368
+ if (!this.dbManager)
369
+ return;
370
+ try {
371
+ await this.dbManager.clear(RESOURCE_STORE_NAME);
372
+ if (resourceList.length === 0)
373
+ return;
374
+ if (this.dbManager.bulkAdd) {
375
+ await this.dbManager.bulkAdd(RESOURCE_STORE_NAME, resourceList);
376
+ return;
377
+ }
378
+ await Promise.all(resourceList.map((r) => this.dbManager.add(RESOURCE_STORE_NAME, r)));
379
+ } catch (error) {
380
+ console.error("saveResourcesToSQLite error", error);
381
+ this.logError("保存资源到 SQLite 失败", {
382
+ error: error instanceof Error ? error.message : String(error),
383
+ resourceList: resourceList.length
384
+ });
385
+ }
386
+ }
387
+ // private async loadBookingsFromSQLite(): Promise<ResourceBooking[]> {
388
+ // if (!this.dbManager) return []
389
+ // try {
390
+ // const bookings = await this.dbManager.getAll(BOOKING_STORE_NAME)
391
+ // return bookings || []
392
+ // } catch {
393
+ // return []
394
+ // }
395
+ // }
396
+ // private async saveBookingsToSQLite(bookings: ResourceBooking[]): Promise<void> {
397
+ // if (!this.dbManager) return
398
+ // try {
399
+ // await this.dbManager.clear(BOOKING_STORE_NAME)
400
+ // if (bookings.length === 0) return
401
+ // if (this.dbManager.bulkAdd) {
402
+ // await this.dbManager.bulkAdd(BOOKING_STORE_NAME, bookings)
403
+ // return
404
+ // }
405
+ // await Promise.all(bookings.map(b => this.dbManager.add(BOOKING_STORE_NAME, b)))
406
+ // } catch {
407
+ // // 忽略 SQLite 异常
408
+ // }
409
+ // }
410
+ // ─────────────────────────────────────────────────────────────────
411
+ // pubsub 同步
412
+ // ─────────────────────────────────────────────────────────────────
413
+ initResourceDataSource() {
414
+ var _a, _b;
415
+ const ResourceDataSourceClass = (_b = (_a = this.core.serverOptions) == null ? void 0 : _a.All_DATA_SOURCES) == null ? void 0 : _b.ResourceDataSource;
416
+ if (!ResourceDataSourceClass)
417
+ return;
418
+ this.resourceDataSource = new ResourceDataSourceClass();
419
+ }
420
+ async setupResourceSync() {
421
+ var _a, _b, _c;
422
+ if (!this.resourceDataSource)
423
+ return;
424
+ const result = await this.resourceDataSource.run({
425
+ pubsub: {
426
+ callback: (res) => {
427
+ const data = (res == null ? void 0 : res.data) || res;
428
+ if (!data)
429
+ return;
430
+ const channelKey = data.module || "resource";
431
+ this.pendingSyncMessages.push({ ...data, _channelKey: channelKey });
432
+ if (this.syncTimer)
433
+ clearTimeout(this.syncTimer);
434
+ this.syncTimer = setTimeout(() => {
435
+ this.processSyncMessages();
436
+ }, RESOURCE_SYNC_DEBOUNCE_MS);
437
+ }
438
+ }
439
+ }).catch(() => {
440
+ });
441
+ console.log("result", result);
442
+ if ((_b = (_a = result == null ? void 0 : result.data) == null ? void 0 : _a.list) == null ? void 0 : _b.length) {
443
+ await this.mergeResourcesToStore((_c = result == null ? void 0 : result.data) == null ? void 0 : _c.list);
444
+ }
445
+ }
446
+ async processSyncMessages() {
447
+ var _a, _b, _c;
448
+ const messages = [...this.pendingSyncMessages];
449
+ this.pendingSyncMessages = [];
450
+ if (messages.length === 0)
451
+ return;
452
+ const deleteIds = [];
453
+ const bodyUpdates = /* @__PURE__ */ new Map();
454
+ const sseRefreshIds = [];
455
+ for (const msg of messages) {
456
+ if (msg.operation === "delete" || msg.action === "delete") {
457
+ if ((_a = msg.ids) == null ? void 0 : _a.length)
458
+ deleteIds.push(...msg.ids);
459
+ else if (msg.id !== void 0)
460
+ deleteIds.push(msg.id);
461
+ continue;
462
+ }
463
+ if (msg.body) {
464
+ const bodyId = msg.body.id ?? msg.id;
465
+ if (bodyId === void 0)
466
+ continue;
467
+ bodyUpdates.set(this.getIdKey(bodyId), { ...msg.body, id: bodyId });
468
+ continue;
469
+ }
470
+ if ((_b = msg.ids) == null ? void 0 : _b.length) {
471
+ sseRefreshIds.push(...msg.ids);
472
+ } else if (msg.id !== void 0) {
473
+ sseRefreshIds.push(msg.id);
474
+ } else if ((_c = msg.relation_resource_ids) == null ? void 0 : _c.length) {
475
+ sseRefreshIds.push(...msg.relation_resource_ids);
476
+ }
477
+ }
478
+ const uniqueDeleteIds = this.uniqueResourceIds(deleteIds);
479
+ const uniqueSSEIds = this.uniqueResourceIds(sseRefreshIds);
480
+ const bodyList = [...bodyUpdates.values()];
481
+ if (uniqueDeleteIds.length > 0)
482
+ await this.removeResourcesByIds(uniqueDeleteIds);
483
+ if (bodyList.length > 0)
484
+ await this.mergeResourcesToStore(bodyList);
485
+ if (uniqueSSEIds.length > 0) {
486
+ const freshResources = await this.fetchResourcesBySSE(uniqueSSEIds);
487
+ if (freshResources.length > 0)
488
+ await this.mergeResourcesToStore(freshResources);
489
+ }
490
+ if (uniqueDeleteIds.length === 0 && bodyList.length === 0 && uniqueSSEIds.length === 0)
491
+ return;
492
+ await this.core.effects.emit(import_types.ResourceHooks.onResourcesSyncCompleted, null);
493
+ }
494
+ async fetchResourcesBySSE(ids) {
495
+ if (!this.resourceDataSource)
496
+ return [];
497
+ try {
498
+ const list = await this.resourceDataSource.run({
499
+ sse: { query: { type: "resource", ids } }
500
+ });
501
+ return list || [];
502
+ } catch {
503
+ return [];
504
+ }
505
+ }
506
+ async removeResourcesByIds(ids) {
507
+ const keySet = new Set(ids.map((id) => this.getIdKey(id)));
508
+ this.store.list = this.store.list.filter((r) => !keySet.has(this.getIdKey(r.id)));
509
+ this.syncResourcesMap();
510
+ if (this.dbManager) {
511
+ try {
512
+ for (const id of ids) {
513
+ await this.dbManager.delete(RESOURCE_STORE_NAME, id);
514
+ }
515
+ } catch {
516
+ }
517
+ }
518
+ await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
519
+ }
520
+ async mergeResourcesToStore(freshResources) {
521
+ const freshMap = /* @__PURE__ */ new Map();
522
+ for (const r of freshResources) {
523
+ if ((r == null ? void 0 : r.id) === void 0)
524
+ continue;
525
+ freshMap.set(this.getIdKey(r.id), this.normalizeResource(r));
526
+ }
527
+ const updatedList = this.store.list.map((r) => {
528
+ const key = this.getIdKey(r.id);
529
+ if (!freshMap.has(key))
530
+ return r;
531
+ const fresh = freshMap.get(key);
532
+ freshMap.delete(key);
533
+ return fresh;
534
+ });
535
+ for (const r of freshMap.values()) {
536
+ updatedList.push(r);
537
+ }
538
+ this.store.list = updatedList;
539
+ this.syncResourcesMap();
540
+ await this.saveResourcesToSQLite(this.store.list);
541
+ await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
542
+ }
543
+ uniqueResourceIds(ids) {
544
+ const idMap = /* @__PURE__ */ new Map();
545
+ for (const id of ids) {
546
+ idMap.set(this.getIdKey(id), id);
547
+ }
548
+ return [...idMap.values()];
549
+ }
550
+ };
551
+ var resourceModule = new ResourceModule();
552
+ // Annotate the CommonJS export names for ESM import in node:
553
+ 0 && (module.exports = {
554
+ ResourceHooks,
555
+ ResourceModule,
556
+ resourceModule
557
+ });