@pisell/pisellos 2.2.97 → 2.2.99
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/model/strategy/adapter/walletPass/type.d.ts +2 -2
- package/dist/model/strategy/adapter/walletPass/utils.js +70 -57
- package/dist/modules/Order/index.d.ts +1 -1
- package/dist/server/index.d.ts +30 -0
- package/dist/server/index.js +660 -330
- package/dist/server/modules/floor-plan/index.d.ts +39 -0
- package/dist/server/modules/floor-plan/index.js +595 -0
- package/dist/server/modules/floor-plan/types.d.ts +43 -0
- package/dist/server/modules/floor-plan/types.js +13 -0
- package/dist/server/modules/index.d.ts +3 -0
- package/dist/server/modules/index.js +4 -0
- package/dist/server/modules/order/types.d.ts +13 -1
- package/dist/server/modules/order/types.js +2 -1
- package/dist/server/modules/order/utils/filterBookings.d.ts +7 -1
- package/dist/server/modules/order/utils/filterBookings.js +64 -4
- package/dist/server/modules/resource/index.d.ts +0 -5
- package/dist/server/modules/resource/index.js +186 -269
- package/dist/server/types.d.ts +2 -0
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/Sales/index.d.ts +2 -1
- package/dist/solution/Sales/index.js +23 -10
- package/dist/solution/Sales/types.d.ts +1 -1
- package/lib/model/strategy/adapter/walletPass/type.d.ts +2 -2
- package/lib/model/strategy/adapter/walletPass/utils.js +58 -51
- package/lib/modules/Order/index.d.ts +1 -1
- package/lib/server/index.d.ts +30 -0
- package/lib/server/index.js +202 -9
- package/lib/server/modules/floor-plan/index.d.ts +39 -0
- package/lib/server/modules/floor-plan/index.js +327 -0
- package/lib/server/modules/floor-plan/types.d.ts +43 -0
- package/lib/server/modules/floor-plan/types.js +34 -0
- package/lib/server/modules/index.d.ts +3 -0
- package/lib/server/modules/index.js +6 -0
- package/lib/server/modules/order/types.d.ts +13 -1
- package/lib/server/modules/order/utils/filterBookings.d.ts +7 -1
- package/lib/server/modules/order/utils/filterBookings.js +69 -3
- package/lib/server/modules/resource/index.d.ts +0 -5
- package/lib/server/modules/resource/index.js +60 -73
- package/lib/server/types.d.ts +2 -0
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/Sales/index.d.ts +2 -1
- package/lib/solution/Sales/index.js +11 -4
- package/lib/solution/Sales/types.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 平面图(floor-plan)Server 模块类型
|
|
3
|
+
* 与 GET /shop/schedule/floor-plan 系列接口数据结构对齐
|
|
4
|
+
*/
|
|
5
|
+
export interface FloorPlanItem {
|
|
6
|
+
id: number;
|
|
7
|
+
shop_id?: number;
|
|
8
|
+
code: string;
|
|
9
|
+
name: string | Record<string, string>;
|
|
10
|
+
layout: unknown[];
|
|
11
|
+
canvas_width: number;
|
|
12
|
+
canvas_height: number;
|
|
13
|
+
sort: number;
|
|
14
|
+
status: number;
|
|
15
|
+
created_at?: string;
|
|
16
|
+
updated_at?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface FloorPlanState {
|
|
19
|
+
list: FloorPlanItem[];
|
|
20
|
+
map: Map<string, FloorPlanItem>;
|
|
21
|
+
codeMap: Map<string, FloorPlanItem>;
|
|
22
|
+
}
|
|
23
|
+
/** pubsub / Ably 推送消息(与《平面图编辑器API文档》Socket 一节一致) */
|
|
24
|
+
export interface FloorPlanSyncMessage {
|
|
25
|
+
module?: string;
|
|
26
|
+
action?: string;
|
|
27
|
+
operation?: string;
|
|
28
|
+
id?: number;
|
|
29
|
+
ids?: number[];
|
|
30
|
+
body?: Partial<FloorPlanItem> & {
|
|
31
|
+
id?: number;
|
|
32
|
+
};
|
|
33
|
+
message_uuid?: string;
|
|
34
|
+
timestamp?: string;
|
|
35
|
+
_channelKey?: string;
|
|
36
|
+
}
|
|
37
|
+
export declare const FloorPlanHooks: {
|
|
38
|
+
/** 本地列表变更(预加载、合并、删除后) */
|
|
39
|
+
readonly onFloorPlansChanged: "server_floor_plan:onFloorPlansChanged";
|
|
40
|
+
/** pubsub 同步处理完成,供 Server 向订阅者推送最新查询结果 */
|
|
41
|
+
readonly onFloorPlanSyncCompleted: "server_floor_plan:onFloorPlanSyncCompleted";
|
|
42
|
+
};
|
|
43
|
+
export type FloorPlanHooksType = (typeof FloorPlanHooks)[keyof typeof FloorPlanHooks];
|
|
@@ -0,0 +1,34 @@
|
|
|
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/floor-plan/types.ts
|
|
20
|
+
var types_exports = {};
|
|
21
|
+
__export(types_exports, {
|
|
22
|
+
FloorPlanHooks: () => FloorPlanHooks
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(types_exports);
|
|
25
|
+
var FloorPlanHooks = {
|
|
26
|
+
/** 本地列表变更(预加载、合并、删除后) */
|
|
27
|
+
onFloorPlansChanged: "server_floor_plan:onFloorPlansChanged",
|
|
28
|
+
/** pubsub 同步处理完成,供 Server 向订阅者推送最新查询结果 */
|
|
29
|
+
onFloorPlanSyncCompleted: "server_floor_plan:onFloorPlanSyncCompleted"
|
|
30
|
+
};
|
|
31
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
32
|
+
0 && (module.exports = {
|
|
33
|
+
FloorPlanHooks
|
|
34
|
+
});
|
|
@@ -16,6 +16,9 @@ export type { ScheduleState, ScheduleItem } from './schedule/types';
|
|
|
16
16
|
export { OrderModule } from './order';
|
|
17
17
|
export type { OrderState, OrderData, OrderId, OrderSummary, OrderBookingItem, OrderProductLineItem, OrderPaymentItem, OrderSurchargeItem, OrderProductDiscountItem, OrderWithoutBookings, BookingData, OrderFilters, BookingFilters, OrderFilterResult, BookingFilterResult, OrderModulePagedResult, } from './order/types';
|
|
18
18
|
export { OrderHooks } from './order/types';
|
|
19
|
+
export { FloorPlanModule } from './floor-plan';
|
|
20
|
+
export type { FloorPlanItem, FloorPlanState, FloorPlanSyncMessage } from './floor-plan/types';
|
|
21
|
+
export { FloorPlanHooks } from './floor-plan/types';
|
|
19
22
|
export { ResourceModule, resourceModule } from './resource';
|
|
20
23
|
export type { ResourceState, ResourceData, ResourceId, ResourceBooking, ResourcePageQuery, ResourcePageResult, QueryOptions, ScheduleEventResource, } from './resource';
|
|
21
24
|
export { ResourceHooks } from './resource';
|
|
@@ -19,6 +19,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
// src/server/modules/index.ts
|
|
20
20
|
var modules_exports = {};
|
|
21
21
|
__export(modules_exports, {
|
|
22
|
+
FloorPlanHooks: () => import_types5.FloorPlanHooks,
|
|
23
|
+
FloorPlanModule: () => import_floor_plan.FloorPlanModule,
|
|
22
24
|
MenuHooks: () => import_types2.MenuHooks,
|
|
23
25
|
MenuModule: () => import_menu.MenuModule,
|
|
24
26
|
OrderHooks: () => import_types4.OrderHooks,
|
|
@@ -42,10 +44,14 @@ var import_types3 = require("./quotation/types");
|
|
|
42
44
|
var import_schedule = require("./schedule");
|
|
43
45
|
var import_order = require("./order");
|
|
44
46
|
var import_types4 = require("./order/types");
|
|
47
|
+
var import_floor_plan = require("./floor-plan");
|
|
48
|
+
var import_types5 = require("./floor-plan/types");
|
|
45
49
|
var import_resource = require("./resource");
|
|
46
50
|
var import_resource2 = require("./resource");
|
|
47
51
|
// Annotate the CommonJS export names for ESM import in node:
|
|
48
52
|
0 && (module.exports = {
|
|
53
|
+
FloorPlanHooks,
|
|
54
|
+
FloorPlanModule,
|
|
49
55
|
MenuHooks,
|
|
50
56
|
MenuModule,
|
|
51
57
|
OrderHooks,
|
|
@@ -121,6 +121,8 @@ export interface OrderProductLineItem {
|
|
|
121
121
|
product_bundle?: OrderProductBundleItem[];
|
|
122
122
|
/** 元数据;含 unique_identification_number。来源:Detail.metadata */
|
|
123
123
|
metadata?: OrderProductMetadata | null;
|
|
124
|
+
/** 关联子预约 ID(仅输出,预约订单场景)。来源:Detail.schedule_event_id */
|
|
125
|
+
schedule_event_id?: number | null;
|
|
124
126
|
}
|
|
125
127
|
/** 预约条目 metadata,常含 unique_identification_number */
|
|
126
128
|
export interface OrderBookingMetadata {
|
|
@@ -188,6 +190,14 @@ export interface OrderBookingItem {
|
|
|
188
190
|
holder?: Record<string, unknown> | null;
|
|
189
191
|
/** 元数据;含 unique_identification_number。来源:ScheduleEvent.metadata */
|
|
190
192
|
metadata?: OrderBookingMetadata | null;
|
|
193
|
+
/**
|
|
194
|
+
* 与订单明细等资源的关联(如 resource_type 为订单 Detail 时 resource_id 对应 order_detail_id)。
|
|
195
|
+
* 来源:服务端 ScheduleEvent 关联表。
|
|
196
|
+
*/
|
|
197
|
+
relation_items?: {
|
|
198
|
+
resource_id?: number | null;
|
|
199
|
+
[key: string]: unknown;
|
|
200
|
+
}[];
|
|
191
201
|
}
|
|
192
202
|
/** 支付记录 metadata,常含 unique_payment_number */
|
|
193
203
|
export interface OrderPaymentMetadata {
|
|
@@ -391,10 +401,12 @@ export interface OrderData {
|
|
|
391
401
|
/** 去掉 bookings 后的订单快照;展开预约行时挂在 {@link BookingData.order} 上 */
|
|
392
402
|
export type OrderWithoutBookings = Omit<OrderData, 'bookings'>;
|
|
393
403
|
/**
|
|
394
|
-
* 展开后的单条预约视图:协议 {@link OrderBookingItem} 平铺字段 + 所属订单(不含 bookings
|
|
404
|
+
* 展开后的单条预约视图:协议 {@link OrderBookingItem} 平铺字段 + 所属订单(不含 bookings)+
|
|
405
|
+
* 当前预约归属的商品行(由订单 products 按 schedule_event_id / relation_items 归集,不修改 order)
|
|
395
406
|
*/
|
|
396
407
|
export type BookingData = OrderBookingItem & {
|
|
397
408
|
order: OrderWithoutBookings;
|
|
409
|
+
products: OrderProductLineItem[];
|
|
398
410
|
};
|
|
399
411
|
/**
|
|
400
412
|
* 订单列表筛选条件(与 order.ts getFilterButtonList 等 UI 对齐)
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import type { BookingData, BookingFilters, BookingFilterResult, OrderData } from '../types';
|
|
1
|
+
import type { BookingData, BookingFilters, BookingFilterResult, OrderBookingItem, OrderData, OrderProductLineItem } from '../types';
|
|
2
2
|
export type { BookingData, BookingFilters, BookingFilterResult } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* 从整单 `order.products` 中归集属于指定 `booking` 的明细行。
|
|
5
|
+
* - 第一遍:`product.schedule_event_id === booking.schedule_event_id`(保持 products 原顺序)
|
|
6
|
+
* - 第二遍:按 `relation_items` 顺序追加 `resource_id` 与 `order_detail_id` 匹配且尚未收录的行
|
|
7
|
+
*/
|
|
8
|
+
export declare function productsForBooking(order: OrderData, booking: OrderBookingItem): OrderProductLineItem[];
|
|
3
9
|
export declare function flattenOrdersToBookings(orders: OrderData[]): BookingData[];
|
|
4
10
|
export declare function filterBookingsFromOrders(orders: OrderData[], filters: BookingFilters): BookingFilterResult;
|
|
5
11
|
export declare function sortBookings(result: BookingFilterResult, filters: BookingFilters): BookingFilterResult;
|
|
@@ -22,6 +22,7 @@ __export(filterBookings_exports, {
|
|
|
22
22
|
filterBookings: () => filterBookings,
|
|
23
23
|
filterBookingsFromOrders: () => filterBookingsFromOrders,
|
|
24
24
|
flattenOrdersToBookings: () => flattenOrdersToBookings,
|
|
25
|
+
productsForBooking: () => productsForBooking,
|
|
25
26
|
sortBookings: () => sortBookings
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(filterBookings_exports);
|
|
@@ -189,6 +190,58 @@ function matchBooking(booking, orderInfo, ctx) {
|
|
|
189
190
|
}
|
|
190
191
|
return true;
|
|
191
192
|
}
|
|
193
|
+
function productsForBooking(order, booking) {
|
|
194
|
+
var _a;
|
|
195
|
+
const products = order.products;
|
|
196
|
+
if (!Array.isArray(products) || products.length === 0)
|
|
197
|
+
return [];
|
|
198
|
+
const bookingEventId = booking.schedule_event_id;
|
|
199
|
+
const byDetailId = /* @__PURE__ */ new Map();
|
|
200
|
+
for (let i = 0, len = products.length; i < len; i++) {
|
|
201
|
+
const p = products[i];
|
|
202
|
+
const oid = p.order_detail_id;
|
|
203
|
+
if (oid === void 0 || oid === null)
|
|
204
|
+
continue;
|
|
205
|
+
const detailId = Number(oid);
|
|
206
|
+
if (Number.isNaN(detailId))
|
|
207
|
+
continue;
|
|
208
|
+
byDetailId.set(detailId, p);
|
|
209
|
+
}
|
|
210
|
+
const seen = /* @__PURE__ */ new Set();
|
|
211
|
+
const out = [];
|
|
212
|
+
for (let i = 0, len = products.length; i < len; i++) {
|
|
213
|
+
const p = products[i];
|
|
214
|
+
const oid = p.order_detail_id;
|
|
215
|
+
if (oid === void 0 || oid === null)
|
|
216
|
+
continue;
|
|
217
|
+
const detailId = Number(oid);
|
|
218
|
+
if (Number.isNaN(detailId))
|
|
219
|
+
continue;
|
|
220
|
+
if (bookingEventId !== void 0 && bookingEventId !== null && p.schedule_event_id !== void 0 && p.schedule_event_id !== null && Number(p.schedule_event_id) === Number(bookingEventId)) {
|
|
221
|
+
if (!seen.has(detailId)) {
|
|
222
|
+
seen.add(detailId);
|
|
223
|
+
out.push(p);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const relationItems = booking.relation_items;
|
|
228
|
+
if (Array.isArray(relationItems) && relationItems.length > 0) {
|
|
229
|
+
for (let r = 0, rLen = relationItems.length; r < rLen; r++) {
|
|
230
|
+
const rid = (_a = relationItems[r]) == null ? void 0 : _a.resource_id;
|
|
231
|
+
if (rid === void 0 || rid === null)
|
|
232
|
+
continue;
|
|
233
|
+
const detailId = Number(rid);
|
|
234
|
+
if (Number.isNaN(detailId) || seen.has(detailId))
|
|
235
|
+
continue;
|
|
236
|
+
const line = byDetailId.get(detailId);
|
|
237
|
+
if (line) {
|
|
238
|
+
seen.add(detailId);
|
|
239
|
+
out.push(line);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return out;
|
|
244
|
+
}
|
|
192
245
|
function flattenOrdersToBookings(orders) {
|
|
193
246
|
if (!orders || !Array.isArray(orders))
|
|
194
247
|
return [];
|
|
@@ -200,7 +253,12 @@ function flattenOrdersToBookings(orders) {
|
|
|
200
253
|
continue;
|
|
201
254
|
const { bookings: _omit, ...orderInfo } = order;
|
|
202
255
|
for (let j = 0, bLen = bookings.length; j < bLen; j++) {
|
|
203
|
-
|
|
256
|
+
const booking = bookings[j];
|
|
257
|
+
result.push({
|
|
258
|
+
...booking,
|
|
259
|
+
order: orderInfo,
|
|
260
|
+
products: productsForBooking(order, booking)
|
|
261
|
+
});
|
|
204
262
|
}
|
|
205
263
|
}
|
|
206
264
|
return result;
|
|
@@ -237,7 +295,11 @@ function filterBookingsFromOrders(orders, filters) {
|
|
|
237
295
|
const { bookings: _omit, ...rest } = order;
|
|
238
296
|
orderInfo = rest;
|
|
239
297
|
}
|
|
240
|
-
paginatedList.push({
|
|
298
|
+
paginatedList.push({
|
|
299
|
+
...booking,
|
|
300
|
+
order: orderInfo,
|
|
301
|
+
products: productsForBooking(order, booking)
|
|
302
|
+
});
|
|
241
303
|
}
|
|
242
304
|
totalCount++;
|
|
243
305
|
}
|
|
@@ -300,7 +362,10 @@ function filterBookings(bookings, filters) {
|
|
|
300
362
|
if (!matchBooking(booking, order, ctx))
|
|
301
363
|
continue;
|
|
302
364
|
if (totalCount >= startIndex && paginatedList.length < size) {
|
|
303
|
-
paginatedList.push(
|
|
365
|
+
paginatedList.push({
|
|
366
|
+
...booking,
|
|
367
|
+
products: productsForBooking(booking.order, booking)
|
|
368
|
+
});
|
|
304
369
|
}
|
|
305
370
|
totalCount++;
|
|
306
371
|
}
|
|
@@ -316,5 +381,6 @@ function filterBookings(bookings, filters) {
|
|
|
316
381
|
filterBookings,
|
|
317
382
|
filterBookingsFromOrders,
|
|
318
383
|
flattenOrdersToBookings,
|
|
384
|
+
productsForBooking,
|
|
319
385
|
sortBookings
|
|
320
386
|
});
|
|
@@ -50,15 +50,12 @@ export declare class ResourceModule extends BaseModule implements Module {
|
|
|
50
50
|
/**
|
|
51
51
|
* 创建预订
|
|
52
52
|
*/
|
|
53
|
-
createBooking(booking: Partial<ResourceBooking>): ResourceBooking;
|
|
54
53
|
/**
|
|
55
54
|
* 更新预订
|
|
56
55
|
*/
|
|
57
|
-
updateBooking(id: ResourceId, data: Partial<ResourceBooking>): ResourceBooking | undefined;
|
|
58
56
|
/**
|
|
59
57
|
* 删除预订
|
|
60
58
|
*/
|
|
61
|
-
deleteBooking(id: ResourceId): boolean;
|
|
62
59
|
/**
|
|
63
60
|
* 清空缓存
|
|
64
61
|
*/
|
|
@@ -73,8 +70,6 @@ export declare class ResourceModule extends BaseModule implements Module {
|
|
|
73
70
|
private loadResourcesByServer;
|
|
74
71
|
private loadResourcesFromSQLite;
|
|
75
72
|
private saveResourcesToSQLite;
|
|
76
|
-
private loadBookingsFromSQLite;
|
|
77
|
-
private saveBookingsToSQLite;
|
|
78
73
|
private initResourceDataSource;
|
|
79
74
|
private setupResourceSync;
|
|
80
75
|
private processSyncMessages;
|
|
@@ -29,7 +29,6 @@ var import_BaseModule = require("../../../modules/BaseModule");
|
|
|
29
29
|
var import_types = require("./types");
|
|
30
30
|
var import_types2 = require("./types");
|
|
31
31
|
var RESOURCE_STORE_NAME = "resources";
|
|
32
|
-
var BOOKING_STORE_NAME = "resource_bookings";
|
|
33
32
|
var DEFAULT_PAGE_SIZE = 999;
|
|
34
33
|
var RESOURCE_SYNC_DEBOUNCE_MS = 1e4;
|
|
35
34
|
var ResourceModule = class extends import_BaseModule.BaseModule {
|
|
@@ -103,11 +102,6 @@ var ResourceModule = class extends import_BaseModule.BaseModule {
|
|
|
103
102
|
await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
|
|
104
103
|
}
|
|
105
104
|
}
|
|
106
|
-
const cachedBookings = await this.loadBookingsFromSQLite();
|
|
107
|
-
if (cachedBookings.length > 0) {
|
|
108
|
-
this.store.bookings = (0, import_lodash_es.cloneDeep)(cachedBookings);
|
|
109
|
-
this.syncBookingsIndex();
|
|
110
|
-
}
|
|
111
105
|
}
|
|
112
106
|
getRoutes() {
|
|
113
107
|
return [];
|
|
@@ -205,54 +199,49 @@ var ResourceModule = class extends import_BaseModule.BaseModule {
|
|
|
205
199
|
/**
|
|
206
200
|
* 创建预订
|
|
207
201
|
*/
|
|
208
|
-
createBooking(booking) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
202
|
+
// createBooking(booking: Partial<ResourceBooking>): ResourceBooking {
|
|
203
|
+
// const id = booking?.id ?? Date.now()
|
|
204
|
+
// const normalized: ResourceBooking = {
|
|
205
|
+
// id,
|
|
206
|
+
// ...booking,
|
|
207
|
+
// } as ResourceBooking
|
|
208
|
+
// this.store.bookings.push(normalized)
|
|
209
|
+
// const rid = normalized.resource_id ?? normalized.resourceId
|
|
210
|
+
// if (rid !== undefined) {
|
|
211
|
+
// const existing = this.resourceIdIndex.get(rid) || []
|
|
212
|
+
// existing.push(normalized)
|
|
213
|
+
// this.resourceIdIndex.set(rid, existing)
|
|
214
|
+
// }
|
|
215
|
+
// this.saveBookingsToSQLite(this.store.bookings).catch(() => {})
|
|
216
|
+
// this.safeEmit(ResourceHooks.onBookingsChanged, this.store.bookings)
|
|
217
|
+
// return normalized
|
|
218
|
+
// }
|
|
226
219
|
/**
|
|
227
220
|
* 更新预订
|
|
228
221
|
*/
|
|
229
|
-
updateBooking(id, data) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return updated;
|
|
241
|
-
}
|
|
222
|
+
// updateBooking(id: ResourceId, data: Partial<ResourceBooking>): ResourceBooking | undefined {
|
|
223
|
+
// const index = this.store.bookings.findIndex(b => this.getIdKey(b.id) === this.getIdKey(id))
|
|
224
|
+
// if (index === -1) return undefined
|
|
225
|
+
// const old = this.store.bookings[index]
|
|
226
|
+
// const updated: ResourceBooking = { ...old, ...data, id: old.id } as ResourceBooking
|
|
227
|
+
// this.store.bookings[index] = updated
|
|
228
|
+
// this.rebuildBookingsIndex()
|
|
229
|
+
// this.saveBookingsToSQLite(this.store.bookings).catch(() => {})
|
|
230
|
+
// this.safeEmit(ResourceHooks.onBookingsChanged, this.store.bookings)
|
|
231
|
+
// return updated
|
|
232
|
+
// }
|
|
242
233
|
/**
|
|
243
234
|
* 删除预订
|
|
244
235
|
*/
|
|
245
|
-
deleteBooking(id) {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
return true;
|
|
255
|
-
}
|
|
236
|
+
// deleteBooking(id: ResourceId): boolean {
|
|
237
|
+
// const index = this.store.bookings.findIndex(b => this.getIdKey(b.id) === this.getIdKey(id))
|
|
238
|
+
// if (index === -1) return false
|
|
239
|
+
// this.store.bookings.splice(index, 1)
|
|
240
|
+
// this.rebuildBookingsIndex()
|
|
241
|
+
// this.saveBookingsToSQLite(this.store.bookings).catch(() => {})
|
|
242
|
+
// this.safeEmit(ResourceHooks.onBookingsChanged, this.store.bookings)
|
|
243
|
+
// return true
|
|
244
|
+
// }
|
|
256
245
|
/**
|
|
257
246
|
* 清空缓存
|
|
258
247
|
*/
|
|
@@ -396,31 +385,29 @@ var ResourceModule = class extends import_BaseModule.BaseModule {
|
|
|
396
385
|
});
|
|
397
386
|
}
|
|
398
387
|
}
|
|
399
|
-
async loadBookingsFromSQLite() {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
}
|
|
423
|
-
}
|
|
388
|
+
// private async loadBookingsFromSQLite(): Promise<ResourceBooking[]> {
|
|
389
|
+
// if (!this.dbManager) return []
|
|
390
|
+
// try {
|
|
391
|
+
// const bookings = await this.dbManager.getAll(BOOKING_STORE_NAME)
|
|
392
|
+
// return bookings || []
|
|
393
|
+
// } catch {
|
|
394
|
+
// return []
|
|
395
|
+
// }
|
|
396
|
+
// }
|
|
397
|
+
// private async saveBookingsToSQLite(bookings: ResourceBooking[]): Promise<void> {
|
|
398
|
+
// if (!this.dbManager) return
|
|
399
|
+
// try {
|
|
400
|
+
// await this.dbManager.clear(BOOKING_STORE_NAME)
|
|
401
|
+
// if (bookings.length === 0) return
|
|
402
|
+
// if (this.dbManager.bulkAdd) {
|
|
403
|
+
// await this.dbManager.bulkAdd(BOOKING_STORE_NAME, bookings)
|
|
404
|
+
// return
|
|
405
|
+
// }
|
|
406
|
+
// await Promise.all(bookings.map(b => this.dbManager.add(BOOKING_STORE_NAME, b)))
|
|
407
|
+
// } catch {
|
|
408
|
+
// // 忽略 SQLite 异常
|
|
409
|
+
// }
|
|
410
|
+
// }
|
|
424
411
|
// ─────────────────────────────────────────────────────────────────
|
|
425
412
|
// pubsub 同步
|
|
426
413
|
// ─────────────────────────────────────────────────────────────────
|
package/lib/server/types.d.ts
CHANGED
|
@@ -344,7 +344,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
344
344
|
};
|
|
345
345
|
setOtherData(key: string, value: any): void;
|
|
346
346
|
getOtherData(key: string): any;
|
|
347
|
-
getProductTypeById(id: number): Promise<"
|
|
347
|
+
getProductTypeById(id: number): Promise<"normal" | "duration" | "session">;
|
|
348
348
|
/**
|
|
349
349
|
* 提供给 UI 的方法,减轻 UI 层的计算压力,UI 层只需要传递 cartItemId 和 resourceCode 即返回对应的 renderList
|
|
350
350
|
*
|
|
@@ -87,10 +87,11 @@ export declare class SalesImpl extends BaseModule implements Module, SalesModule
|
|
|
87
87
|
/**
|
|
88
88
|
* 标准化单条 booking:
|
|
89
89
|
* - 过滤终态(rejected/cancelled/completed)
|
|
90
|
+
* - 当 deviceTime 早于 currentTime 时,过滤 end_time 早于 currentTime 的历史数据
|
|
90
91
|
* - 注入 status / isTimeout / reserved_status
|
|
91
92
|
*/
|
|
92
93
|
private normalizeMatchedBooking;
|
|
93
|
-
getResourceBookingList(currentTime: string, bookingList?: BookingData[]): Promise<SalesResourceBookingItem[]>;
|
|
94
|
+
getResourceBookingList(currentTime: string, bookingList?: BookingData[], deviceTime?: string): Promise<SalesResourceBookingItem[]>;
|
|
94
95
|
}
|
|
95
96
|
export { SalesImpl as Sales };
|
|
96
97
|
export default SalesImpl;
|
|
@@ -312,15 +312,19 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
312
312
|
/**
|
|
313
313
|
* 标准化单条 booking:
|
|
314
314
|
* - 过滤终态(rejected/cancelled/completed)
|
|
315
|
+
* - 当 deviceTime 早于 currentTime 时,过滤 end_time 早于 currentTime 的历史数据
|
|
315
316
|
* - 注入 status / isTimeout / reserved_status
|
|
316
317
|
*/
|
|
317
|
-
normalizeMatchedBooking(current, booking) {
|
|
318
|
+
normalizeMatchedBooking(current, deviceCurrent, booking) {
|
|
318
319
|
const appointmentStatus = String(booking.appointment_status ?? booking.status ?? "");
|
|
319
320
|
if (appointmentStatus === "rejected" || appointmentStatus === "cancelled" || appointmentStatus === "completed") {
|
|
320
321
|
return null;
|
|
321
322
|
}
|
|
322
|
-
const bookingStatus = this.getBookingStatus(appointmentStatus);
|
|
323
323
|
const endAt = this.toBookingDateTime(booking.end_date, booking.end_time);
|
|
324
|
+
const shouldFilterHistoryByCurrent = deviceCurrent.isBefore(current);
|
|
325
|
+
if (shouldFilterHistoryByCurrent && endAt.isValid() && endAt.isBefore(current))
|
|
326
|
+
return null;
|
|
327
|
+
const bookingStatus = this.getBookingStatus(appointmentStatus);
|
|
324
328
|
const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
|
|
325
329
|
const isTimeout = bookingStatus === "occupied" && endAt.isValid() && current.isAfter(endAt);
|
|
326
330
|
const timeoutTime = isTimeout ? current.diff(endAt, "minute") : void 0;
|
|
@@ -362,11 +366,14 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
362
366
|
remainingReserveTime
|
|
363
367
|
};
|
|
364
368
|
}
|
|
365
|
-
async getResourceBookingList(currentTime, bookingList = []) {
|
|
369
|
+
async getResourceBookingList(currentTime, bookingList = [], deviceTime = currentTime) {
|
|
366
370
|
var _a;
|
|
367
371
|
const current = (0, import_dayjs.default)(currentTime);
|
|
368
372
|
if (!current.isValid())
|
|
369
373
|
return [];
|
|
374
|
+
const deviceCurrent = (0, import_dayjs.default)(deviceTime);
|
|
375
|
+
if (!deviceCurrent.isValid())
|
|
376
|
+
return [];
|
|
370
377
|
const resourceResponse = await this.request.get(
|
|
371
378
|
"/shop/form/resource/page",
|
|
372
379
|
{ skip: 1, num: 999 },
|
|
@@ -376,7 +383,7 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
376
383
|
const resourceList = ((_a = resourceResponse == null ? void 0 : resourceResponse.data) == null ? void 0 : _a.list) ?? [];
|
|
377
384
|
if (!Array.isArray(resourceList) || resourceList.length === 0)
|
|
378
385
|
return [];
|
|
379
|
-
const normalizedBookings = bookingList.map((booking) => this.normalizeMatchedBooking(current, booking)).filter((booking) => Boolean(booking)).sort((left, right) => {
|
|
386
|
+
const normalizedBookings = bookingList.map((booking) => this.normalizeMatchedBooking(current, deviceCurrent, booking)).filter((booking) => Boolean(booking)).sort((left, right) => {
|
|
380
387
|
const leftStartAt = this.toBookingDateTime(left.start_date, left.start_time).valueOf();
|
|
381
388
|
const rightStartAt = this.toBookingDateTime(right.start_date, right.start_time).valueOf();
|
|
382
389
|
return leftStartAt - rightStartAt;
|
|
@@ -61,7 +61,7 @@ export interface SalesModuleAPI {
|
|
|
61
61
|
/** 重置预约列表为空 */
|
|
62
62
|
resetReservationList: () => Reservation[];
|
|
63
63
|
/** 获取资源维度的预约占用列表 */
|
|
64
|
-
getResourceBookingList: (currentTime: string, bookingList: BookingData[]) => Promise<SalesResourceBookingItem[]>;
|
|
64
|
+
getResourceBookingList: (currentTime: string, bookingList: BookingData[], deviceTime?: string) => Promise<SalesResourceBookingItem[]>;
|
|
65
65
|
/** 获取时间轴每个时间片的预约数量 */
|
|
66
66
|
getTimelineHighlights: (bookingList: BookingData[], startDateTime?: string, endDateTime?: string) => SalesTimelineHighlights;
|
|
67
67
|
}
|