@pisell/pisellos 2.1.38 → 2.2.1
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.
- package/dist/core/index.d.ts +8 -1
- package/dist/core/index.js +116 -42
- package/dist/effects/index.d.ts +1 -0
- package/dist/effects/index.js +29 -6
- package/dist/modules/Account/index.js +2 -3
- package/dist/modules/BaseModule.d.ts +3 -0
- package/dist/modules/BaseModule.js +15 -0
- package/dist/modules/Customer/index.js +9 -10
- package/dist/modules/Customer/types.d.ts +2 -2
- package/dist/modules/Customer/types.js +2 -2
- package/dist/modules/Discount/index.js +1 -1
- package/dist/modules/Guests/index.js +9 -9
- package/dist/modules/Order/index.js +1 -1
- package/dist/modules/Payment/index.js +63 -73
- package/dist/modules/Payment/walletpass.js +4 -1
- package/dist/modules/Product/index.d.ts +1 -1
- package/dist/modules/Product/types.d.ts +19 -0
- package/dist/modules/ProductList/index.js +5 -14
- package/dist/modules/Resource/index.js +1 -1
- package/dist/modules/Rules/index.js +2 -3
- package/dist/modules/Schedule/types.d.ts +2 -0
- package/dist/plugins/request.d.ts +1 -0
- package/dist/server/index.d.ts +152 -0
- package/dist/server/index.js +946 -0
- package/dist/server/modules/index.d.ts +16 -0
- package/dist/server/modules/index.js +21 -0
- package/dist/server/modules/menu/index.d.ts +63 -0
- package/dist/server/modules/menu/index.js +476 -0
- package/dist/server/modules/menu/types.d.ts +68 -0
- package/dist/server/modules/menu/types.js +16 -0
- package/dist/server/modules/products/index.d.ts +141 -0
- package/dist/server/modules/products/index.js +768 -0
- package/dist/server/modules/products/types.d.ts +94 -0
- package/dist/server/modules/products/types.js +43 -0
- package/dist/server/modules/quotation/index.d.ts +47 -0
- package/dist/server/modules/quotation/index.js +367 -0
- package/dist/server/modules/quotation/types.d.ts +50 -0
- package/dist/server/modules/quotation/types.js +20 -0
- package/dist/server/modules/schedule/index.d.ts +62 -0
- package/dist/server/modules/schedule/index.js +431 -0
- package/dist/server/modules/schedule/types.d.ts +1 -0
- package/dist/server/modules/schedule/types.js +2 -0
- package/dist/server/modules/schedule/utils.d.ts +32 -0
- package/dist/server/modules/schedule/utils.js +747 -0
- package/dist/server/types.d.ts +64 -0
- package/dist/server/types.js +1 -0
- package/dist/server/utils/index.d.ts +5 -0
- package/dist/server/utils/index.js +6 -0
- package/dist/server/utils/product.d.ts +18 -0
- package/dist/server/utils/product.js +339 -0
- package/dist/server/utils/schedule.d.ts +14 -0
- package/dist/server/utils/schedule.js +108 -0
- package/dist/server/utils/time.d.ts +18 -0
- package/dist/server/utils/time.js +53 -0
- package/dist/solution/BookingByStep/index.d.ts +1 -17
- package/dist/solution/BookingByStep/index.js +23 -468
- package/dist/solution/BookingByStep/utils/capacity.d.ts +2 -7
- package/dist/solution/BookingByStep/utils/capacity.js +8 -24
- package/dist/solution/BookingTicket/index.d.ts +12 -0
- package/dist/solution/BookingTicket/index.js +122 -79
- package/dist/solution/BookingTicket/utils/scan/index.d.ts +4 -0
- package/dist/solution/BookingTicket/utils/scan/index.js +25 -16
- package/dist/solution/BuyTickets/index.js +7 -8
- package/dist/solution/Checkout/index.d.ts +1 -46
- package/dist/solution/Checkout/index.js +530 -850
- package/dist/solution/ShopDiscount/index.js +9 -10
- package/dist/types/index.d.ts +27 -0
- package/lib/core/index.d.ts +8 -1
- package/lib/core/index.js +48 -1
- package/lib/effects/index.d.ts +1 -0
- package/lib/effects/index.js +13 -0
- package/lib/modules/Account/index.js +2 -3
- package/lib/modules/BaseModule.d.ts +3 -0
- package/lib/modules/BaseModule.js +9 -0
- package/lib/modules/Customer/index.js +9 -10
- package/lib/modules/Customer/types.d.ts +2 -2
- package/lib/modules/Customer/types.js +2 -2
- package/lib/modules/Discount/index.js +1 -1
- package/lib/modules/Guests/index.js +9 -9
- package/lib/modules/Order/index.js +1 -1
- package/lib/modules/Payment/index.js +56 -43
- package/lib/modules/Payment/walletpass.js +3 -1
- package/lib/modules/Product/index.d.ts +1 -1
- package/lib/modules/Product/types.d.ts +19 -0
- package/lib/modules/ProductList/index.js +4 -13
- package/lib/modules/Resource/index.js +1 -1
- package/lib/modules/Rules/index.js +2 -3
- package/lib/modules/Schedule/types.d.ts +2 -0
- package/lib/plugins/request.d.ts +1 -0
- package/lib/server/index.d.ts +152 -0
- package/lib/server/index.js +555 -0
- package/lib/server/modules/index.d.ts +16 -0
- package/lib/server/modules/index.js +47 -0
- package/lib/server/modules/menu/index.d.ts +63 -0
- package/lib/server/modules/menu/index.js +234 -0
- package/lib/server/modules/menu/types.d.ts +68 -0
- package/lib/server/modules/menu/types.js +33 -0
- package/lib/server/modules/products/index.d.ts +141 -0
- package/lib/server/modules/products/index.js +434 -0
- package/lib/server/modules/products/types.d.ts +94 -0
- package/lib/server/modules/products/types.js +35 -0
- package/lib/server/modules/quotation/index.d.ts +47 -0
- package/lib/server/modules/quotation/index.js +177 -0
- package/lib/server/modules/quotation/types.d.ts +50 -0
- package/lib/server/modules/quotation/types.js +33 -0
- package/lib/server/modules/schedule/index.d.ts +62 -0
- package/lib/server/modules/schedule/index.js +231 -0
- package/lib/server/modules/schedule/types.d.ts +1 -0
- package/lib/server/modules/schedule/types.js +23 -0
- package/lib/server/modules/schedule/utils.d.ts +32 -0
- package/lib/server/modules/schedule/utils.js +451 -0
- package/lib/server/types.d.ts +64 -0
- package/lib/server/types.js +17 -0
- package/lib/server/utils/index.d.ts +5 -0
- package/lib/server/utils/index.js +25 -0
- package/lib/server/utils/product.d.ts +18 -0
- package/lib/server/utils/product.js +262 -0
- package/lib/server/utils/schedule.d.ts +14 -0
- package/lib/server/utils/schedule.js +88 -0
- package/lib/server/utils/time.d.ts +18 -0
- package/lib/server/utils/time.js +70 -0
- package/lib/solution/BookingByStep/index.d.ts +1 -17
- package/lib/solution/BookingByStep/index.js +40 -312
- package/lib/solution/BookingByStep/utils/capacity.d.ts +2 -7
- package/lib/solution/BookingByStep/utils/capacity.js +8 -21
- package/lib/solution/BookingTicket/index.d.ts +12 -0
- package/lib/solution/BookingTicket/index.js +25 -6
- package/lib/solution/BookingTicket/utils/scan/index.d.ts +4 -0
- package/lib/solution/BookingTicket/utils/scan/index.js +7 -1
- package/lib/solution/BuyTickets/index.js +7 -8
- package/lib/solution/Checkout/index.d.ts +1 -46
- package/lib/solution/Checkout/index.js +92 -289
- package/lib/solution/ShopDiscount/index.js +10 -11
- package/lib/types/index.d.ts +27 -0
- package/package.json +2 -2
|
@@ -0,0 +1,555 @@
|
|
|
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 __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/server/index.ts
|
|
21
|
+
var server_exports = {};
|
|
22
|
+
__export(server_exports, {
|
|
23
|
+
default: () => server_default
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(server_exports);
|
|
26
|
+
var import_products = require("./modules/products");
|
|
27
|
+
var import_menu = require("./modules/menu");
|
|
28
|
+
var import_quotation = require("./modules/quotation");
|
|
29
|
+
var import_schedule = require("./modules/schedule");
|
|
30
|
+
var import_schedule2 = require("./utils/schedule");
|
|
31
|
+
__reExport(server_exports, require("./modules"), module.exports);
|
|
32
|
+
var Server = class {
|
|
33
|
+
constructor(core) {
|
|
34
|
+
// 路由注册表
|
|
35
|
+
this.router = {
|
|
36
|
+
get: {},
|
|
37
|
+
post: {},
|
|
38
|
+
put: {},
|
|
39
|
+
remove: {}
|
|
40
|
+
};
|
|
41
|
+
// 模块注册表 - 定义所有可用的模块配置
|
|
42
|
+
this.moduleRegistry = {
|
|
43
|
+
products: {
|
|
44
|
+
name: "products",
|
|
45
|
+
moduleClass: import_products.ProductsModule,
|
|
46
|
+
moduleName: "server_products",
|
|
47
|
+
version: "1.0.0",
|
|
48
|
+
defaultStore: {
|
|
49
|
+
list: [],
|
|
50
|
+
selectProducts: []
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
menu: {
|
|
54
|
+
name: "menu",
|
|
55
|
+
moduleClass: import_menu.MenuModule,
|
|
56
|
+
moduleName: "server_menu",
|
|
57
|
+
version: "1.0.0",
|
|
58
|
+
defaultStore: {
|
|
59
|
+
menuList: []
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
quotation: {
|
|
63
|
+
name: "quotation",
|
|
64
|
+
moduleClass: import_quotation.QuotationModule,
|
|
65
|
+
moduleName: "server_quotation",
|
|
66
|
+
version: "1.0.0",
|
|
67
|
+
defaultStore: {
|
|
68
|
+
quotationList: []
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
schedule: {
|
|
72
|
+
name: "schedule",
|
|
73
|
+
moduleClass: import_schedule.ScheduleModuleEx,
|
|
74
|
+
moduleName: "server_schedule",
|
|
75
|
+
version: "1.1.0",
|
|
76
|
+
defaultStore: {
|
|
77
|
+
scheduleList: [],
|
|
78
|
+
availabilityDateList: [],
|
|
79
|
+
otherProductsIds: []
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* 处理商品查询请求(编排 Products、Menu、Schedule 模块)
|
|
85
|
+
* 这是一个业务编排方法,协调多个模块完成复杂的业务需求
|
|
86
|
+
*/
|
|
87
|
+
this.handleProductQuery = async ({ url, method, data, config }) => {
|
|
88
|
+
console.log("[Server] handleProductQuery:", url, method, data, config);
|
|
89
|
+
const { menu_list_ids, schedule_datetime, schedule_date } = data;
|
|
90
|
+
if (!this.products) {
|
|
91
|
+
console.error("[Server] Products 模块未注册");
|
|
92
|
+
return {
|
|
93
|
+
message: "Products 模块未注册",
|
|
94
|
+
data: { list: [], count: 0 }
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (!this.menu) {
|
|
98
|
+
console.error("[Server] Menu 模块未注册");
|
|
99
|
+
return {
|
|
100
|
+
message: "Menu 模块未注册",
|
|
101
|
+
data: { list: [], count: 0 }
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (!this.schedule) {
|
|
105
|
+
console.error("[Server] Schedule 模块未注册");
|
|
106
|
+
return {
|
|
107
|
+
message: "Schedule 模块未注册",
|
|
108
|
+
data: { list: [], count: 0 }
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
let activeMenuList = [];
|
|
112
|
+
if (menu_list_ids && Array.isArray(menu_list_ids) && menu_list_ids.length > 0) {
|
|
113
|
+
console.log("[Server] 获取餐牌详情,IDs:", menu_list_ids);
|
|
114
|
+
const menuList = this.menu.getMenuByIds(menu_list_ids);
|
|
115
|
+
activeMenuList = menuList.filter((menu) => {
|
|
116
|
+
var _a;
|
|
117
|
+
return ((_a = this.schedule) == null ? void 0 : _a.getDateIsInSchedule(schedule_datetime, menu.schedule)) || false;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
console.log(activeMenuList, "activeMenuList");
|
|
121
|
+
const allProductsWithPrice = await this.products.getProductsWithPrice(data.schedule_date, {
|
|
122
|
+
scheduleModule: this.getSchedule()
|
|
123
|
+
});
|
|
124
|
+
console.log(allProductsWithPrice, "allProductsWithPrice");
|
|
125
|
+
let filteredProducts = this.filterProductsByMenuConfig(allProductsWithPrice, activeMenuList);
|
|
126
|
+
filteredProducts = filteredProducts.sort((a, b) => {
|
|
127
|
+
const sortDiff = Number(b.sort) - Number(a.sort);
|
|
128
|
+
if (sortDiff !== 0) {
|
|
129
|
+
return sortDiff;
|
|
130
|
+
}
|
|
131
|
+
return (a.title || "").localeCompare(b.title || "");
|
|
132
|
+
});
|
|
133
|
+
console.log("[Server] 原始商品数量:", allProductsWithPrice.length);
|
|
134
|
+
console.log("[Server] 过滤后商品数量:", filteredProducts.length);
|
|
135
|
+
console.log(filteredProducts, "filteredProducts");
|
|
136
|
+
return {
|
|
137
|
+
code: 200,
|
|
138
|
+
data: {
|
|
139
|
+
list: filteredProducts,
|
|
140
|
+
count: filteredProducts.length
|
|
141
|
+
},
|
|
142
|
+
message: "",
|
|
143
|
+
status: true
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* 处理获取日程时间段点的请求
|
|
148
|
+
* 通过餐牌ID列表获取所有相关日程的时间段点
|
|
149
|
+
*/
|
|
150
|
+
this.handleGetScheduleTimePoints = async ({ url, method, data, config }) => {
|
|
151
|
+
console.log("[Server] handleGetScheduleTimePoints:", url, method, data, config);
|
|
152
|
+
const { menu_list_ids } = data;
|
|
153
|
+
if (!this.menu) {
|
|
154
|
+
console.error("[Server] Menu 模块未注册");
|
|
155
|
+
return {
|
|
156
|
+
code: 500,
|
|
157
|
+
message: "Menu 模块未注册",
|
|
158
|
+
data: [],
|
|
159
|
+
status: false
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
if (!this.schedule) {
|
|
163
|
+
console.error("[Server] Schedule 模块未注册");
|
|
164
|
+
return {
|
|
165
|
+
code: 500,
|
|
166
|
+
message: "Schedule 模块未注册",
|
|
167
|
+
data: [],
|
|
168
|
+
status: false
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (!menu_list_ids || !Array.isArray(menu_list_ids) || menu_list_ids.length === 0) {
|
|
172
|
+
console.error("[Server] menu_list_ids 参数无效");
|
|
173
|
+
return {
|
|
174
|
+
code: 400,
|
|
175
|
+
message: "menu_list_ids 参数无效",
|
|
176
|
+
data: [],
|
|
177
|
+
status: false
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
const menuList = this.menu.getMenuByIds(menu_list_ids);
|
|
182
|
+
console.log(`[Server] 找到 ${menuList.length} 个餐牌`);
|
|
183
|
+
const scheduleIds = (0, import_schedule2.extractScheduleIdsFromMenus)(menuList);
|
|
184
|
+
console.log(`[Server] 提取到 ${scheduleIds.length} 个日程ID:`, scheduleIds);
|
|
185
|
+
if (scheduleIds.length === 0) {
|
|
186
|
+
return {
|
|
187
|
+
code: 200,
|
|
188
|
+
message: "没有找到相关日程",
|
|
189
|
+
data: [],
|
|
190
|
+
status: true
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const scheduleList = this.schedule.getScheduleByIds(scheduleIds);
|
|
194
|
+
console.log(`[Server] 找到 ${scheduleList.length} 个日程`);
|
|
195
|
+
const timePoints = (0, import_schedule2.extractTimePointsFromSchedules)(scheduleList);
|
|
196
|
+
console.log(`[Server] 提取到 ${timePoints.length} 个时间点:`, timePoints);
|
|
197
|
+
return {
|
|
198
|
+
code: 200,
|
|
199
|
+
message: "获取成功",
|
|
200
|
+
data: timePoints,
|
|
201
|
+
status: true
|
|
202
|
+
};
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.error("[Server] 获取日程时间点失败:", error);
|
|
205
|
+
return {
|
|
206
|
+
code: 500,
|
|
207
|
+
message: `获取失败: ${error instanceof Error ? error.message : "未知错误"}`,
|
|
208
|
+
data: [],
|
|
209
|
+
status: false
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
this.core = core;
|
|
214
|
+
console.log("[Server] Server 初始化");
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* 注册路由
|
|
218
|
+
* @param routes 路由定义数组
|
|
219
|
+
*/
|
|
220
|
+
registerRoutes(routes) {
|
|
221
|
+
routes.forEach((route) => {
|
|
222
|
+
const { method, path, handler } = route;
|
|
223
|
+
if (!this.router[method]) {
|
|
224
|
+
console.warn(`[Server] 不支持的 HTTP 方法: ${method}`);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (this.router[method][path]) {
|
|
228
|
+
console.warn(`[Server] 路由已存在,将被覆盖: ${method.toUpperCase()} ${path}`);
|
|
229
|
+
}
|
|
230
|
+
this.router[method][path] = handler;
|
|
231
|
+
console.log(`[Server] 📝 注册路由: ${method.toUpperCase()} ${path}`);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* 注册单个模块并自动注册其路由
|
|
236
|
+
* @param module 模块实例
|
|
237
|
+
* @param options 模块配置
|
|
238
|
+
* @param moduleName 模块名称(用于日志)
|
|
239
|
+
*/
|
|
240
|
+
async registerModuleWithRoutes(module2, options, moduleName) {
|
|
241
|
+
await this.core.registerModule(module2, options);
|
|
242
|
+
console.log(`[Server] ✅ ${moduleName} 模块已注册`);
|
|
243
|
+
if (typeof module2.getRoutes === "function") {
|
|
244
|
+
const routes = module2.getRoutes();
|
|
245
|
+
if (routes && routes.length > 0) {
|
|
246
|
+
this.registerRoutes(routes);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* 根据模块名称注册单个模块
|
|
252
|
+
* @param moduleConfig 模块配置(可以是字符串或配置对象)
|
|
253
|
+
*/
|
|
254
|
+
async registerModuleByName(moduleConfig) {
|
|
255
|
+
const moduleName = typeof moduleConfig === "string" ? moduleConfig : moduleConfig.name;
|
|
256
|
+
const shouldPreload = typeof moduleConfig === "object" ? moduleConfig.preload !== false : true;
|
|
257
|
+
const customConfig = typeof moduleConfig === "object" ? moduleConfig.config : {};
|
|
258
|
+
const registryConfig = this.moduleRegistry[moduleName];
|
|
259
|
+
if (!registryConfig) {
|
|
260
|
+
throw new Error(`[Server] 未找到模块配置: ${moduleName}`);
|
|
261
|
+
}
|
|
262
|
+
const ModuleClass = registryConfig.moduleClass;
|
|
263
|
+
const moduleInstance = new ModuleClass(registryConfig.moduleName, registryConfig.version);
|
|
264
|
+
const moduleOptions = {
|
|
265
|
+
store: { ...registryConfig.defaultStore },
|
|
266
|
+
...customConfig
|
|
267
|
+
};
|
|
268
|
+
await this.registerModuleWithRoutes(
|
|
269
|
+
moduleInstance,
|
|
270
|
+
moduleOptions,
|
|
271
|
+
moduleName.charAt(0).toUpperCase() + moduleName.slice(1)
|
|
272
|
+
);
|
|
273
|
+
this[moduleName] = moduleInstance;
|
|
274
|
+
return { module: moduleInstance, config: registryConfig, shouldPreload };
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* 注册指定的服务端模块
|
|
278
|
+
* @param moduleConfigs 要注册的模块配置数组(模块名称或配置对象)
|
|
279
|
+
*/
|
|
280
|
+
async registerModules(moduleConfigs) {
|
|
281
|
+
console.log("[Server] 开始注册模块...");
|
|
282
|
+
const configs = moduleConfigs || Object.keys(this.moduleRegistry);
|
|
283
|
+
const registeredModules = [];
|
|
284
|
+
for (const config of configs) {
|
|
285
|
+
try {
|
|
286
|
+
const result = await this.registerModuleByName(config);
|
|
287
|
+
registeredModules.push(result);
|
|
288
|
+
} catch (error) {
|
|
289
|
+
console.error(`[Server] 模块注册失败:`, error);
|
|
290
|
+
throw error;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
console.log("[Server] ✅ 所有模块注册完成");
|
|
294
|
+
return registeredModules;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* 预加载指定模块的数据
|
|
298
|
+
* @param registeredModules 已注册的模块信息
|
|
299
|
+
*/
|
|
300
|
+
async preloadModulesData(registeredModules, options) {
|
|
301
|
+
var _a, _b;
|
|
302
|
+
console.log("[Server] 开始预加载模块数据...");
|
|
303
|
+
for (const { module: module2, config, shouldPreload } of registeredModules) {
|
|
304
|
+
if (!shouldPreload) {
|
|
305
|
+
console.log(`[Server] ⏭️ 跳过 ${config.name} 模块预加载`);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
if (typeof module2.preload === "function") {
|
|
309
|
+
try {
|
|
310
|
+
(_a = options == null ? void 0 : options.onModuleLoad) == null ? void 0 : _a.call(options, config.name);
|
|
311
|
+
await module2.preload();
|
|
312
|
+
(_b = options == null ? void 0 : options.onModuleLoadComplete) == null ? void 0 : _b.call(options, config.name);
|
|
313
|
+
console.log(`[Server] ✅ ${config.name} 模块数据已预加载`);
|
|
314
|
+
} catch (error) {
|
|
315
|
+
console.error(`[Server] ❌ ${config.name} 模块预加载失败:`, error);
|
|
316
|
+
}
|
|
317
|
+
} else {
|
|
318
|
+
console.log(`[Server] ⚠️ ${config.name} 模块未实现 preload() 方法`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
console.log("[Server] ✅ 所有模块数据预加载完成");
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* 初始化 Server(注册模块并预加载数据)
|
|
325
|
+
* @param moduleConfigs 要注册的模块配置
|
|
326
|
+
* @param autoPreload 是否自动预加载数据
|
|
327
|
+
*/
|
|
328
|
+
async initialize(moduleConfigs, autoPreload = true, options) {
|
|
329
|
+
this.registerServerRoutes();
|
|
330
|
+
const registeredModules = await this.registerModules(moduleConfigs);
|
|
331
|
+
if (autoPreload) {
|
|
332
|
+
await this.preloadModulesData(registeredModules, options);
|
|
333
|
+
}
|
|
334
|
+
return registeredModules;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* 获取 Products 模块实例
|
|
338
|
+
*/
|
|
339
|
+
getProducts() {
|
|
340
|
+
return this.products;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* 获取 Menu 模块实例
|
|
344
|
+
*/
|
|
345
|
+
getMenu() {
|
|
346
|
+
return this.menu;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* 获取 Quotation 模块实例
|
|
350
|
+
*/
|
|
351
|
+
getQuotation() {
|
|
352
|
+
return this.quotation;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* 获取 Schedule 模块实例
|
|
356
|
+
*/
|
|
357
|
+
getSchedule() {
|
|
358
|
+
return this.schedule;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* 获取所有已注册的模块列表
|
|
362
|
+
*/
|
|
363
|
+
getRegisteredModules() {
|
|
364
|
+
const modules = [];
|
|
365
|
+
if (this.products)
|
|
366
|
+
modules.push("products");
|
|
367
|
+
if (this.menu)
|
|
368
|
+
modules.push("menu");
|
|
369
|
+
if (this.quotation)
|
|
370
|
+
modules.push("quotation");
|
|
371
|
+
if (this.schedule)
|
|
372
|
+
modules.push("schedule");
|
|
373
|
+
return modules;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* 清空所有server模块的IndexedDB缓存
|
|
377
|
+
* @returns Promise<void>
|
|
378
|
+
*/
|
|
379
|
+
async clearAllIndexDB() {
|
|
380
|
+
console.log("[Server] 开始清空所有模块的IndexedDB缓存...");
|
|
381
|
+
const clearTasks = [];
|
|
382
|
+
const moduleNames = [];
|
|
383
|
+
if (this.products) {
|
|
384
|
+
clearTasks.push(this.products.clear());
|
|
385
|
+
moduleNames.push("Products");
|
|
386
|
+
}
|
|
387
|
+
if (this.menu) {
|
|
388
|
+
clearTasks.push(this.menu.clear());
|
|
389
|
+
moduleNames.push("Menu");
|
|
390
|
+
}
|
|
391
|
+
if (this.quotation) {
|
|
392
|
+
clearTasks.push(this.quotation.clear());
|
|
393
|
+
moduleNames.push("Quotation");
|
|
394
|
+
}
|
|
395
|
+
if (this.schedule) {
|
|
396
|
+
clearTasks.push(this.schedule.clear());
|
|
397
|
+
moduleNames.push("Schedule");
|
|
398
|
+
}
|
|
399
|
+
if (clearTasks.length === 0) {
|
|
400
|
+
console.warn("[Server] 没有找到已注册的模块,无需清空");
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
try {
|
|
404
|
+
await Promise.all(clearTasks);
|
|
405
|
+
console.log(`[Server] ✅ 已成功清空所有模块的IndexedDB缓存: ${moduleNames.join(", ")}`);
|
|
406
|
+
} catch (error) {
|
|
407
|
+
console.error("[Server] ❌ 清空IndexedDB缓存时发生错误:", error);
|
|
408
|
+
throw error;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* 获取所有注册的路由
|
|
413
|
+
*/
|
|
414
|
+
getRoutes() {
|
|
415
|
+
return this.router;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* 根据方法和路径获取路由处理函数
|
|
419
|
+
* @param method HTTP 方法
|
|
420
|
+
* @param path 路径
|
|
421
|
+
*/
|
|
422
|
+
getRouteHandler(method, path) {
|
|
423
|
+
var _a;
|
|
424
|
+
return (_a = this.router[method]) == null ? void 0 : _a[path];
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* 检查路由是否存在
|
|
428
|
+
* @param method HTTP 方法
|
|
429
|
+
* @param path 路径
|
|
430
|
+
*/
|
|
431
|
+
hasRoute(method, path) {
|
|
432
|
+
var _a;
|
|
433
|
+
console.log(method, path, "method, path");
|
|
434
|
+
return !!((_a = this.router[method]) == null ? void 0 : _a[path]);
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* 执行路由处理函数
|
|
438
|
+
* @param method HTTP 方法
|
|
439
|
+
* @param path 路径
|
|
440
|
+
* @param params 请求参数
|
|
441
|
+
*/
|
|
442
|
+
async handleRoute(method, path, params) {
|
|
443
|
+
console.log(method, path, params, "method, path, params");
|
|
444
|
+
const handler = this.getRouteHandler(method, path);
|
|
445
|
+
if (!handler) {
|
|
446
|
+
throw new Error(`Route not found: ${method.toUpperCase()} ${path}`);
|
|
447
|
+
}
|
|
448
|
+
try {
|
|
449
|
+
return await handler(params);
|
|
450
|
+
} catch (error) {
|
|
451
|
+
console.error(`[Server] 路由处理错误: ${method.toUpperCase()} ${path}`, error);
|
|
452
|
+
throw error;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* 获取所有路由列表(用于调试和文档)
|
|
457
|
+
*/
|
|
458
|
+
getAllRoutes() {
|
|
459
|
+
const routes = [];
|
|
460
|
+
["get", "post", "put", "remove"].forEach((method) => {
|
|
461
|
+
Object.keys(this.router[method]).forEach((path) => {
|
|
462
|
+
routes.push({ method, path });
|
|
463
|
+
});
|
|
464
|
+
});
|
|
465
|
+
return routes;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* 注册 Server 层的业务路由
|
|
469
|
+
* 这些路由需要编排多个模块的数据
|
|
470
|
+
* @private
|
|
471
|
+
*/
|
|
472
|
+
registerServerRoutes() {
|
|
473
|
+
console.log("[Server] 注册 Server 层业务路由...");
|
|
474
|
+
this.registerRoutes([
|
|
475
|
+
{
|
|
476
|
+
method: "post",
|
|
477
|
+
path: "/shop/product/query",
|
|
478
|
+
handler: this.handleProductQuery.bind(this)
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
method: "post",
|
|
482
|
+
path: "/shop/menu/schedule-time-points",
|
|
483
|
+
handler: this.handleGetScheduleTimePoints.bind(this)
|
|
484
|
+
}
|
|
485
|
+
]);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* 根据餐牌配置过滤商品
|
|
489
|
+
* @param products 所有商品列表
|
|
490
|
+
* @param activeMenuList 生效的餐牌列表
|
|
491
|
+
* @returns 过滤后的商品列表
|
|
492
|
+
* @private
|
|
493
|
+
*/
|
|
494
|
+
filterProductsByMenuConfig(products, activeMenuList) {
|
|
495
|
+
if (!activeMenuList || activeMenuList.length === 0) {
|
|
496
|
+
console.log("[Server] 没有生效的餐牌,返回空数组");
|
|
497
|
+
return [];
|
|
498
|
+
}
|
|
499
|
+
let allowedProductIds = /* @__PURE__ */ new Set();
|
|
500
|
+
let allowedCollectionIds = /* @__PURE__ */ new Set();
|
|
501
|
+
let hasProductAll = false;
|
|
502
|
+
for (const menu of activeMenuList) {
|
|
503
|
+
const config = menu.partyroom_package;
|
|
504
|
+
if (!config) {
|
|
505
|
+
console.warn("[Server] 餐牌缺少 partyroom_package 配置:", menu);
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
if (config.type === "product_all") {
|
|
509
|
+
console.log("[Server] 餐牌允许所有商品:", menu.name);
|
|
510
|
+
hasProductAll = true;
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
if (config.type === "products" && Array.isArray(config.products)) {
|
|
514
|
+
const productIds = config.products.map((item) => item.product_id);
|
|
515
|
+
productIds.forEach((id) => id && allowedProductIds.add(id));
|
|
516
|
+
console.log("[Server] 餐牌允许指定商品 (product_ids):", menu.name, productIds);
|
|
517
|
+
}
|
|
518
|
+
if (config.type === "product_collection" && Array.isArray(config.products)) {
|
|
519
|
+
const collectionIds = config.products.map((item) => item.product_collection_id);
|
|
520
|
+
collectionIds.forEach((id) => id && allowedCollectionIds.add(id));
|
|
521
|
+
console.log("[Server] 餐牌允许商品集合 (product_collection):", menu.name, collectionIds);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (hasProductAll) {
|
|
525
|
+
return products;
|
|
526
|
+
}
|
|
527
|
+
if (allowedProductIds.size === 0 && allowedCollectionIds.size === 0) {
|
|
528
|
+
console.log("[Server] 没有允许的商品和集合");
|
|
529
|
+
return [];
|
|
530
|
+
}
|
|
531
|
+
console.log("[Server] 允许的商品 IDs:", Array.from(allowedProductIds));
|
|
532
|
+
console.log("[Server] 允许的集合 IDs:", Array.from(allowedCollectionIds));
|
|
533
|
+
const filteredProducts = products.filter((product) => {
|
|
534
|
+
if (allowedProductIds.has(product.id)) {
|
|
535
|
+
return true;
|
|
536
|
+
}
|
|
537
|
+
if (allowedCollectionIds.size > 0 && Array.isArray(product.collection)) {
|
|
538
|
+
const hasMatchingCollection = product.collection.some(
|
|
539
|
+
(col) => allowedCollectionIds.has(col.id)
|
|
540
|
+
);
|
|
541
|
+
if (hasMatchingCollection) {
|
|
542
|
+
return true;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return false;
|
|
546
|
+
});
|
|
547
|
+
console.log("[Server] 过滤结果: 原始 %d 个,过滤后 %d 个", products.length, filteredProducts.length);
|
|
548
|
+
return filteredProducts;
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
var server_default = Server;
|
|
552
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
553
|
+
0 && (module.exports = {
|
|
554
|
+
...require("./modules")
|
|
555
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server 模块导出
|
|
3
|
+
* 包含新增的 Products、Menu、Quotation 和扩展的 Schedule 模块
|
|
4
|
+
*/
|
|
5
|
+
export { ProductsModule } from './products';
|
|
6
|
+
export type { ProductsState } from './products/types';
|
|
7
|
+
export { ProductsHooks } from './products/types';
|
|
8
|
+
export { MenuModule } from './menu';
|
|
9
|
+
export type { MenuState, MenuData } from './menu/types';
|
|
10
|
+
export { MenuHooks } from './menu/types';
|
|
11
|
+
export { QuotationModule } from './quotation';
|
|
12
|
+
export type { QuotationState, QuotationData, QuotationProductPrice } from './quotation/types';
|
|
13
|
+
export { QuotationHooks } from './quotation/types';
|
|
14
|
+
export { ScheduleModuleEx } from './schedule';
|
|
15
|
+
export type { ScheduleState, ScheduleItem } from './schedule/types';
|
|
16
|
+
export type { RouteHandler, HttpMethod, RouteDefinition, Router, ModuleRegistryConfig, } from '../types';
|
|
@@ -0,0 +1,47 @@
|
|
|
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/index.ts
|
|
20
|
+
var modules_exports = {};
|
|
21
|
+
__export(modules_exports, {
|
|
22
|
+
MenuHooks: () => import_types2.MenuHooks,
|
|
23
|
+
MenuModule: () => import_menu.MenuModule,
|
|
24
|
+
ProductsHooks: () => import_types.ProductsHooks,
|
|
25
|
+
ProductsModule: () => import_products.ProductsModule,
|
|
26
|
+
QuotationHooks: () => import_types3.QuotationHooks,
|
|
27
|
+
QuotationModule: () => import_quotation.QuotationModule,
|
|
28
|
+
ScheduleModuleEx: () => import_schedule.ScheduleModuleEx
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(modules_exports);
|
|
31
|
+
var import_products = require("./products");
|
|
32
|
+
var import_types = require("./products/types");
|
|
33
|
+
var import_menu = require("./menu");
|
|
34
|
+
var import_types2 = require("./menu/types");
|
|
35
|
+
var import_quotation = require("./quotation");
|
|
36
|
+
var import_types3 = require("./quotation/types");
|
|
37
|
+
var import_schedule = require("./schedule");
|
|
38
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
39
|
+
0 && (module.exports = {
|
|
40
|
+
MenuHooks,
|
|
41
|
+
MenuModule,
|
|
42
|
+
ProductsHooks,
|
|
43
|
+
ProductsModule,
|
|
44
|
+
QuotationHooks,
|
|
45
|
+
QuotationModule,
|
|
46
|
+
ScheduleModuleEx
|
|
47
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Module, PisellCore, ModuleOptions } from '../../../types';
|
|
2
|
+
import { BaseModule } from '../../../modules/BaseModule';
|
|
3
|
+
import type { RouteDefinition } from '../../types';
|
|
4
|
+
import { MenuData } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* 餐牌模块 - 用于管理餐牌数据和根据餐牌过滤商品
|
|
7
|
+
*/
|
|
8
|
+
export declare class MenuModule extends BaseModule implements Module {
|
|
9
|
+
protected defaultName: string;
|
|
10
|
+
protected defaultVersion: string;
|
|
11
|
+
private request;
|
|
12
|
+
private store;
|
|
13
|
+
private dbManager;
|
|
14
|
+
constructor(name?: string, version?: string);
|
|
15
|
+
initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* 加载餐牌列表(从服务器)
|
|
18
|
+
*/
|
|
19
|
+
loadMenuList(): Promise<MenuData[]>;
|
|
20
|
+
/**
|
|
21
|
+
* 设置餐牌列表
|
|
22
|
+
*/
|
|
23
|
+
setMenuList(menuList: MenuData[]): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* 获取餐牌列表
|
|
26
|
+
*/
|
|
27
|
+
getMenuList(): MenuData[];
|
|
28
|
+
/**
|
|
29
|
+
* 根据 form_record_id 数组获取餐牌详情
|
|
30
|
+
* 使用 Map 快速查询,时间复杂度 O(m),m 为 ids 数量
|
|
31
|
+
*/
|
|
32
|
+
getMenuByIds(ids: number[]): MenuData[];
|
|
33
|
+
/**
|
|
34
|
+
* 同步更新餐牌 Map 缓存
|
|
35
|
+
* 将 menuList 中的餐牌同步到 map,以 form_record_id 为 key
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
private syncMenuMap;
|
|
39
|
+
/**
|
|
40
|
+
* 清空缓存
|
|
41
|
+
*/
|
|
42
|
+
clear(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* 从 IndexDB 加载餐牌数据
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
private loadMenuFromIndexDB;
|
|
48
|
+
/**
|
|
49
|
+
* 保存餐牌数据到 IndexDB
|
|
50
|
+
* @private
|
|
51
|
+
*/
|
|
52
|
+
private saveMenuToIndexDB;
|
|
53
|
+
/**
|
|
54
|
+
* 预加载模块数据(统一接口)
|
|
55
|
+
* 在模块注册后自动调用
|
|
56
|
+
*/
|
|
57
|
+
preload(): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* 获取模块的路由定义
|
|
60
|
+
* 返回该模块需要注册的 API 路由
|
|
61
|
+
*/
|
|
62
|
+
getRoutes(): RouteDefinition[];
|
|
63
|
+
}
|