UNPKG

focus-product-extractor2

Version:

Extract product information from chat/order data

226 lines (211 loc) 7.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.OutputStandard = void 0; var _messageTypes = require("../constants/messageTypes.js"); /** * 商品信息标准化输出类 * 负责从不同平台获取商品信息并格式化为统一结构 */ class OutputStandard { /** * 构造函数,初始化平台类型和API端点配置 */ constructor() { this.platformTypes = { taobao: ['tb'], domestic: ['jd', 'ks', 'dy', 'pdd', 'xhs'], overseas: ['lazada', 'shopee', 'tiktok'] // 新增海外平台标识 }; // 提取API端点配置 this.apiEndpoints = { taobao: 'https://gateway.1yangai.com/open/goods-center/gc/v2/goods_info', domestic: 'https://gateway.xiaoduoai.com/open/goods-center/gc/v2/goods_info', // 暂无海外平台API端点 overseas: '' }; } /** * 获取商品详细信息 * @param {Object} item - 商品对象 * @param {string} item.goodsId - 商品ID * @param {string} [item.platform] - 商品平台 * @param {string} [item.shopId] - 店铺ID * @param {Object} [item.metadata] - 元数据 * @param {Object} authConfig - 认证配置 * @param {string} authConfig.taobaoAuth - 淘宝认证token * @param {string} authConfig.domesticAuth - 国内非淘平台认证token * @returns {Promise<Object|null>} 商品信息或错误对象 */ async _fetchGoodsInfo(item, authConfig) { var _item$metadata, _item$metadata2; if (!item.goodsId || isNaN(item.goodsId)) { return this._createErrorResponse('Invalid goods ID'); } const platform = item.platform || ((_item$metadata = item.metadata) === null || _item$metadata === void 0 ? void 0 : _item$metadata.platform); const shopId = item.shopId || ((_item$metadata2 = item.metadata) === null || _item$metadata2 === void 0 ? void 0 : _item$metadata2.shopId); try { const { endpoint, auth } = this._getApiConfig(platform, authConfig); if (!endpoint) { return this._createErrorResponse('Unsupported platform'); } const response = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': auth }, body: JSON.stringify({ plat_goods_id: item.goodsId, platform, shop_id: shopId }) }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); return this._createErrorResponse(`API request failed with status ${response.status}`, errorData); } return await response.json(); } catch (error) { console.error('Fetch goods info error:', error); return this._createErrorResponse(error.message, { stack: error.stack }); } } /** * 获取API配置 * @private * @param {string} platform - 平台标识 * @param {Object} authConfig - 认证配置 * @returns {Object} 包含endpoint和auth的对象 */ _getApiConfig(platform, authConfig) { if (this.platformTypes.taobao.includes(platform)) { return { endpoint: this.apiEndpoints.taobao, auth: authConfig.taobaoAuth }; } if (this.platformTypes.domestic.includes(platform)) { return { endpoint: this.apiEndpoints.domestic, auth: authConfig.domesticAuth }; } if (this.platformTypes.overseas.includes(platform)) { return { endpoint: this.apiEndpoints.overseas, // TODO 需要先定义海外平台API端点 auth: authConfig.overseasAuth }; } return {}; } /** * 创建统一格式的错误响应 * @private * @param {string} message - 错误消息 * @param {Object} [details={}] - 错误详情 * @returns {Object} 错误响应对象 */ _createErrorResponse(message, details = {}) { return { error: message, ...details }; } _calcOrder(item) { if (item.metadata.messageSubType === _messageTypes.MESSAGE_SUB_TYPES.BUYER_ENTER) return 100; if (item.metadata.sender === _messageTypes.SENDER_TYPES.BUYER) return 90; if (item.metadata.sender === _messageTypes.SENDER_TYPES.SERVICE) return 80; if (item.metadata.sender === _messageTypes.SENDER_TYPES.SYSTEM) return 70; return item.confidence || 0; } /** * 格式化商品信息列表 * @param {Array} items - 商品信息数组 * @param {Object} authConfig - 认证配置 * @returns {Promise<Object>} 标准化后的商品信息 * @property {Array} items - 商品列表 * @property {number} timestamp - 时间戳 */ async format(items = [], authConfig = {}) { if (!Array.isArray(items)) { return { items: [] }; } // 去重 let sortedItems = items.filter((item, index, self) => index === self.findIndex(t => t.goodsId === item.goodsId)); // 按type分组:order类型和其他类型 const orderItems = sortedItems.filter(item => item.type === 'order'); const otherItems = sortedItems.filter(item => item.type !== 'order'); // 分别对order类型和其他类型进行优先级排序 const sortedOrderItems = orderItems.sort((a, b) => { const a_score = this._calcOrder(a); const b_score = this._calcOrder(b); if (a_score === b_score) { return b.metadata.timestamp - a.metadata.timestamp; } return b_score - a_score; }); const sortedOtherItems = otherItems.sort((a, b) => { const a_score = this._calcOrder(a); const b_score = this._calcOrder(b); if (a_score === b_score) { return b.metadata.timestamp - a.metadata.timestamp; } return b_score - a_score; }); // console.log(sortedOrderItems, sortedOtherItems); // 取两者优先级最高的商品组成列表 sortedItems = []; if (sortedOrderItems.length > 0) { sortedItems.push(sortedOrderItems[0]); } if (sortedOtherItems.length > 0) { sortedItems.push(sortedOtherItems[0]); } // 如果设置了自定义规则,则获取全部商品信息,否则只获取前2个商品信息 // console.log(authConfig); if (!authConfig.customRules || authConfig.customRules.length <= 0) { sortedItems = sortedItems.slice(0, 2); } // TODO 按置信度降序排序 // const sortedItems = orderedItems.sort((a, b) => (b.confidence || 0) - (a.confidence || 0)); // 为每个商品获取详细信息 const enrichedItems = await Promise.all(sortedItems.map(async item => { // 构建返回对象 const result = { ...item }; // 只对类型为 sku 或 spu 且有 goodsId 的项目进行商品信息填充 if (item.goodsId && (item.type === 'sku' || item.type === 'spu')) { const goodsInfo = await this._fetchGoodsInfo(item, authConfig); if (goodsInfo && !goodsInfo.error) { result.goodsInfo = goodsInfo.data; } else { result.goodsInfoError = goodsInfo !== null && goodsInfo !== void 0 && goodsInfo.error ? { message: `Failed to fetch goods info for ID: ${item.goodsId}`, details: goodsInfo } : { message: `Unknown error occurred for ID: ${item.goodsId}` }; } } // 其他类型(order)或没有 goodsId 的项目不进行商品信息填充,直接返回 return result; })); return { items: enrichedItems, timestamp: Date.now() }; } } exports.OutputStandard = OutputStandard; var _default = exports.default = new OutputStandard();