@pisell/pisellos
Version:
一个可扩展的前端模块化SDK框架,支持插件系统
218 lines (216 loc) • 6.93 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/model/strategy/adapter/promotion/adapter.ts
var adapter_exports = {};
__export(adapter_exports, {
PromotionAdapter: () => PromotionAdapter,
default: () => adapter_default
});
module.exports = __toCommonJS(adapter_exports);
var import_type = require("./type");
var PromotionAdapter = class {
constructor() {
this.name = "PromotionAdapter";
this.version = "1.0.0";
}
/**
* 准备运行时上下文
*
* 将业务数据转换为策略引擎可识别的 RuntimeContext
*/
prepareContext(businessData) {
const { products, currentProduct, channel, custom } = businessData;
const now = /* @__PURE__ */ new Date();
const currentDateTime = this.formatDateTime(now);
const evaluatingProduct = currentProduct || (products.length > 0 ? products[0] : null);
return {
entities: {
products,
currentProduct: evaluatingProduct
},
attributes: {
// 当前时间(格式化字符串,用于时间条件判断)
currentDateTime,
// 当前评估的商品信息(用于 product_match 运算符)
productIdAndVariantId: evaluatingProduct ? {
product_id: evaluatingProduct.product_id,
product_variant_id: evaluatingProduct.product_variant_id
} : null,
// 渠道
channel: channel || "",
// 商品总数量
totalQuantity: products.reduce((sum, p) => sum + p.quantity, 0),
// 商品总金额
totalAmount: products.reduce((sum, p) => sum + p.price * p.quantity, 0),
// 自定义属性
...custom
},
metadata: {
timestamp: Date.now()
}
};
}
/**
* 转换执行结果
*
* 将策略引擎的通用结果转换为业务层需要的格式
* 主要是整理 matchedActions,让业务层更容易使用
*/
transformResult(result, businessData) {
const applicableProducts = businessData ? this.getApplicableProducts(result, businessData) : [];
if (!result.applicable) {
return {
isApplicable: false,
applicableProducts: [],
reason: result.message,
reasonCode: result.code,
strategyResult: result
};
}
const matchedAction = result.matchedActions[0];
if (!matchedAction) {
return {
isApplicable: false,
applicableProducts: [],
reason: "No matched action",
reasonCode: "NO_ACTION",
strategyResult: result
};
}
const actionDetail = this.parseActionDetail(matchedAction);
return {
isApplicable: true,
actionType: matchedAction.type,
actionDetail,
applicableProducts,
strategyResult: result
};
}
/**
* 格式化配置
*/
formatConfig(result, businessData) {
return { result, businessData };
}
// ============================================
// 私有辅助方法
// ============================================
/**
* 格式化日期时间
*/
formatDateTime(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
const seconds = String(date.getSeconds()).padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
/**
* 解析 Action 详情
*
* 将 matchedAction 转换为更易用的结构
*/
parseActionDetail(action) {
switch (action.type) {
case import_type.PROMOTION_ACTION_TYPES.X_ITEMS_FOR_Y_PRICE:
return this.parseXItemsForYPriceAction(action);
case import_type.PROMOTION_ACTION_TYPES.BUY_X_GET_Y_FREE:
return this.parseBuyXGetYFreeAction(action);
default:
return void 0;
}
}
/**
* 解析 X件Y元 Action
*/
parseXItemsForYPriceAction(action) {
const value = action.value || {};
const config = action.config || {};
return {
type: import_type.PROMOTION_ACTION_TYPES.X_ITEMS_FOR_Y_PRICE,
x: value.x || 2,
price: value.price || 0,
allowCrossProduct: config.allowCrossProduct ?? true,
cumulative: config.cumulative ?? true
};
}
/**
* 解析 买X送Y Action
*/
parseBuyXGetYFreeAction(action) {
const value = action.value || {};
const config = action.config || {};
return {
type: import_type.PROMOTION_ACTION_TYPES.BUY_X_GET_Y_FREE,
buyQuantity: value.buyQuantity || 1,
freeQuantity: value.freeQuantity || 1,
giftSelectionMode: config.giftSelectionMode || "user_select",
cumulative: config.cumulative ?? true,
giftProducts: config.giftProducts || []
};
}
/**
* 获取适用的商品列表
*
* 从购物车商品中筛选出符合策略条件的商品
*/
getApplicableProducts(result, businessData) {
const { products } = businessData;
const productMatchRule = this.findProductMatchRule(result.config);
if (!productMatchRule) {
return products;
}
const configProducts = productMatchRule.value;
return products.filter(
(product) => this.isProductMatch(product, configProducts)
);
}
/**
* 查找商品匹配规则
*/
findProductMatchRule(config) {
var _a;
if (!((_a = config == null ? void 0 : config.conditions) == null ? void 0 : _a.rules)) {
return null;
}
return config.conditions.rules.find(
(rule) => rule.field === "productIdAndVariantId" && (rule.operator === "product_match" || rule.operator === "object_in")
);
}
/**
* 检查商品是否匹配
*/
isProductMatch(product, configProducts) {
return configProducts.some((config) => {
if (config.product_id !== product.product_id) {
return false;
}
if (config.product_variant_id === 0) {
return true;
}
return config.product_variant_id === product.product_variant_id;
});
}
};
var adapter_default = PromotionAdapter;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
PromotionAdapter
});