@pisell/pisellos 2.3.74 → 2.3.76
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.js +6 -10
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/model/strategy/adapter/walletPass/example.js +3 -26
- package/dist/model/strategy/strategy-example.js +5 -19
- package/dist/modules/Cart/index.js +0 -3
- package/dist/modules/Cart/utils/cartProduct.js +0 -1
- package/dist/modules/Date/index.js +1 -5
- package/dist/modules/Discount/index.js +2 -4
- package/dist/modules/OpenData/index.js +0 -2
- package/dist/modules/Order/index.d.ts +1 -1
- package/dist/modules/Order/index.js +75 -91
- package/dist/modules/Order/types.d.ts +3 -1
- package/dist/modules/Payment/index.js +97 -162
- package/dist/modules/Rules/index.js +1 -4
- package/dist/modules/Schedule/index.js +0 -1
- package/dist/modules/Schedule/utils.js +0 -1
- package/dist/modules/Step/index.js +0 -1
- package/dist/plugins/request.js +1 -4
- package/dist/plugins/window.js +2 -6
- package/dist/server/index.js +97 -129
- package/dist/server/modules/menu/index.js +32 -41
- package/dist/server/modules/order/index.js +2 -4
- package/dist/server/modules/products/index.js +24 -42
- package/dist/server/modules/quotation/index.js +29 -38
- package/dist/server/modules/resource/index.js +3 -4
- package/dist/server/modules/schedule/index.js +27 -35
- package/dist/server/utils/product.js +0 -1
- package/dist/solution/BaseSales/index.js +100 -72
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +5 -0
- package/dist/solution/BaseSales/utils/cartPromotion.js +15 -6
- package/dist/solution/BookingByStep/index.js +7 -59
- package/dist/solution/BookingByStep/utils/capacity.js +1 -11
- package/dist/solution/BookingByStep/utils/resources.js +1 -3
- package/dist/solution/BookingByStep/utils/timeslots.js +2 -43
- package/dist/solution/BookingTicket/index.js +0 -2
- package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +6 -7
- package/dist/solution/BookingTicket/utils/scan/handleScan.js +25 -31
- package/dist/solution/BookingTicket/utils/scan/index.js +6 -10
- package/dist/solution/BuyTickets/index.js +9 -12
- package/dist/solution/Checkout/index.js +177 -252
- package/dist/solution/Checkout/utils/index.js +4 -16
- package/dist/solution/RegisterAndLogin/index.js +30 -76
- package/dist/solution/ScanOrder/index.js +50 -60
- package/dist/solution/ShopDiscount/index.js +2 -7
- package/dist/solution/VenueBooking/index.js +45 -55
- package/dist/utils/task.js +15 -18
- package/dist/utils/watch.js +0 -1
- package/lib/apis/picoding.js +2 -0
- package/lib/core/index.js +134 -134
- package/lib/effects/index.js +46 -57
- package/lib/index.js +82 -49
- package/lib/model/index.js +14 -21
- package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +162 -236
- package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
- package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
- package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
- package/lib/model/strategy/adapter/index.js +100 -64
- package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
- package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
- package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
- package/lib/model/strategy/adapter/itemRule/index.js +83 -57
- package/lib/model/strategy/adapter/itemRule/type.js +97 -36
- package/lib/model/strategy/adapter/promotion/adapter.js +91 -69
- package/lib/model/strategy/adapter/promotion/evaluator.js +444 -310
- package/lib/model/strategy/adapter/promotion/examples.js +222 -234
- package/lib/model/strategy/adapter/promotion/index.js +1 -0
- package/lib/model/strategy/adapter/promotion/type.js +243 -36
- package/lib/model/strategy/adapter/type.js +4 -16
- package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -150
- package/lib/model/strategy/adapter/walletPass/example.js +217 -190
- package/lib/model/strategy/adapter/walletPass/index.js +75 -51
- package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
- package/lib/model/strategy/adapter/walletPass/type.js +4 -16
- package/lib/model/strategy/adapter/walletPass/utils.js +588 -378
- package/lib/model/strategy/engine.js +270 -168
- package/lib/model/strategy/index.js +49 -34
- package/lib/model/strategy/strategy-example.js +243 -239
- package/lib/model/strategy/type.js +100 -40
- package/lib/modules/Account/index.js +39 -53
- package/lib/modules/Account/types.js +20 -33
- package/lib/modules/AccountList/index.js +116 -154
- package/lib/modules/AccountList/types.js +30 -31
- package/lib/modules/AccountList/utils.js +18 -30
- package/lib/modules/BaseModule.js +23 -42
- package/lib/modules/BookingContext/index.js +158 -136
- package/lib/modules/BookingContext/types.js +46 -32
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +138 -146
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +78 -83
- package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +170 -150
- package/lib/modules/BookingContext/utils/flexible.js +38 -55
- package/lib/modules/BookingContext/utils/formatResourceList.js +19 -34
- package/lib/modules/BookingContext/utils/index.js +124 -41
- package/lib/modules/BookingContext/utils/noResource.js +58 -70
- package/lib/modules/BookingContext/utils/orderLineDisplay.js +14 -41
- package/lib/modules/BookingContext/utils/productExtend.js +202 -155
- package/lib/modules/BookingContext/utils/resourceErrors.js +53 -53
- package/lib/modules/BookingContext/utils/resourceSelection.js +19 -41
- package/lib/modules/BookingContext/utils/resources.js +209 -167
- package/lib/modules/BookingContext/utils/serviceTimes.js +115 -116
- package/lib/modules/BookingContext/utils/timeSlices.js +76 -86
- package/lib/modules/Cart/index.js +170 -124
- package/lib/modules/Cart/types.js +46 -51
- package/lib/modules/Cart/utils/cartAccount.js +40 -39
- package/lib/modules/Cart/utils/cartDate.js +56 -61
- package/lib/modules/Cart/utils/cartDiscount.js +28 -33
- package/lib/modules/Cart/utils/cartNote.js +27 -32
- package/lib/modules/Cart/utils/cartProduct.js +321 -251
- package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
- package/lib/modules/Cart/utils/cartResource.js +70 -78
- package/lib/modules/Cart/utils/changePrice.js +22 -50
- package/lib/modules/Cart/utils/index.js +106 -48
- package/lib/modules/Customer/constants.js +13 -34
- package/lib/modules/Customer/index.js +235 -172
- package/lib/modules/Customer/types.js +38 -35
- package/lib/modules/Date/index.js +116 -115
- package/lib/modules/Date/types.js +16 -28
- package/lib/modules/Date/utils.js +174 -123
- package/lib/modules/Discount/index.js +122 -127
- package/lib/modules/Discount/types.js +9 -31
- package/lib/modules/Guests/index.js +30 -56
- package/lib/modules/Guests/types.js +23 -33
- package/lib/modules/Holder/index.js +209 -189
- package/lib/modules/Holder/types.js +4 -16
- package/lib/modules/Holder/utils.js +20 -49
- package/lib/modules/OpenData/index.js +70 -76
- package/lib/modules/OpenData/types.js +4 -16
- package/lib/modules/OpenData/utils.js +44 -78
- package/lib/modules/Order/index.d.ts +1 -1
- package/lib/modules/Order/index.js +1733 -2121
- package/lib/modules/Order/payment-utils.js +77 -120
- package/lib/modules/Order/types.d.ts +3 -1
- package/lib/modules/Order/types.js +88 -35
- package/lib/modules/Order/utils/bundleDiscountHydration.js +41 -74
- package/lib/modules/Order/utils/discountProductLineIdentity.js +142 -100
- package/lib/modules/Order/utils/manualProductDiscount.js +124 -123
- package/lib/modules/Order/utils/orderCollectionIdentity.js +184 -244
- package/lib/modules/Order/utils.js +814 -647
- package/lib/modules/Payment/cash.js +20 -33
- package/lib/modules/Payment/cashRecommendationAlgorithm.js +145 -76
- package/lib/modules/Payment/eftpos.js +16 -30
- package/lib/modules/Payment/index.js +532 -399
- package/lib/modules/Payment/mx51.js +1 -0
- package/lib/modules/Payment/types.js +230 -108
- package/lib/modules/Payment/utils.js +52 -51
- package/lib/modules/Payment/walletpass.js +485 -660
- package/lib/modules/Product/index.js +51 -46
- package/lib/modules/Product/types.js +4 -16
- package/lib/modules/Product/utils.js +32 -33
- package/lib/modules/ProductList/index.js +113 -123
- package/lib/modules/ProductList/types.js +9 -31
- package/lib/modules/Quotation/index.js +81 -118
- package/lib/modules/Quotation/types.js +4 -16
- package/lib/modules/Resource/index.js +27 -59
- package/lib/modules/Resource/types.js +22 -32
- package/lib/modules/Resource/utils.js +30 -38
- package/lib/modules/ResourcePlanner/index.js +25 -23
- package/lib/modules/ResourcePlanner/localClock.js +54 -119
- package/lib/modules/ResourcePlanner/planner.js +589 -770
- package/lib/modules/ResourcePlanner/types.js +10 -29
- package/lib/modules/Rules/index.js +1218 -959
- package/lib/modules/Rules/types.js +17 -40
- package/lib/modules/SalesSummary/index.js +85 -90
- package/lib/modules/SalesSummary/types.js +4 -16
- package/lib/modules/SalesSummary/utils.js +355 -430
- package/lib/modules/ScanOrderLogger/index.js +59 -79
- package/lib/modules/ScanOrderLogger/providers/feishu.js +54 -78
- package/lib/modules/ScanOrderLogger/providers/grafana.js +13 -36
- package/lib/modules/ScanOrderLogger/types.js +4 -16
- package/lib/modules/Schedule/getDateIsInSchedule.js +334 -163
- package/lib/modules/Schedule/index.js +100 -114
- package/lib/modules/Schedule/type.js +4 -16
- package/lib/modules/Schedule/types.js +4 -16
- package/lib/modules/Schedule/utils.js +433 -291
- package/lib/modules/Step/index.js +40 -52
- package/lib/modules/Step/tyeps.js +4 -16
- package/lib/modules/Summary/index.js +66 -71
- package/lib/modules/Summary/types.js +4 -16
- package/lib/modules/Summary/utils.js +773 -418
- package/lib/modules/SurchargeList/index.js +46 -60
- package/lib/modules/SurchargeList/types.js +4 -16
- package/lib/modules/index.js +245 -63
- package/lib/plugins/app.js +4 -16
- package/lib/plugins/index.js +36 -25
- package/lib/plugins/request.js +137 -126
- package/lib/plugins/shopStore.js +4 -16
- package/lib/plugins/user.js +4 -16
- package/lib/plugins/window.js +171 -179
- package/lib/server/index.js +3050 -2665
- package/lib/server/modules/floor-plan/index.js +118 -134
- package/lib/server/modules/floor-plan/types.js +15 -30
- package/lib/server/modules/index.js +106 -68
- package/lib/server/modules/menu/index.js +142 -122
- package/lib/server/modules/menu/types.js +18 -31
- package/lib/server/modules/order/index.js +784 -1002
- package/lib/server/modules/order/types.js +122 -33
- package/lib/server/modules/order/utils/filterBookings.js +219 -194
- package/lib/server/modules/order/utils/filterOrders.js +118 -92
- package/lib/server/modules/payment/index.js +59 -83
- package/lib/server/modules/payment/types.js +4 -16
- package/lib/server/modules/products/index.js +583 -471
- package/lib/server/modules/products/types.js +44 -34
- package/lib/server/modules/quotation/index.js +137 -172
- package/lib/server/modules/quotation/types.js +21 -31
- package/lib/server/modules/resource/index.js +220 -186
- package/lib/server/modules/resource/types.js +42 -33
- package/lib/server/modules/schedule/index.js +135 -123
- package/lib/server/modules/schedule/types.js +14 -21
- package/lib/server/modules/schedule/utils.js +334 -163
- package/lib/server/types.js +4 -16
- package/lib/server/utils/index.js +25 -23
- package/lib/server/utils/product.js +196 -139
- package/lib/server/utils/schedule.js +34 -41
- package/lib/server/utils/small-ticket.js +479 -456
- package/lib/server/utils/time.js +40 -49
- package/lib/solution/BaseSales/index.js +1220 -1412
- package/lib/solution/BaseSales/types.js +42 -38
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +5 -0
- package/lib/solution/BaseSales/utils/cartPromotion.js +652 -498
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +85 -105
- package/lib/solution/BaseSales/utils/quotationPrice.js +56 -114
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +108 -145
- package/lib/solution/BaseSales/utils.js +158 -143
- package/lib/solution/BookingByStep/index.js +1527 -1340
- package/lib/solution/BookingByStep/types.js +40 -99
- package/lib/solution/BookingByStep/utils/capacity.js +192 -160
- package/lib/solution/BookingByStep/utils/products.js +42 -52
- package/lib/solution/BookingByStep/utils/resources.js +527 -330
- package/lib/solution/BookingByStep/utils/stock.js +65 -44
- package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
- package/lib/solution/BookingTicket/index.js +607 -522
- package/lib/solution/BookingTicket/types.js +99 -77
- package/lib/solution/BookingTicket/utils/addProductDecision.js +226 -189
- package/lib/solution/BookingTicket/utils/addTimeAvailability.js +58 -89
- package/lib/solution/BookingTicket/utils/bookingStatus.js +107 -78
- package/lib/solution/BookingTicket/utils/cartView.js +114 -99
- package/lib/solution/BookingTicket/utils/exampleData.js +185 -0
- package/lib/solution/BookingTicket/utils/orderCustomer.js +18 -41
- package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +219 -86
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +168 -116
- package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +79 -91
- package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +54 -41
- package/lib/solution/BookingTicket/utils/scan/handleScan.js +84 -81
- package/lib/solution/BookingTicket/utils/scan/index.js +98 -104
- package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
- package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +52 -64
- package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +56 -58
- package/lib/solution/BookingTicket/utils/weighingProductSku.js +34 -48
- package/lib/solution/BuyTickets/index.js +67 -70
- package/lib/solution/BuyTickets/types.js +22 -38
- package/lib/solution/Checkout/index.js +1451 -1158
- package/lib/solution/Checkout/types.js +91 -61
- package/lib/solution/Checkout/utils/index.js +228 -156
- package/lib/solution/PlaceOrder/index.js +55 -0
- package/lib/solution/RegisterAndLogin/config.js +493 -460
- package/lib/solution/RegisterAndLogin/index.js +633 -630
- package/lib/solution/RegisterAndLogin/types.js +189 -76
- package/lib/solution/RegisterAndLogin/utils.js +183 -125
- package/lib/solution/Sales/index.js +328 -324
- package/lib/solution/Sales/types.js +27 -33
- package/lib/solution/ScanOrder/index.js +832 -864
- package/lib/solution/ScanOrder/types.js +33 -34
- package/lib/solution/ScanOrder/utils.js +409 -374
- package/lib/solution/ShopDiscount/index.js +226 -232
- package/lib/solution/ShopDiscount/types.js +15 -37
- package/lib/solution/ShopDiscount/utils.js +300 -172
- package/lib/solution/UnifiedBookingSales/index.js +1035 -1201
- package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.js +99 -159
- package/lib/solution/UnifiedBookingSales/types.js +10 -32
- package/lib/solution/VenueBooking/index.js +811 -879
- package/lib/solution/VenueBooking/types.js +19 -39
- package/lib/solution/VenueBooking/utils/dateSummary.js +27 -56
- package/lib/solution/VenueBooking/utils/resource.js +31 -54
- package/lib/solution/VenueBooking/utils/slotMerge.js +94 -107
- package/lib/solution/VenueBooking/utils/timeSlot.js +132 -132
- package/lib/solution/VenueBooking/utils.js +130 -67
- package/lib/solution/index.js +124 -41
- package/lib/store/createStore.js +32 -29
- package/lib/types/index.js +4 -16
- package/lib/utils/payment-number.js +26 -46
- package/lib/utils/task.js +36 -36
- package/lib/utils/watch.js +81 -47
- package/package.json +2 -1
|
@@ -1,48 +1,52 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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/model/strategy/engine.ts
|
|
20
|
-
var engine_exports = {};
|
|
21
|
-
__export(engine_exports, {
|
|
22
|
-
StrategyEngine: () => StrategyEngine,
|
|
23
|
-
createStrategyEngine: () => createStrategyEngine,
|
|
24
|
-
evaluate: () => evaluate
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
25
5
|
});
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
6
|
+
exports.StrategyEngine = void 0;
|
|
7
|
+
exports.createStrategyEngine = createStrategyEngine;
|
|
8
|
+
exports.evaluate = evaluate;
|
|
9
|
+
var _type = require("./type");
|
|
10
|
+
/**
|
|
11
|
+
* 策略模型 - 核心实现
|
|
12
|
+
*
|
|
13
|
+
* 完全业务无关的通用策略引擎
|
|
14
|
+
* 支持条件评估、动作匹配、结果返回
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// ============================================
|
|
18
|
+
// 策略引擎实现
|
|
19
|
+
// ============================================
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 策略引擎
|
|
23
|
+
*
|
|
24
|
+
* 核心职责:
|
|
25
|
+
* 1. 递归评估条件组
|
|
26
|
+
* 2. 收集满足条件的 actionIds
|
|
27
|
+
* 3. 根据 actionIds 获取 ActionEffect 对象
|
|
28
|
+
* 4. 按 priority 排序返回
|
|
29
|
+
*/
|
|
30
|
+
class StrategyEngine {
|
|
31
|
+
options;
|
|
32
|
+
operatorHandlers;
|
|
29
33
|
constructor(options = {}) {
|
|
30
34
|
this.options = {
|
|
31
35
|
debug: options.debug ?? false,
|
|
32
36
|
enableTrace: options.enableTrace ?? false,
|
|
33
37
|
operatorHandlers: options.operatorHandlers ?? {},
|
|
34
|
-
errorHandler: options.errorHandler ?? (
|
|
38
|
+
errorHandler: options.errorHandler ?? (error => console.error(error))
|
|
35
39
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
);
|
|
40
|
+
|
|
41
|
+
// 初始化内置运算符处理器
|
|
42
|
+
this.operatorHandlers = new Map(Object.entries(this.options.operatorHandlers));
|
|
39
43
|
this.initializeBuiltInOperators();
|
|
40
44
|
}
|
|
45
|
+
|
|
41
46
|
/**
|
|
42
47
|
* 评估策略
|
|
43
48
|
*/
|
|
44
49
|
evaluate(config, context) {
|
|
45
|
-
var _a, _b;
|
|
46
50
|
const startTime = Date.now();
|
|
47
51
|
const trace = {
|
|
48
52
|
steps: [],
|
|
@@ -50,23 +54,23 @@ var StrategyEngine = class {
|
|
|
50
54
|
errors: []
|
|
51
55
|
};
|
|
52
56
|
try {
|
|
57
|
+
// 验证配置
|
|
53
58
|
this.validateConfig(config);
|
|
54
59
|
if (this.options.enableTrace) {
|
|
55
60
|
trace.steps.push({
|
|
56
|
-
step:
|
|
57
|
-
status:
|
|
61
|
+
step: 'validate_config',
|
|
62
|
+
status: 'success',
|
|
58
63
|
duration: Date.now() - startTime
|
|
59
64
|
});
|
|
60
65
|
}
|
|
66
|
+
|
|
67
|
+
// 递归评估条件组,收集 actionIds
|
|
61
68
|
const evaluateStart = Date.now();
|
|
62
|
-
const evaluationResult = this.evaluateConditionGroup(
|
|
63
|
-
config.conditions,
|
|
64
|
-
context
|
|
65
|
-
);
|
|
69
|
+
const evaluationResult = this.evaluateConditionGroup(config.conditions, context);
|
|
66
70
|
if (this.options.enableTrace) {
|
|
67
71
|
trace.steps.push({
|
|
68
|
-
step:
|
|
69
|
-
status:
|
|
72
|
+
step: 'evaluate_conditions',
|
|
73
|
+
status: 'success',
|
|
70
74
|
duration: Date.now() - evaluateStart,
|
|
71
75
|
details: {
|
|
72
76
|
satisfied: evaluationResult.satisfied,
|
|
@@ -74,46 +78,51 @@ var StrategyEngine = class {
|
|
|
74
78
|
}
|
|
75
79
|
});
|
|
76
80
|
}
|
|
81
|
+
|
|
82
|
+
// 根据 actionIds 获取 ActionEffect 对象
|
|
77
83
|
const actionStart = Date.now();
|
|
78
|
-
const matchedActions = this.getActionsByIds(
|
|
79
|
-
evaluationResult.actionIds,
|
|
80
|
-
config.actions
|
|
81
|
-
);
|
|
84
|
+
const matchedActions = this.getActionsByIds(evaluationResult.actionIds, config.actions);
|
|
82
85
|
if (this.options.enableTrace) {
|
|
83
86
|
trace.steps.push({
|
|
84
|
-
step:
|
|
85
|
-
status:
|
|
87
|
+
step: 'get_actions',
|
|
88
|
+
status: 'success',
|
|
86
89
|
duration: Date.now() - actionStart,
|
|
87
|
-
details: {
|
|
90
|
+
details: {
|
|
91
|
+
matchedCount: matchedActions.length
|
|
92
|
+
}
|
|
88
93
|
});
|
|
89
94
|
}
|
|
95
|
+
|
|
96
|
+
// 按 priority 排序(降序)
|
|
90
97
|
const sortStart = Date.now();
|
|
91
98
|
const sortedActions = this.sortActionsByPriority(matchedActions);
|
|
92
99
|
if (this.options.enableTrace) {
|
|
93
100
|
trace.steps.push({
|
|
94
|
-
step:
|
|
95
|
-
status:
|
|
101
|
+
step: 'sort_actions',
|
|
102
|
+
status: 'success',
|
|
96
103
|
duration: Date.now() - sortStart
|
|
97
104
|
});
|
|
98
105
|
}
|
|
106
|
+
|
|
107
|
+
// 构建结果 - applicable 基于条件是否满足,而不是 actionIds 数量
|
|
99
108
|
const applicable = evaluationResult.satisfied;
|
|
100
109
|
const result = {
|
|
101
110
|
success: true,
|
|
102
111
|
applicable,
|
|
103
|
-
code: applicable ?
|
|
104
|
-
message: applicable ?
|
|
112
|
+
code: applicable ? _type.SUCCESS_CODES.SUCCESS : _type.NOT_APPLICABLE_CODES.CONDITION_NOT_MET,
|
|
113
|
+
message: applicable ? 'Strategy is applicable' : 'Conditions not met',
|
|
105
114
|
matched: {
|
|
106
115
|
conditions: applicable,
|
|
107
116
|
actionIds: evaluationResult.actionIds,
|
|
108
117
|
details: {},
|
|
109
|
-
...applicable ? {} : {
|
|
110
|
-
failedField:
|
|
118
|
+
...(applicable ? {} : {
|
|
119
|
+
failedField: evaluationResult.failedRules[0]?.field,
|
|
111
120
|
failedRules: evaluationResult.failedRules
|
|
112
|
-
}
|
|
121
|
+
})
|
|
113
122
|
},
|
|
114
123
|
matchedActions: sortedActions,
|
|
115
124
|
outputs: {},
|
|
116
|
-
config
|
|
125
|
+
config: config
|
|
117
126
|
};
|
|
118
127
|
trace.duration = Date.now() - startTime;
|
|
119
128
|
if (this.options.enableTrace) {
|
|
@@ -121,10 +130,10 @@ var StrategyEngine = class {
|
|
|
121
130
|
}
|
|
122
131
|
return result;
|
|
123
132
|
} catch (error) {
|
|
124
|
-
const errorMessage = error instanceof Error ? error.message :
|
|
133
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
125
134
|
if (this.options.enableTrace) {
|
|
126
|
-
|
|
127
|
-
step:
|
|
135
|
+
trace.errors?.push({
|
|
136
|
+
step: 'evaluation',
|
|
128
137
|
error: errorMessage,
|
|
129
138
|
timestamp: Date.now()
|
|
130
139
|
});
|
|
@@ -134,7 +143,7 @@ var StrategyEngine = class {
|
|
|
134
143
|
return {
|
|
135
144
|
success: false,
|
|
136
145
|
applicable: false,
|
|
137
|
-
code:
|
|
146
|
+
code: _type.ERROR_CODES.EVALUATION_ERROR,
|
|
138
147
|
message: errorMessage,
|
|
139
148
|
matched: {
|
|
140
149
|
conditions: false,
|
|
@@ -143,11 +152,12 @@ var StrategyEngine = class {
|
|
|
143
152
|
},
|
|
144
153
|
matchedActions: [],
|
|
145
154
|
outputs: {},
|
|
146
|
-
trace: this.options.enableTrace ? trace :
|
|
147
|
-
config
|
|
155
|
+
trace: this.options.enableTrace ? trace : undefined,
|
|
156
|
+
config: config
|
|
148
157
|
};
|
|
149
158
|
}
|
|
150
159
|
}
|
|
160
|
+
|
|
151
161
|
/**
|
|
152
162
|
* 递归评估条件组
|
|
153
163
|
*
|
|
@@ -157,12 +167,16 @@ var StrategyEngine = class {
|
|
|
157
167
|
*/
|
|
158
168
|
evaluateConditionGroup(group, context) {
|
|
159
169
|
const collectedActionIds = [];
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
170
|
+
|
|
171
|
+
// 评估当前层的 operator 和 rules(同时收集失败信息)
|
|
172
|
+
const {
|
|
173
|
+
satisfied,
|
|
174
|
+
failedRules
|
|
175
|
+
} = this.evaluateGroupLogicDetailed(group, context);
|
|
164
176
|
if (satisfied) {
|
|
165
177
|
collectedActionIds.push(...group.actionIds);
|
|
178
|
+
|
|
179
|
+
// 递归评估嵌套的 ConditionGroup,收集嵌套层的 actionIds
|
|
166
180
|
for (const rule of group.rules) {
|
|
167
181
|
if (this.isConditionGroup(rule)) {
|
|
168
182
|
const nestedResult = this.evaluateConditionGroup(rule, context);
|
|
@@ -176,6 +190,7 @@ var StrategyEngine = class {
|
|
|
176
190
|
failedRules
|
|
177
191
|
};
|
|
178
192
|
}
|
|
193
|
+
|
|
179
194
|
/**
|
|
180
195
|
* 评估条件组的逻辑运算(带失败规则收集)
|
|
181
196
|
*
|
|
@@ -185,46 +200,72 @@ var StrategyEngine = class {
|
|
|
185
200
|
* - `not`:被取反规则实际通过时,记录该规则
|
|
186
201
|
*/
|
|
187
202
|
evaluateGroupLogicDetailed(group, context) {
|
|
188
|
-
const {
|
|
203
|
+
const {
|
|
204
|
+
operator,
|
|
205
|
+
rules
|
|
206
|
+
} = group;
|
|
189
207
|
switch (operator) {
|
|
190
|
-
case
|
|
191
|
-
|
|
192
|
-
const
|
|
193
|
-
|
|
208
|
+
case 'and':
|
|
209
|
+
{
|
|
210
|
+
for (const rule of rules) {
|
|
211
|
+
const ruleResult = this.evaluateRuleDetailed(rule, context);
|
|
212
|
+
if (!ruleResult.satisfied) {
|
|
213
|
+
return {
|
|
214
|
+
satisfied: false,
|
|
215
|
+
failedRules: ruleResult.failedRules
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
satisfied: true,
|
|
221
|
+
failedRules: []
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
case 'or':
|
|
225
|
+
{
|
|
226
|
+
const aggregated = [];
|
|
227
|
+
for (const rule of rules) {
|
|
228
|
+
const ruleResult = this.evaluateRuleDetailed(rule, context);
|
|
229
|
+
if (ruleResult.satisfied) {
|
|
230
|
+
return {
|
|
231
|
+
satisfied: true,
|
|
232
|
+
failedRules: []
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
aggregated.push(...ruleResult.failedRules);
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
satisfied: false,
|
|
239
|
+
failedRules: aggregated
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
case 'not':
|
|
243
|
+
{
|
|
244
|
+
if (rules.length === 0) {
|
|
194
245
|
return {
|
|
195
246
|
satisfied: false,
|
|
196
|
-
failedRules:
|
|
247
|
+
failedRules: []
|
|
197
248
|
};
|
|
198
249
|
}
|
|
199
|
-
|
|
200
|
-
return { satisfied: true, failedRules: [] };
|
|
201
|
-
}
|
|
202
|
-
case "or": {
|
|
203
|
-
const aggregated = [];
|
|
204
|
-
for (const rule of rules) {
|
|
205
|
-
const ruleResult = this.evaluateRuleDetailed(rule, context);
|
|
250
|
+
const ruleResult = this.evaluateRuleDetailed(rules[0], context);
|
|
206
251
|
if (ruleResult.satisfied) {
|
|
207
|
-
|
|
252
|
+
// 被取反规则实际通过,导致 not 失败
|
|
253
|
+
const failed = this.isConditionGroup(rules[0]) ? [] : [this.buildFailedRuleInfo(rules[0], context)];
|
|
254
|
+
return {
|
|
255
|
+
satisfied: false,
|
|
256
|
+
failedRules: failed
|
|
257
|
+
};
|
|
208
258
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
case "not": {
|
|
214
|
-
if (rules.length === 0) {
|
|
215
|
-
return { satisfied: false, failedRules: [] };
|
|
259
|
+
return {
|
|
260
|
+
satisfied: true,
|
|
261
|
+
failedRules: []
|
|
262
|
+
};
|
|
216
263
|
}
|
|
217
|
-
const ruleResult = this.evaluateRuleDetailed(rules[0], context);
|
|
218
|
-
if (ruleResult.satisfied) {
|
|
219
|
-
const failed = this.isConditionGroup(rules[0]) ? [] : [this.buildFailedRuleInfo(rules[0], context)];
|
|
220
|
-
return { satisfied: false, failedRules: failed };
|
|
221
|
-
}
|
|
222
|
-
return { satisfied: true, failedRules: [] };
|
|
223
|
-
}
|
|
224
264
|
default:
|
|
225
265
|
throw new Error(`Unknown operator: ${operator}`);
|
|
226
266
|
}
|
|
227
267
|
}
|
|
268
|
+
|
|
228
269
|
/**
|
|
229
270
|
* 评估单个规则(带失败规则收集)
|
|
230
271
|
*/
|
|
@@ -235,27 +276,35 @@ var StrategyEngine = class {
|
|
|
235
276
|
const conditionRule = rule;
|
|
236
277
|
const satisfied = this.evaluateAtomicRule(conditionRule, context);
|
|
237
278
|
if (satisfied) {
|
|
238
|
-
return {
|
|
279
|
+
return {
|
|
280
|
+
satisfied: true,
|
|
281
|
+
failedRules: []
|
|
282
|
+
};
|
|
239
283
|
}
|
|
240
284
|
return {
|
|
241
285
|
satisfied: false,
|
|
242
286
|
failedRules: [this.buildFailedRuleInfo(conditionRule, context)]
|
|
243
287
|
};
|
|
244
288
|
}
|
|
289
|
+
|
|
245
290
|
/**
|
|
246
291
|
* 评估原子规则(不收集失败信息,仅返回布尔结果)
|
|
247
292
|
*/
|
|
248
293
|
evaluateAtomicRule(conditionRule, context) {
|
|
249
|
-
|
|
294
|
+
// Code 模式:使用 eval 执行
|
|
295
|
+
if (conditionRule.type === 'code' && conditionRule.code) {
|
|
250
296
|
return this.evaluateCodeCondition(conditionRule.code, context);
|
|
251
297
|
}
|
|
298
|
+
|
|
299
|
+
// Operator 模式:标准运算符判断
|
|
252
300
|
return this.evaluateOperatorCondition(conditionRule, context);
|
|
253
301
|
}
|
|
302
|
+
|
|
254
303
|
/**
|
|
255
304
|
* 构建失败规则信息
|
|
256
305
|
*/
|
|
257
306
|
buildFailedRuleInfo(conditionRule, context) {
|
|
258
|
-
const actualValue = conditionRule.field ? this.getFieldValue(conditionRule.field, context) :
|
|
307
|
+
const actualValue = conditionRule.field ? this.getFieldValue(conditionRule.field, context) : undefined;
|
|
259
308
|
return {
|
|
260
309
|
field: conditionRule.field,
|
|
261
310
|
operator: conditionRule.operator,
|
|
@@ -263,144 +312,169 @@ var StrategyEngine = class {
|
|
|
263
312
|
actualValue
|
|
264
313
|
};
|
|
265
314
|
}
|
|
315
|
+
|
|
266
316
|
/**
|
|
267
317
|
* 评估代码模式条件
|
|
268
318
|
*/
|
|
269
319
|
evaluateCodeCondition(code, context) {
|
|
270
320
|
try {
|
|
271
|
-
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
321
|
+
// 将 context 解构到作用域中,方便代码直接使用
|
|
322
|
+
const {
|
|
323
|
+
entities,
|
|
324
|
+
attributes,
|
|
325
|
+
metadata
|
|
326
|
+
} = context;
|
|
327
|
+
|
|
328
|
+
// 使用 Function 构造器代替 eval,更安全
|
|
329
|
+
const evalFunc = new Function('entities', 'attributes', 'metadata', `return (${code})`);
|
|
278
330
|
const result = evalFunc(entities, attributes, metadata);
|
|
279
331
|
return Boolean(result);
|
|
280
332
|
} catch (error) {
|
|
281
333
|
if (this.options.debug) {
|
|
282
|
-
console.error(
|
|
334
|
+
console.error('Code evaluation error:', error);
|
|
283
335
|
}
|
|
284
336
|
return false;
|
|
285
337
|
}
|
|
286
338
|
}
|
|
339
|
+
|
|
287
340
|
/**
|
|
288
341
|
* 评估运算符模式条件
|
|
289
342
|
*/
|
|
290
343
|
evaluateOperatorCondition(rule, context) {
|
|
291
|
-
const {
|
|
344
|
+
const {
|
|
345
|
+
field,
|
|
346
|
+
operator,
|
|
347
|
+
value
|
|
348
|
+
} = rule;
|
|
292
349
|
if (!field || !operator) {
|
|
293
350
|
return false;
|
|
294
351
|
}
|
|
352
|
+
|
|
353
|
+
// 从 context.attributes 中获取字段值
|
|
295
354
|
const fieldValue = this.getFieldValue(field, context);
|
|
355
|
+
|
|
356
|
+
// 使用运算符处理器
|
|
296
357
|
const handler = this.operatorHandlers.get(operator);
|
|
297
358
|
if (handler) {
|
|
298
359
|
return handler(fieldValue, value, rule);
|
|
299
360
|
}
|
|
361
|
+
|
|
362
|
+
// 回退到内置运算符
|
|
300
363
|
return this.evaluateBuiltInOperator(fieldValue, operator, value);
|
|
301
364
|
}
|
|
365
|
+
|
|
302
366
|
/**
|
|
303
367
|
* 获取字段值
|
|
304
368
|
*/
|
|
305
369
|
getFieldValue(field, context) {
|
|
306
|
-
|
|
370
|
+
// 支持点号路径,如 "order.total"
|
|
371
|
+
const path = field.split('.');
|
|
307
372
|
let value = context.attributes;
|
|
308
373
|
for (const key of path) {
|
|
309
|
-
if (value && typeof value ===
|
|
374
|
+
if (value && typeof value === 'object' && key in value) {
|
|
310
375
|
value = value[key];
|
|
311
376
|
} else {
|
|
312
|
-
return
|
|
377
|
+
return undefined;
|
|
313
378
|
}
|
|
314
379
|
}
|
|
315
380
|
return value;
|
|
316
381
|
}
|
|
382
|
+
|
|
317
383
|
/**
|
|
318
384
|
* 评估内置运算符
|
|
319
385
|
*/
|
|
320
386
|
evaluateBuiltInOperator(fieldValue, operator, compareValue) {
|
|
321
387
|
switch (operator) {
|
|
322
|
-
|
|
323
|
-
case
|
|
388
|
+
// 比较运算符
|
|
389
|
+
case '=':
|
|
390
|
+
case '==':
|
|
324
391
|
return fieldValue == compareValue;
|
|
325
|
-
case
|
|
392
|
+
case '!=':
|
|
326
393
|
return fieldValue != compareValue;
|
|
327
|
-
case
|
|
394
|
+
case '>':
|
|
328
395
|
return fieldValue > compareValue;
|
|
329
|
-
case
|
|
396
|
+
case '>=':
|
|
330
397
|
return fieldValue >= compareValue;
|
|
331
|
-
case
|
|
398
|
+
case '<':
|
|
332
399
|
return fieldValue < compareValue;
|
|
333
|
-
case
|
|
400
|
+
case '<=':
|
|
334
401
|
return fieldValue <= compareValue;
|
|
335
|
-
|
|
402
|
+
|
|
403
|
+
// 集合运算符
|
|
404
|
+
case 'in':
|
|
336
405
|
return Array.isArray(compareValue) && compareValue.includes(fieldValue);
|
|
337
|
-
case
|
|
406
|
+
case 'not_in':
|
|
338
407
|
return Array.isArray(compareValue) && !compareValue.includes(fieldValue);
|
|
339
|
-
case
|
|
408
|
+
case 'contains':
|
|
340
409
|
if (Array.isArray(fieldValue)) {
|
|
341
410
|
return fieldValue.includes(compareValue);
|
|
342
411
|
}
|
|
343
|
-
if (typeof fieldValue ===
|
|
412
|
+
if (typeof fieldValue === 'string') {
|
|
344
413
|
return fieldValue.includes(compareValue);
|
|
345
414
|
}
|
|
346
415
|
return false;
|
|
347
|
-
case
|
|
416
|
+
case 'not_contains':
|
|
348
417
|
if (Array.isArray(fieldValue)) {
|
|
349
418
|
return !fieldValue.includes(compareValue);
|
|
350
419
|
}
|
|
351
|
-
if (typeof fieldValue ===
|
|
420
|
+
if (typeof fieldValue === 'string') {
|
|
352
421
|
return !fieldValue.includes(compareValue);
|
|
353
422
|
}
|
|
354
423
|
return true;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
case
|
|
358
|
-
return typeof fieldValue ===
|
|
359
|
-
case
|
|
360
|
-
return typeof fieldValue ===
|
|
361
|
-
case
|
|
362
|
-
|
|
363
|
-
|
|
424
|
+
|
|
425
|
+
// 字符串运算符
|
|
426
|
+
case 'starts_with':
|
|
427
|
+
return typeof fieldValue === 'string' && fieldValue.startsWith(compareValue);
|
|
428
|
+
case 'ends_with':
|
|
429
|
+
return typeof fieldValue === 'string' && fieldValue.endsWith(compareValue);
|
|
430
|
+
case 'regex':
|
|
431
|
+
return typeof fieldValue === 'string' && new RegExp(compareValue).test(fieldValue);
|
|
432
|
+
|
|
433
|
+
// 范围运算符
|
|
434
|
+
case 'between':
|
|
435
|
+
if (!Array.isArray(compareValue) || compareValue.length !== 2) return false;
|
|
364
436
|
return fieldValue >= compareValue[0] && fieldValue <= compareValue[1];
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
case
|
|
368
|
-
return fieldValue
|
|
369
|
-
case
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
if (
|
|
373
|
-
|
|
374
|
-
if (typeof fieldValue ===
|
|
375
|
-
return Object.keys(fieldValue).length === 0;
|
|
437
|
+
|
|
438
|
+
// 逻辑运算符
|
|
439
|
+
case 'is_null':
|
|
440
|
+
return fieldValue === null || fieldValue === undefined;
|
|
441
|
+
case 'is_not_null':
|
|
442
|
+
return fieldValue !== null && fieldValue !== undefined;
|
|
443
|
+
case 'is_empty':
|
|
444
|
+
if (Array.isArray(fieldValue)) return fieldValue.length === 0;
|
|
445
|
+
if (typeof fieldValue === 'string') return fieldValue.length === 0;
|
|
446
|
+
if (typeof fieldValue === 'object') return Object.keys(fieldValue).length === 0;
|
|
376
447
|
return !fieldValue;
|
|
377
|
-
case
|
|
378
|
-
if (Array.isArray(fieldValue))
|
|
379
|
-
|
|
380
|
-
if (typeof fieldValue ===
|
|
381
|
-
return fieldValue.length > 0;
|
|
382
|
-
if (typeof fieldValue === "object")
|
|
383
|
-
return Object.keys(fieldValue).length > 0;
|
|
448
|
+
case 'is_not_empty':
|
|
449
|
+
if (Array.isArray(fieldValue)) return fieldValue.length > 0;
|
|
450
|
+
if (typeof fieldValue === 'string') return fieldValue.length > 0;
|
|
451
|
+
if (typeof fieldValue === 'object') return Object.keys(fieldValue).length > 0;
|
|
384
452
|
return Boolean(fieldValue);
|
|
385
|
-
|
|
453
|
+
|
|
454
|
+
// 商品匹配运算符
|
|
455
|
+
case 'product_match':
|
|
386
456
|
return this.evaluateProductMatch(fieldValue, compareValue);
|
|
387
|
-
|
|
457
|
+
|
|
458
|
+
// 对象包含运算符(兼容旧配置)
|
|
459
|
+
case 'object_in':
|
|
388
460
|
return this.evaluateProductMatch(fieldValue, compareValue);
|
|
389
461
|
default:
|
|
390
462
|
throw new Error(`Unsupported operator: ${operator}`);
|
|
391
463
|
}
|
|
392
464
|
}
|
|
465
|
+
|
|
393
466
|
/**
|
|
394
467
|
* 根据 actionIds 获取 ActionEffect 对象
|
|
395
468
|
*/
|
|
396
469
|
getActionsByIds(actionIds, actions) {
|
|
397
470
|
const matchedActions = [];
|
|
398
|
-
const actionMap = new Map(actions.map(
|
|
471
|
+
const actionMap = new Map(actions.map(action => [action.id, action]));
|
|
399
472
|
for (const id of actionIds) {
|
|
400
473
|
const action = actionMap.get(id);
|
|
401
474
|
if (action) {
|
|
402
475
|
matchedActions.push(action);
|
|
403
476
|
} else {
|
|
477
|
+
// 找不到的 ID 记录警告
|
|
404
478
|
if (this.options.debug) {
|
|
405
479
|
console.warn(`Action with id "${id}" not found in actions array`);
|
|
406
480
|
}
|
|
@@ -408,6 +482,7 @@ var StrategyEngine = class {
|
|
|
408
482
|
}
|
|
409
483
|
return matchedActions;
|
|
410
484
|
}
|
|
485
|
+
|
|
411
486
|
/**
|
|
412
487
|
* 按 priority 排序(降序)
|
|
413
488
|
*/
|
|
@@ -415,37 +490,43 @@ var StrategyEngine = class {
|
|
|
415
490
|
return [...actions].sort((a, b) => {
|
|
416
491
|
const priorityA = a.priority ?? 0;
|
|
417
492
|
const priorityB = b.priority ?? 0;
|
|
418
|
-
return priorityB - priorityA;
|
|
493
|
+
return priorityB - priorityA; // 降序
|
|
419
494
|
});
|
|
420
495
|
}
|
|
496
|
+
|
|
421
497
|
/**
|
|
422
498
|
* 判断是否为条件组
|
|
423
499
|
*/
|
|
424
500
|
isConditionGroup(rule) {
|
|
425
|
-
return
|
|
501
|
+
return 'operator' in rule && 'rules' in rule && Array.isArray(rule.rules);
|
|
426
502
|
}
|
|
503
|
+
|
|
427
504
|
/**
|
|
428
505
|
* 验证配置
|
|
429
506
|
*/
|
|
430
507
|
validateConfig(config) {
|
|
431
508
|
if (!config) {
|
|
432
|
-
throw new Error(
|
|
509
|
+
throw new Error('Strategy config is required');
|
|
433
510
|
}
|
|
434
511
|
if (!config.metadata || !config.metadata.id) {
|
|
435
|
-
throw new Error(
|
|
512
|
+
throw new Error('Strategy metadata.id is required');
|
|
436
513
|
}
|
|
437
514
|
if (!config.conditions) {
|
|
438
|
-
throw new Error(
|
|
515
|
+
throw new Error('Strategy conditions is required');
|
|
439
516
|
}
|
|
440
517
|
if (!Array.isArray(config.actions)) {
|
|
441
|
-
throw new Error(
|
|
518
|
+
throw new Error('Strategy actions must be an array');
|
|
442
519
|
}
|
|
443
520
|
}
|
|
521
|
+
|
|
444
522
|
/**
|
|
445
523
|
* 初始化内置运算符处理器
|
|
446
524
|
*/
|
|
447
525
|
initializeBuiltInOperators() {
|
|
526
|
+
// 内置运算符已经在 evaluateBuiltInOperator 中实现
|
|
527
|
+
// 这里可以添加自定义的运算符处理器
|
|
448
528
|
}
|
|
529
|
+
|
|
449
530
|
/**
|
|
450
531
|
* 评估商品匹配运算符
|
|
451
532
|
*
|
|
@@ -459,35 +540,49 @@ var StrategyEngine = class {
|
|
|
459
540
|
* @returns 是否匹配
|
|
460
541
|
*/
|
|
461
542
|
evaluateProductMatch(fieldValue, configValue) {
|
|
543
|
+
// 确保 configValue 是数组
|
|
462
544
|
if (!Array.isArray(configValue)) {
|
|
463
545
|
return false;
|
|
464
546
|
}
|
|
465
|
-
|
|
547
|
+
|
|
548
|
+
// 确保 fieldValue 是有效的商品对象
|
|
549
|
+
if (!fieldValue || typeof fieldValue !== 'object' || typeof fieldValue.product_id !== 'number') {
|
|
466
550
|
return false;
|
|
467
551
|
}
|
|
468
552
|
const actualProductId = fieldValue.product_id;
|
|
469
553
|
const actualVariantId = fieldValue.product_variant_id ?? 0;
|
|
470
|
-
|
|
471
|
-
|
|
554
|
+
|
|
555
|
+
// 遍历配置的商品列表,检查是否有匹配
|
|
556
|
+
return configValue.some(item => {
|
|
557
|
+
// 验证配置项格式
|
|
558
|
+
if (!item || typeof item.product_id !== 'number') {
|
|
472
559
|
return false;
|
|
473
560
|
}
|
|
474
561
|
const configProductId = item.product_id;
|
|
475
562
|
const configVariantId = item.product_variant_id ?? 0;
|
|
563
|
+
|
|
564
|
+
// 首先检查 product_id 是否匹配
|
|
476
565
|
if (configProductId !== actualProductId) {
|
|
477
566
|
return false;
|
|
478
567
|
}
|
|
568
|
+
|
|
569
|
+
// 如果配置的 product_variant_id = 0,只需要 product_id 匹配
|
|
479
570
|
if (configVariantId === 0) {
|
|
480
571
|
return true;
|
|
481
572
|
}
|
|
573
|
+
|
|
574
|
+
// 否则需要 product_variant_id 精确匹配
|
|
482
575
|
return configVariantId === actualVariantId;
|
|
483
576
|
});
|
|
484
577
|
}
|
|
578
|
+
|
|
485
579
|
/**
|
|
486
580
|
* 注册自定义运算符
|
|
487
581
|
*/
|
|
488
582
|
registerOperator(operator, handler) {
|
|
489
583
|
this.operatorHandlers.set(operator, handler);
|
|
490
584
|
}
|
|
585
|
+
|
|
491
586
|
/**
|
|
492
587
|
* 获取调试信息
|
|
493
588
|
*/
|
|
@@ -498,17 +593,24 @@ var StrategyEngine = class {
|
|
|
498
593
|
registeredOperators: Array.from(this.operatorHandlers.keys())
|
|
499
594
|
};
|
|
500
595
|
}
|
|
501
|
-
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// ============================================
|
|
599
|
+
// 导出工具函数
|
|
600
|
+
// ============================================
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* 创建策略引擎实例
|
|
604
|
+
*/
|
|
605
|
+
exports.StrategyEngine = StrategyEngine;
|
|
502
606
|
function createStrategyEngine(options) {
|
|
503
607
|
return new StrategyEngine(options);
|
|
504
608
|
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* 快速评估(使用默认引擎配置)
|
|
612
|
+
*/
|
|
505
613
|
function evaluate(config, context) {
|
|
506
614
|
const engine = new StrategyEngine();
|
|
507
615
|
return engine.evaluate(config, context);
|
|
508
|
-
}
|
|
509
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
510
|
-
0 && (module.exports = {
|
|
511
|
-
StrategyEngine,
|
|
512
|
-
createStrategyEngine,
|
|
513
|
-
evaluate
|
|
514
|
-
});
|
|
616
|
+
}
|