@pisell/pisellos 2.1.36 → 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/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 +0 -16
- package/dist/solution/BookingByStep/index.js +57 -508
- 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/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 +0 -16
- package/lib/solution/BookingByStep/index.js +44 -316
- 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,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server 类型定义
|
|
3
|
+
*/
|
|
4
|
+
export type CacheType = 'memory' | 'storage' | 'indexDB';
|
|
5
|
+
export interface CacheProps {
|
|
6
|
+
key?: string;
|
|
7
|
+
type?: CacheType;
|
|
8
|
+
updateCache?: boolean;
|
|
9
|
+
cacheUpdateChange?: (data: any) => void;
|
|
10
|
+
}
|
|
11
|
+
export interface RequestSetting {
|
|
12
|
+
abort?: boolean;
|
|
13
|
+
headers?: any;
|
|
14
|
+
cache?: CacheProps;
|
|
15
|
+
signal?: any;
|
|
16
|
+
token?: string;
|
|
17
|
+
osServer?: boolean;
|
|
18
|
+
[key: string]: any;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 路由处理函数类型
|
|
22
|
+
*/
|
|
23
|
+
export type RouteHandler = (params: {
|
|
24
|
+
url: string;
|
|
25
|
+
method: 'get' | 'post' | 'remove' | 'put';
|
|
26
|
+
data?: any;
|
|
27
|
+
config?: RequestSetting;
|
|
28
|
+
}) => Promise<any> | any;
|
|
29
|
+
/**
|
|
30
|
+
* HTTP 方法类型
|
|
31
|
+
*/
|
|
32
|
+
export type HttpMethod = 'get' | 'post' | 'remove' | 'put';
|
|
33
|
+
/**
|
|
34
|
+
* 路由定义类型
|
|
35
|
+
*/
|
|
36
|
+
export type RouteDefinition = {
|
|
37
|
+
method: HttpMethod;
|
|
38
|
+
path: string;
|
|
39
|
+
handler: RouteHandler;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Router 对象类型
|
|
43
|
+
*/
|
|
44
|
+
export interface Router {
|
|
45
|
+
get: Record<string, RouteHandler>;
|
|
46
|
+
post: Record<string, RouteHandler>;
|
|
47
|
+
put: Record<string, RouteHandler>;
|
|
48
|
+
remove: Record<string, RouteHandler>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 模块注册配置(内部使用)
|
|
52
|
+
*/
|
|
53
|
+
export interface ModuleRegistryConfig {
|
|
54
|
+
/** 模块名称 */
|
|
55
|
+
name: string;
|
|
56
|
+
/** 模块类 */
|
|
57
|
+
moduleClass: any;
|
|
58
|
+
/** 模块完整名称(用于注册到 Core) */
|
|
59
|
+
moduleName: string;
|
|
60
|
+
/** 模块版本 */
|
|
61
|
+
version: string;
|
|
62
|
+
/** 默认 store 结构 */
|
|
63
|
+
defaultStore: Record<string, any>;
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ProductData } from '../../modules/Product/types';
|
|
2
|
+
import { FormattedProductData, LoadProductsPriceData, ProductFormatterContext } from '../modules/products/types';
|
|
3
|
+
/**
|
|
4
|
+
* 将价格数据应用到商品列表(高性能版本)
|
|
5
|
+
* 通过预构建 Map 索引,将时间复杂度从 O(n×m) 优化到 O(n+m)
|
|
6
|
+
* @param products 商品列表
|
|
7
|
+
* @param priceData 价格数据
|
|
8
|
+
* @returns 应用价格后的商品列表
|
|
9
|
+
*/
|
|
10
|
+
export declare function applyPriceDataToProducts(products: ProductData[], priceData: LoadProductsPriceData[]): ProductData[];
|
|
11
|
+
export declare const getIsSessionProduct: (product: ProductData) => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* 将详情值数据应用到商品列表
|
|
14
|
+
* @param products 商品列表
|
|
15
|
+
* @param context 格式化器上下文
|
|
16
|
+
* @returns 应用详情值后的商品列表
|
|
17
|
+
*/
|
|
18
|
+
export declare function applyDetailValueToProducts(products: ProductData[], context: ProductFormatterContext): FormattedProductData[];
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
3
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
4
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
5
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
6
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
7
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
8
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
9
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
10
|
+
import Decimal from 'decimal.js';
|
|
11
|
+
import { getScheduleStartEndTimePoints } from "../modules/schedule/utils";
|
|
12
|
+
import { getUniqueId } from "../../modules/Cart/utils";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 构建价格数据的 Map 索引结构
|
|
16
|
+
* 使用三层 Map 实现 O(1) 查询,大幅提升性能
|
|
17
|
+
* @param priceData 价格数据数组
|
|
18
|
+
* @returns 三层 Map 索引:商品、variant、bundle
|
|
19
|
+
*/
|
|
20
|
+
function buildPriceIndexMap(priceData) {
|
|
21
|
+
// 1. 商品主价格 Map: productId -> priceInfo
|
|
22
|
+
var priceMap = new Map(priceData.map(function (p) {
|
|
23
|
+
return [p.id, p];
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
// 2. Variant 价格 Map: productId -> (variantId -> variantPriceInfo)
|
|
27
|
+
var variantMap = new Map();
|
|
28
|
+
priceData.forEach(function (p) {
|
|
29
|
+
if (p.variant && p.variant.length > 0) {
|
|
30
|
+
var variantById = new Map(p.variant.map(function (v) {
|
|
31
|
+
return [v.id, v];
|
|
32
|
+
}));
|
|
33
|
+
variantMap.set(p.id, variantById);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// 3. Bundle 价格 Map: productId -> (groupId -> (itemId -> itemPriceInfo))
|
|
38
|
+
var bundleMap = new Map();
|
|
39
|
+
priceData.forEach(function (p) {
|
|
40
|
+
if (p.bundle_group && p.bundle_group.length > 0) {
|
|
41
|
+
var groupMap = new Map();
|
|
42
|
+
p.bundle_group.forEach(function (bg) {
|
|
43
|
+
var itemMap = new Map(bg.bundle_item.map(function (bi) {
|
|
44
|
+
return [bi.id, bi];
|
|
45
|
+
}));
|
|
46
|
+
groupMap.set(bg.id, itemMap);
|
|
47
|
+
});
|
|
48
|
+
bundleMap.set(p.id, groupMap);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
priceMap: priceMap,
|
|
53
|
+
variantMap: variantMap,
|
|
54
|
+
bundleMap: bundleMap
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 将价格数据应用到商品列表(高性能版本)
|
|
60
|
+
* 通过预构建 Map 索引,将时间复杂度从 O(n×m) 优化到 O(n+m)
|
|
61
|
+
* @param products 商品列表
|
|
62
|
+
* @param priceData 价格数据
|
|
63
|
+
* @returns 应用价格后的商品列表
|
|
64
|
+
*/
|
|
65
|
+
export function applyPriceDataToProducts(products, priceData) {
|
|
66
|
+
// 如果没有价格数据,直接返回原商品
|
|
67
|
+
if (!priceData || priceData.length === 0) {
|
|
68
|
+
console.log('[applyPriceDataToProducts] 没有价格数据,返回原商品');
|
|
69
|
+
return products;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 预先构建 Map 索引(O(m) 时间)
|
|
73
|
+
var _buildPriceIndexMap = buildPriceIndexMap(priceData),
|
|
74
|
+
priceMap = _buildPriceIndexMap.priceMap,
|
|
75
|
+
variantMap = _buildPriceIndexMap.variantMap,
|
|
76
|
+
bundleMap = _buildPriceIndexMap.bundleMap;
|
|
77
|
+
console.log("[applyPriceDataToProducts] \u5DF2\u6784\u5EFA\u4EF7\u683C\u7D22\u5F15\uFF0C\u5171 ".concat(priceMap.size, " \u4E2A\u5546\u54C1\u4EF7\u683C"));
|
|
78
|
+
|
|
79
|
+
// 应用价格到商品(O(n) 时间)
|
|
80
|
+
var updatedProducts = products.map(function (product) {
|
|
81
|
+
// O(1) 查询商品价格
|
|
82
|
+
var priceInfo = priceMap.get(product.id);
|
|
83
|
+
if (!priceInfo) {
|
|
84
|
+
return product;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 深拷贝商品对象
|
|
88
|
+
var updatedProduct = _objectSpread({}, product);
|
|
89
|
+
|
|
90
|
+
// 1. 更新主价格(转换为 string 类型)
|
|
91
|
+
updatedProduct.price = priceInfo.price;
|
|
92
|
+
updatedProduct.base_price = priceInfo.base_price;
|
|
93
|
+
|
|
94
|
+
// 2. 更新 variant 价格
|
|
95
|
+
if (updatedProduct.variant && updatedProduct.variant.length > 0) {
|
|
96
|
+
var productVariantMap = variantMap.get(product.id);
|
|
97
|
+
if (productVariantMap) {
|
|
98
|
+
updatedProduct.variant = updatedProduct.variant.map(function (v) {
|
|
99
|
+
var priceVariant = productVariantMap.get(v.id); // O(1)
|
|
100
|
+
if (priceVariant) {
|
|
101
|
+
return _objectSpread(_objectSpread({}, v), {}, {
|
|
102
|
+
price: String(priceVariant.price),
|
|
103
|
+
base_price: String(priceVariant.base_price)
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return v;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 3. 更新 bundle_groups 价格
|
|
112
|
+
if (updatedProduct.bundle_groups && updatedProduct.bundle_groups.length > 0) {
|
|
113
|
+
var productBundleMap = bundleMap.get(product.id);
|
|
114
|
+
if (productBundleMap) {
|
|
115
|
+
updatedProduct.bundle_groups = updatedProduct.bundle_groups.map(function (bg) {
|
|
116
|
+
var groupItemMap = productBundleMap.get(bg.id); // O(1)
|
|
117
|
+
if (!groupItemMap) return bg;
|
|
118
|
+
return _objectSpread(_objectSpread({}, bg), {}, {
|
|
119
|
+
bundle_item: bg.bundle_item.map(function (bi) {
|
|
120
|
+
var priceBi = groupItemMap.get(bi.id); // O(1)
|
|
121
|
+
if (priceBi) {
|
|
122
|
+
// 处理 markdown 类型
|
|
123
|
+
var price = priceBi.price;
|
|
124
|
+
if (priceBi.price_type === 'markdown') {
|
|
125
|
+
price = new Decimal(price || 0).mul(-1).toNumber();
|
|
126
|
+
}
|
|
127
|
+
return _objectSpread(_objectSpread({}, bi), {}, {
|
|
128
|
+
price: String(price),
|
|
129
|
+
base_price: String(priceBi.base_price)
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return bi;
|
|
133
|
+
})
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return updatedProduct;
|
|
139
|
+
});
|
|
140
|
+
console.log("[applyPriceDataToProducts] \u5DF2\u5E94\u7528\u4EF7\u683C\u5230 ".concat(updatedProducts.length, " \u4E2A\u5546\u54C1"));
|
|
141
|
+
return updatedProducts;
|
|
142
|
+
}
|
|
143
|
+
export var getIsSessionProduct = function getIsSessionProduct(product) {
|
|
144
|
+
return ['session_product', 'session_ticket'].includes(product.extension_type);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 获取是否打开详情弹窗
|
|
149
|
+
* @param product 商品
|
|
150
|
+
* @param context 格式化器上下文
|
|
151
|
+
* @returns 是否打开详情弹窗
|
|
152
|
+
*/
|
|
153
|
+
var getIsOpenDetailModal = function getIsOpenDetailModal(product, context) {
|
|
154
|
+
/** 是否为套餐组商品 */
|
|
155
|
+
var isBundleProduct = product.bundle_group_count > 0;
|
|
156
|
+
|
|
157
|
+
/** 是否为选项组商品 */
|
|
158
|
+
var isOptionProduct = product.option_group_count > 0;
|
|
159
|
+
|
|
160
|
+
/** 是否为组合规格商品 */
|
|
161
|
+
var isVariantProduct = product.is_variant > 0;
|
|
162
|
+
|
|
163
|
+
/** 是否为日程商品 */
|
|
164
|
+
var isSessionProduct = getIsSessionProduct(product);
|
|
165
|
+
|
|
166
|
+
// 获取商品关联的日程时间段
|
|
167
|
+
var scheduleTimeSlots = [];
|
|
168
|
+
if (isSessionProduct && product['schedule.ids'] && context.scheduleModule) {
|
|
169
|
+
var scheduleIds = product['schedule.ids'];
|
|
170
|
+
// 从 context 中获取完整的 scheduleList,然后过滤出商品关联的 schedule
|
|
171
|
+
var productSchedules = context.scheduleModule.getScheduleByIds(scheduleIds);
|
|
172
|
+
// 获取当前日期的所有时间段
|
|
173
|
+
scheduleTimeSlots = getScheduleStartEndTimePoints(context.schedule_date, productSchedules);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 是否打开详情弹窗 套餐组、选项组、组合规格、日程商品、日程时间段大于1个 打开详情弹窗
|
|
177
|
+
var isOpenDetailModal = isBundleProduct || isOptionProduct || isVariantProduct || scheduleTimeSlots.length > 1;
|
|
178
|
+
return {
|
|
179
|
+
isOpenDetailModal: isOpenDetailModal,
|
|
180
|
+
scheduleTimeSlots: scheduleTimeSlots
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
var formatDataKey = function formatDataKey(data) {
|
|
184
|
+
var _data$option, _data$bundle;
|
|
185
|
+
var _data = _objectSpread({}, data);
|
|
186
|
+
var key = "".concat(_data.product_id);
|
|
187
|
+
var rowKey = key;
|
|
188
|
+
|
|
189
|
+
// 组合规格
|
|
190
|
+
if (_data.product_variant_id) {
|
|
191
|
+
var str = "_".concat(_data.product_variant_id);
|
|
192
|
+
key += str;
|
|
193
|
+
rowKey += str;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 单规格
|
|
197
|
+
if (_data !== null && _data !== void 0 && (_data$option = _data.option) !== null && _data$option !== void 0 && _data$option.length) {
|
|
198
|
+
var _iterator = _createForOfIteratorHelper(_data.option),
|
|
199
|
+
_step;
|
|
200
|
+
try {
|
|
201
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
202
|
+
var item = _step.value;
|
|
203
|
+
var _str = "_".concat(item.option_group_id, "_").concat(item.product_option_item_id);
|
|
204
|
+
key += _str;
|
|
205
|
+
rowKey += "".concat(_str, "_").concat(item.quantity || item.num);
|
|
206
|
+
}
|
|
207
|
+
} catch (err) {
|
|
208
|
+
_iterator.e(err);
|
|
209
|
+
} finally {
|
|
210
|
+
_iterator.f();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// 套餐
|
|
215
|
+
if (_data !== null && _data !== void 0 && (_data$bundle = _data.bundle) !== null && _data$bundle !== void 0 && _data$bundle.length) {
|
|
216
|
+
var _iterator2 = _createForOfIteratorHelper(_data.bundle),
|
|
217
|
+
_step2;
|
|
218
|
+
try {
|
|
219
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
220
|
+
var _item = _step2.value;
|
|
221
|
+
var _str2 = "_".concat(_item.group_id, "_").concat(_item.bundle_product_id);
|
|
222
|
+
key += _str2;
|
|
223
|
+
rowKey += "".concat(_str2, "_").concat(_item.quantity || _item.num);
|
|
224
|
+
// 如果有单规格
|
|
225
|
+
if (_item !== null && _item !== void 0 && _item.option) {
|
|
226
|
+
var _iterator3 = _createForOfIteratorHelper(_item.option),
|
|
227
|
+
_step3;
|
|
228
|
+
try {
|
|
229
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
230
|
+
var opt = _step3.value;
|
|
231
|
+
var _str3 = "_".concat(opt.option_group_id, "_").concat(opt.product_option_item_id);
|
|
232
|
+
key += _str3;
|
|
233
|
+
rowKey += "".concat(_str3, "_").concat(opt.quantity || opt.num);
|
|
234
|
+
}
|
|
235
|
+
} catch (err) {
|
|
236
|
+
_iterator3.e(err);
|
|
237
|
+
} finally {
|
|
238
|
+
_iterator3.f();
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
} catch (err) {
|
|
243
|
+
_iterator2.e(err);
|
|
244
|
+
} finally {
|
|
245
|
+
_iterator2.f();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// session time
|
|
250
|
+
if (_data !== null && _data !== void 0 && _data.session) {
|
|
251
|
+
var _data$session;
|
|
252
|
+
var _str4 = "_".concat(_data === null || _data === void 0 || (_data$session = _data.session) === null || _data$session === void 0 ? void 0 : _data$session.key);
|
|
253
|
+
key += _str4;
|
|
254
|
+
rowKey += _str4;
|
|
255
|
+
}
|
|
256
|
+
if (_data !== null && _data !== void 0 && _data.schedule) {
|
|
257
|
+
var _data$schedule;
|
|
258
|
+
var _str5 = "_".concat(_data === null || _data === void 0 || (_data$schedule = _data.schedule) === null || _data$schedule === void 0 ? void 0 : _data$schedule.key);
|
|
259
|
+
key += _str5;
|
|
260
|
+
rowKey += _str5;
|
|
261
|
+
}
|
|
262
|
+
_data.key = key;
|
|
263
|
+
_data.rowKey = rowKey;
|
|
264
|
+
return _data;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 生成购物车详情值
|
|
269
|
+
* @param product 商品
|
|
270
|
+
* @param context 格式化器上下文
|
|
271
|
+
* @returns 购物车详情值
|
|
272
|
+
*/
|
|
273
|
+
var genCartDetailValue = function genCartDetailValue(product, scheduleTimeSlots) {
|
|
274
|
+
var params = {
|
|
275
|
+
product_id: product === null || product === void 0 ? void 0 : product.id,
|
|
276
|
+
option: [],
|
|
277
|
+
bundle: [],
|
|
278
|
+
product_variant_id: 0,
|
|
279
|
+
quantity: 1,
|
|
280
|
+
unique: getUniqueId(),
|
|
281
|
+
session: null
|
|
282
|
+
};
|
|
283
|
+
if (scheduleTimeSlots.length) {
|
|
284
|
+
params.session = scheduleTimeSlots.map(function (item) {
|
|
285
|
+
return _objectSpread(_objectSpread({}, item), {}, {
|
|
286
|
+
unique: getUniqueId()
|
|
287
|
+
});
|
|
288
|
+
})[0];
|
|
289
|
+
}
|
|
290
|
+
if (product !== null && product !== void 0 && product.service_times) {
|
|
291
|
+
params.service_times = product === null || product === void 0 ? void 0 : product.service_times;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// 票务订单需要返回对应的扩展属性
|
|
295
|
+
if (product !== null && product !== void 0 && product.machine_code) {
|
|
296
|
+
params.machine_code = product.machine_code;
|
|
297
|
+
}
|
|
298
|
+
if (product !== null && product !== void 0 && product['schedule.ids']) {
|
|
299
|
+
params.schedule_id = product['schedule.ids'];
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// 协议id
|
|
303
|
+
if (product !== null && product !== void 0 && product.policy) {
|
|
304
|
+
params.policy_id = product === null || product === void 0 ? void 0 : product.policy;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// appointment预约商品
|
|
308
|
+
if (product !== null && product !== void 0 && product.duration) {
|
|
309
|
+
params.duration = product.duration;
|
|
310
|
+
}
|
|
311
|
+
return formatDataKey(params);
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* 将详情值数据应用到商品列表
|
|
316
|
+
* @param products 商品列表
|
|
317
|
+
* @param context 格式化器上下文
|
|
318
|
+
* @returns 应用详情值后的商品列表
|
|
319
|
+
*/
|
|
320
|
+
export function applyDetailValueToProducts(products, context) {
|
|
321
|
+
var newProducts = products.map(function (product) {
|
|
322
|
+
/** 是否打开详情弹窗 套餐组、选项组、组合规格、日程商品、日程时间段大于1个 打开详情弹窗 */
|
|
323
|
+
var _getIsOpenDetailModal = getIsOpenDetailModal(product, context),
|
|
324
|
+
isOpenDetailModal = _getIsOpenDetailModal.isOpenDetailModal,
|
|
325
|
+
scheduleTimeSlots = _getIsOpenDetailModal.scheduleTimeSlots;
|
|
326
|
+
var cartDetailValue = null;
|
|
327
|
+
if (!isOpenDetailModal) {
|
|
328
|
+
// 生成购物车详情值
|
|
329
|
+
cartDetailValue = genCartDetailValue(product, scheduleTimeSlots);
|
|
330
|
+
}
|
|
331
|
+
return _objectSpread(_objectSpread({}, product), {}, {
|
|
332
|
+
// 是否打开详情弹窗
|
|
333
|
+
isOpenDetailModal: isOpenDetailModal,
|
|
334
|
+
// 购物车详情值
|
|
335
|
+
cartDetailValue: cartDetailValue
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
return newProducts;
|
|
339
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ScheduleItem } from '../../modules/Schedule/types';
|
|
2
|
+
import type { MenuData } from '../modules/menu/types';
|
|
3
|
+
/**
|
|
4
|
+
* 从餐牌列表中提取所有 schedule IDs
|
|
5
|
+
* @param menus 餐牌列表
|
|
6
|
+
* @returns 去重后的日程ID数组
|
|
7
|
+
*/
|
|
8
|
+
export declare function extractScheduleIdsFromMenus(menus: MenuData[]): number[];
|
|
9
|
+
/**
|
|
10
|
+
* 从日程列表中提取所有时间点
|
|
11
|
+
* @param schedules 日程列表
|
|
12
|
+
* @returns 排序后的时间点数组,格式为 ["10:00", "12:00", "14:00", "18:00"]
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractTimePointsFromSchedules(schedules: ScheduleItem[]): string[];
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
2
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
3
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
5
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
6
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
7
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
8
|
+
import { extractTimeFromDateTime, sortTimePoints } from "./time";
|
|
9
|
+
/**
|
|
10
|
+
* 从餐牌列表中提取所有 schedule IDs
|
|
11
|
+
* @param menus 餐牌列表
|
|
12
|
+
* @returns 去重后的日程ID数组
|
|
13
|
+
*/
|
|
14
|
+
export function extractScheduleIdsFromMenus(menus) {
|
|
15
|
+
var scheduleIds = menus.reduce(function (ids, menu) {
|
|
16
|
+
if (menu.schedule && Array.isArray(menu.schedule)) {
|
|
17
|
+
return [].concat(_toConsumableArray(ids), _toConsumableArray(menu.schedule));
|
|
18
|
+
}
|
|
19
|
+
return ids;
|
|
20
|
+
}, []);
|
|
21
|
+
|
|
22
|
+
// 去重
|
|
23
|
+
return Array.from(new Set(scheduleIds));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 从日程列表中提取所有时间点
|
|
28
|
+
* @param schedules 日程列表
|
|
29
|
+
* @returns 排序后的时间点数组,格式为 ["10:00", "12:00", "14:00", "18:00"]
|
|
30
|
+
*/
|
|
31
|
+
export function extractTimePointsFromSchedules(schedules) {
|
|
32
|
+
var timePointsSet = new Set();
|
|
33
|
+
var _iterator = _createForOfIteratorHelper(schedules),
|
|
34
|
+
_step;
|
|
35
|
+
try {
|
|
36
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
37
|
+
var schedule = _step.value;
|
|
38
|
+
switch (schedule.type) {
|
|
39
|
+
case 'standard':
|
|
40
|
+
// 标准类型:从 start_time 和 end_time 中提取时间部分
|
|
41
|
+
if (schedule.start_time) {
|
|
42
|
+
var startTime = extractTimeFromDateTime(schedule.start_time);
|
|
43
|
+
if (startTime) timePointsSet.add(startTime);
|
|
44
|
+
}
|
|
45
|
+
if (schedule.end_time) {
|
|
46
|
+
var endTime = extractTimeFromDateTime(schedule.end_time);
|
|
47
|
+
if (endTime) timePointsSet.add(endTime);
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
case 'time-slots':
|
|
51
|
+
// 时间段类型:从 time_slot 数组中提取时间
|
|
52
|
+
if (schedule.time_slot && Array.isArray(schedule.time_slot)) {
|
|
53
|
+
var _iterator2 = _createForOfIteratorHelper(schedule.time_slot),
|
|
54
|
+
_step2;
|
|
55
|
+
try {
|
|
56
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
57
|
+
var slot = _step2.value;
|
|
58
|
+
if (slot.start_time) {
|
|
59
|
+
timePointsSet.add(slot.start_time);
|
|
60
|
+
}
|
|
61
|
+
if (slot.end_time) {
|
|
62
|
+
timePointsSet.add(slot.end_time);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} catch (err) {
|
|
66
|
+
_iterator2.e(err);
|
|
67
|
+
} finally {
|
|
68
|
+
_iterator2.f();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
case 'designation':
|
|
73
|
+
// 指定日期类型:从 designation 中提取时间
|
|
74
|
+
if (schedule.designation) {
|
|
75
|
+
var designations = Array.isArray(schedule.designation) ? schedule.designation : [schedule.designation];
|
|
76
|
+
var _iterator3 = _createForOfIteratorHelper(designations),
|
|
77
|
+
_step3;
|
|
78
|
+
try {
|
|
79
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
80
|
+
var des = _step3.value;
|
|
81
|
+
if (des.start_time) {
|
|
82
|
+
timePointsSet.add(des.start_time);
|
|
83
|
+
}
|
|
84
|
+
if (des.end_time) {
|
|
85
|
+
timePointsSet.add(des.end_time);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} catch (err) {
|
|
89
|
+
_iterator3.e(err);
|
|
90
|
+
} finally {
|
|
91
|
+
_iterator3.f();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
default:
|
|
96
|
+
console.warn("[ScheduleUtils] \u672A\u77E5\u7684\u65E5\u7A0B\u7C7B\u578B: ".concat(schedule.type));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 转换为数组并排序
|
|
101
|
+
} catch (err) {
|
|
102
|
+
_iterator.e(err);
|
|
103
|
+
} finally {
|
|
104
|
+
_iterator.f();
|
|
105
|
+
}
|
|
106
|
+
var timePoints = Array.from(timePointsSet);
|
|
107
|
+
return sortTimePoints(timePoints);
|
|
108
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 从日期时间字符串中提取时间部分
|
|
3
|
+
* @param dateTime 日期时间字符串,格式如 "2024-01-01 10:00:00"
|
|
4
|
+
* @returns 时间字符串,格式如 "10:00"
|
|
5
|
+
*/
|
|
6
|
+
export declare function extractTimeFromDateTime(dateTime: string): string | null;
|
|
7
|
+
/**
|
|
8
|
+
* 将时间字符串转换为分钟数(用于排序)
|
|
9
|
+
* @param timeStr 时间字符串,格式如 "10:00" 或 "14:30"
|
|
10
|
+
* @returns 从00:00开始的分钟数
|
|
11
|
+
*/
|
|
12
|
+
export declare function timeStringToMinutes(timeStr: string): number;
|
|
13
|
+
/**
|
|
14
|
+
* 对时间点数组进行排序
|
|
15
|
+
* @param timePoints 时间点数组
|
|
16
|
+
* @returns 排序后的时间点数组
|
|
17
|
+
*/
|
|
18
|
+
export declare function sortTimePoints(timePoints: string[]): string[];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 从日期时间字符串中提取时间部分
|
|
5
|
+
* @param dateTime 日期时间字符串,格式如 "2024-01-01 10:00:00"
|
|
6
|
+
* @returns 时间字符串,格式如 "10:00"
|
|
7
|
+
*/
|
|
8
|
+
export function extractTimeFromDateTime(dateTime) {
|
|
9
|
+
if (!dateTime) return null;
|
|
10
|
+
|
|
11
|
+
// 使用 dayjs 解析日期时间
|
|
12
|
+
var date = dayjs(dateTime);
|
|
13
|
+
if (!date.isValid()) {
|
|
14
|
+
console.warn("[TimeUtils] \u65E0\u6548\u7684\u65E5\u671F\u65F6\u95F4\u683C\u5F0F: ".concat(dateTime));
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// 返回 HH:mm 格式的时间
|
|
19
|
+
return date.format('HH:mm');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 将时间字符串转换为分钟数(用于排序)
|
|
24
|
+
* @param timeStr 时间字符串,格式如 "10:00" 或 "14:30"
|
|
25
|
+
* @returns 从00:00开始的分钟数
|
|
26
|
+
*/
|
|
27
|
+
export function timeStringToMinutes(timeStr) {
|
|
28
|
+
if (!timeStr) return 0;
|
|
29
|
+
|
|
30
|
+
// 使用 dayjs 解析时间字符串
|
|
31
|
+
// 由于只有时间没有日期,我们添加一个固定日期来解析
|
|
32
|
+
var date = dayjs("2000-01-01 ".concat(timeStr), 'YYYY-MM-DD HH:mm');
|
|
33
|
+
if (!date.isValid()) {
|
|
34
|
+
console.warn("[TimeUtils] \u65E0\u6548\u7684\u65F6\u95F4\u683C\u5F0F: ".concat(timeStr));
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 计算从00:00开始的分钟数
|
|
39
|
+
return date.hour() * 60 + date.minute();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 对时间点数组进行排序
|
|
44
|
+
* @param timePoints 时间点数组
|
|
45
|
+
* @returns 排序后的时间点数组
|
|
46
|
+
*/
|
|
47
|
+
export function sortTimePoints(timePoints) {
|
|
48
|
+
return timePoints.sort(function (a, b) {
|
|
49
|
+
var timeA = timeStringToMinutes(a);
|
|
50
|
+
var timeB = timeStringToMinutes(b);
|
|
51
|
+
return timeA - timeB;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -324,22 +324,6 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
324
324
|
success: boolean;
|
|
325
325
|
minAvailableCount: number;
|
|
326
326
|
};
|
|
327
|
-
/**
|
|
328
|
-
* 将 ProductData 转换为 CartItem,但不添加到购物车
|
|
329
|
-
* 参考 addProductToCart 方法的实现
|
|
330
|
-
*/
|
|
331
|
-
private convertProductToCartItem;
|
|
332
|
-
checkMaxDurationCapacityForDetailNums({ product, date, account, }: {
|
|
333
|
-
product: ProductData;
|
|
334
|
-
date?: {
|
|
335
|
-
startTime: string;
|
|
336
|
-
endTime: string;
|
|
337
|
-
} | null;
|
|
338
|
-
account?: Account | null;
|
|
339
|
-
}): {
|
|
340
|
-
success: boolean;
|
|
341
|
-
minAvailableCount: number;
|
|
342
|
-
};
|
|
343
327
|
setOtherData(key: string, value: any): void;
|
|
344
328
|
getOtherData(key: string): any;
|
|
345
329
|
getProductTypeById(id: number): Promise<"normal" | "duration" | "session">;
|