# @feedmepos/mf-upselling 中文文档

规范地址：https://npmcn.com/package/%40feedmepos/mf-upselling/

版本：0\.3\.2
npm 元数据更新时间：2026-10-28T20:03:11.032Z
中文译文更新时间：2026-11-14T13:27:59.471Z
软件包许可：UNLICENSED

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40feedmepos/mf-upselling
原文对照：https://npmcn.com/package/%40feedmepos/mf-upselling/?lang=original

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：94 kB，16 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：vue ^3\.4\.21，vue-router ^4\.3\.0，@feedmepos/ui-library ^1\.8\.8
- 首次发布：2026-10-13T16:25:20.633Z
- 最新版本发布：2026-10-28T20:03:05.153Z
- 近 30 天下载量：2126（2026-10-15 至 2026-11-13，npm 官方下载统计）
- 已发布版本数：12（近 12 个月 12 个）

## 中文简介

Connect 的商家设置微前端 。 所有功能 UI 都住在这里; API 运行于报表- query- service 下 `packages/node`连接导入用户界面,并供应其已认证的上下文。 没有新的服务或菜单编辑器 .

## 安装

```sh
npm install @feedmepos/mf-upselling
```

也可以使用：`pnpm add @feedmepos/mf-upselling`、`yarn add @feedmepos/mf-upselling`、`bun add @feedmepos/mf-upselling`

## README

# 向上销售设置

Connect 的商家设置微前端 。 所有功能 UI 都住在这里; API 运行于报表- query- service 下 `packages/node`连接导入用户界面,并供应其已认证的上下文。 没有新的服务或菜单编辑器 .

## 这个发布会做什么

-   为选定的企业或餐厅装入现有产品;显示名称、相片、类别和价格,而不将其复制入MongoDB.
-   一个产品 **调整重量** 切换控制其保存的重量是否适用。 关闭是正常排名,而不是排除.
-   第一次启动时间为50%。 切换关闭保留值 。 活性0%排除;活性100%是最强的偏好,从不保证安置或购买概率.
-   以1%增量自由拖放; 轻轻地释放到最接近的5% 。 标签建议不为0 %,弱为1-39 %,平时为40-59 %,强为60-79%,强为80-100%。 橙色/金色流动效应起于80%,并尊重减动偏好. 这些是重量标签,不是模型分数.
-   仅存储已配置的产品 。 搜索永远不会改变保存的内容 。 当前目录中缺失的产品仍然无法看到,保留了已保存的设置.
-   保存失败保留编辑 。 切换餐厅为这个挂载会话保留了未保存的草稿. 请求和逾期答复仍受原先范围的约束。 没有草稿存储在本地Storage中 .
-   客户预览会选择一个出入口以及餐厅或推车推荐. 测试车支持多种产品和数量,使用出口目录,并在出口变化时清除。 预览控件不制作菜单、顺序或设置.

预览比较 **之前( 当前)** 与 **之后** 使用相同的出口、推荐类型和推车。 可选 `loadPreview(request): Promise<UpsellPreviewResult>` 接受 `{ businessId, restaurantId, recommendationType: 'restaurant' | 'cart', cart: { productId, quantity }[], items: UpsellItem[], limit: 10 }` 返回时 `{ products: UpsellProduct[], source: 'historical' | 'weight_only' | 'no_data' }`。在使用所选出口的有效保存设置之前; 重叠后只匹配未保存的更改, 保留无关的输出重. 保留供应商订单。 只有重量的建议被贴上这样的标签,而不是被贴上最畅销的产品. 没有真正的提供者,面板表示预览没有连接;没有发明客户端排名. `previewTouchpoints` 可自定义标题 `restaurant`编号 :`cart`;一个空阵列隐藏预览. 预览上下文没有持续 。 只草稿重重编辑会话在结果前保存的再使用, 并装入输出目录; 仅在再次请求之后 。 改变出口、建议类型、推车、保存的设置或重试可以刷新基线。 已经打开的预览不会对其他用户保存的更改进行民调 。 选择一车产品立即增加;紧凑行会暴露出数量和去除. 在刷新同一建议背景的同时,现有成果仍然明显可见并按键产品与新位置活跃;减速偏好使这些过渡无法进行。 切换出入口或建议类型可以从上下文中清除出来.

`createUpsellRecommendationPreview({ baseUrl, getToken, loadProducts })` 使用 Eric 的专用 POST `/recommendation/:businessId/current` 时间和地点: `/recommendation/:businessId/preview` 为后. 请求使用 `{ type: 'whats_hot' | 'cart', restaurant_id, cart_item?: string[] }`; 预览额外发送完整 `items` 数组(空即无增益). 两者都发出现有的"门户无记名"(Portal)标志和相同的明确出道口/出道口. 当前省略项目草稿并接受设置 `source: restaurant | business | none`。两者都需要匹配 `restaurant_id`,命令独有 `product_id` 数值和限定对齐 `score` 数值。 API 不披露历史相关元数据:适配器返回 `source: unknown` 并隐藏相关性/重量徽章,而不是发明地位。 建议直接报告终点故障;没有单独提出保健要求。 失败是浮出水面的,从未转化为无历史建议. 前端保留了服务器订单和客户资格/播放限制. 这种就地融合没有确定部署的可用性或经认证的端到端行为.

商机控制使用 FeedMe `FmSelect` 和一个紧凑的双选项建议选择器。 仅读取的客户牌遵循订单服务 [客户 Upselling 项目列表](https://github.com/feedmepos/ordering-service/blob/main/frontend/customer-v3/src/components/upselling/UpsellingItemList.vue), (中文(简体) ), [项目列表](https://github.com/feedmepos/ordering-service/blob/main/frontend/customer-v3/src/components/menu/ItemListTile.vue) 财务报告和审定财务报表 [离职安置](https://github.com/feedmepos/ordering-service/blob/main/frontend/customer-v3/src/components/cart/CartInfo.vue):水平相/名/价牌没有人工添加按钮. 它们说明了默认的布局;商家订购的主题,产品代码,描述,活的可用性和订购动作不由本套件复制或获取.

每个客户取景口被封顶为375px并收缩到可用的空间. 最多可有10个回回产品被装入有比例正方形相片和被包名的双柱网格中,没有横向滚动. 设置布局响应其主机容器宽度,包括由Connect的侧边栏取取的空间.

## 核心/连接整合

### 交付

我的下一个候选人是 `0.3.0-dev.1`。在公关合并后 `mf-upselling/0.3.0-dev.1` 工作流程成功, 安装 `@feedmepos/mf-upselling@0.3.0-dev.1` 从公共npm注册。 该候选人向 `dev`; 稳定 `latest` 保持不变。 软件包 PR 或 分支推力 不发布或部署任何东西.

仅在匹配发布工作流程成功后安装稳定版本 :

```sh
pnpm add --save-exact @feedmepos/mf-upselling@0.2.2
```

这个软件包是通过npmjs而不是GitHub软件包送出. 如果你的当地 `@feedmepos` 范围点位于 GitHub 软件包,使用主机的 npmjs 软件包分辨率设置,而不是改变其其他私有依赖.

对于 Portal 导入图的发送, 登记该精确版本的 `dist/app.js` 装入 `dist/style.css`; 软件包本身不注册。 使用主机共享的Vue,Vue路由器和FeedMe UI. 不要使用未标注 `latest` URL (中文(简体) ).

My API 基础( 启用上市网关路径后): dev `https://query-engine.feedmeapidev.com`生产 `https://query-engine.feedmeapi.com`选择附件 `/report-query` 用于销售。 仅限 `businessId`,客户端使用 `/{businessId}/upsell-settings` 用于获取和PUT。 供应 `restaurantId` 使用现有的 `/{businessId}/{restaurantId}/upsell-settings`。其他国家必须提供匹配的网关 URL。 后端单独部署,不包含在 npm 包中; 生产设置仍然不可用, 而 `UPSELL_SETTINGS_ENABLED=false`。 。 。 .

这个 `Upselling package` 工作流程检查包 PR. 合并后, `mf-upselling/<version>` 必须匹配软件包版本:稳定版本发布到 `latest`,以及 `-dev.N` 发布版本到 `dev`脱氧核糖核酸释放需要现有稳定 `latest` 并证实它保持不变。 释放承诺必须包含在 `main`。出版不部署后端;连接提供API URL,并对其环境进行认证.

连接 `packages/connect/src/api/index.ts` 通常以营销服务为目标并处理其 `code/data` 信封上写着 报告服务时不重复使用该客户端: 设置端点返回纯设置对象 。 向一个报告服务客户端提供正确的国家/环境基础URL和当前门户防火基地标志. 主机上下文来自 `useCoreStore()`;此软件包故意不创建另一个登录会话.

主机必须安装 `FeedMeUI` 装入 `@feedmepos/ui-library/styles.css`。装入此软件包的样式表一次 :

```ts
import { createUpsellSettingsApi, createUpsellingRoutes } from '@feedmepos/mf-upselling'
import '@feedmepos/mf-upselling/style.css'

// An authenticated Axios-compatible client pointed at report-query-service,
// not Portal's default portal-v2 API. Read the current token per request;
// keep the base URL aligned with the selected country and environment.
const api = createUpsellSettingsApi(reportServiceClient)

const upsellRoutes = createUpsellingRoutes(() => ({
  businessId: selectedBusinessId.value,
  // Omit restaurantId for business defaults; pass it only when editing an override.
  restaurantName: selectedRestaurantName.value,
  api,
  loadProducts: loadExistingRestaurantProducts,
}))
// Include upsellRoutes in Connect's child routes. The relative path is 'upselling'.
```

`reportServiceClient`,选择的ID和 `loadExistingRestaurantProducts` 以上为主机拥有的依赖性,而非新软件包全局. 使客户端和产品加载器参考书保持稳定. 当国家、环境或登录用户更改时, 重新创建客户端( 或重挂载组件); 不要在用户之间重新使用挂载的会话草稿 .

`loadProducts({ businessId, restaurantId })` 必须解决 **完整** 该范围的产品清单,必要时可查询现有来源。 无 `restaurantId`,返回商业目录;不需要餐馆存在或替换任意的目录。 带着它,把餐厅的产品还给我. 返回一个平面阵列,而不是 Axios 响应或 `{ data, items, total }` 信封上写着 解开并映射主机适配器中已有的目录响应; 原始连接目录兼容性不假设 。 每个 `productId` 在返回的数组中必须是独一无二的。 将每行映射为:

```ts
interface UpsellProduct {
  productId: string // exact identity used in recommendation product_id[]
  name: string
  imageUrl?: string
  category?: string
  priceLabel?: string // already formatted by the existing menu source
}

// Exported contract: UpsellingProps['loadProducts']
type LoadProducts = (scope: {
  businessId: string
  restaurantId?: string
}) => Promise<UpsellProduct[]>
```

不替换行索引,变体ID或菜单项ID,除非它真的是推荐引擎的产品身份. 这个适配器故意避免将软件包与特定的菜单方案/版本相接. 缺失或破损相片显示文字,而非图标.

或者,挂载 `<UpsellingSettings>` 同样的道具。 它发出 `dirty-change`, (中文(简体) ), `busy-change` 财务报告和审定财务报表 `saved`. 直接组件主机必须利用这些事件守护导航;路线工厂包括未保存的更改确认,并在节省期间防止导航。 两种模式都在浏览器卸下时警告. 通过提供 `messages` 道具; `i18nMessages` 出口 `upselling` 为主机合并设置有英文默认的命名空间 .

可选 `loadApplyTargets(businessId): Promise<UpsellApplyTarget[]>` 启用 **编辑范围** 产品之上的选择器。 每个目标用品 `{ scope: { businessId, restaurantId? }, name, products, unavailableReason? }`,随着主机用菜单服务的菜单模式,目录分配和v3/v4会员规则来解决其实际有效的目录. 奥米 `restaurantId` 用于商业违约。 从不平整独立出入口目录或按名称匹配产品. 无法获取的输出目标不在此列; 范围加载失败已禁用 。 没有这种回调,现有的单镜保存行为不变.

范围选择器,编辑器和预览器共享一个挂载业务的目录负载;更改业务或目录提供者使其无效,失败的负载可以被重审. 选择商业默认显示商业目录并保留单独的预览出站选择器. 选择一个输出点只显示输出点可用的产品,加载其有效的设置,并预览该输出点。 继承的设置被明确确定. 将保存直接应用到选定的范围,而不设置目标对话框 。 为可见目录外的产品所保存的设置被保留; 商业- 默认更新永远不会删除输出覆盖 。 每个商务/出口独立地为挂起会话恢复发稿,导航警告包括其他范围发稿. 保存或丢弃只影响选定的草稿 。 现有的GET/PUT仍然是最后的写法胜出,没有原子同币保护. 商业默认需要一个经主机验证的共享目录. 没有引入批量API,计划或指数变化.

## API / 收藏

后端旗帜 : `UPSELL_SETTINGS_ENABLED=true` 明确启用设置。 未设置或任何其他值会禁用特性:没有注册更新的Mongo连接/服务,认证的设置请求返回503。 其他报告没有改变。 重新启动/重新部署来更改旗帜;只有在数据库和索引提供后才能启用.

公开获取和PUT `/:businessId/upsell-settings` 编辑商业默认而不需要餐厅. 现有 `/:businessId/:restaurantId/upsell-settings` 路由编辑餐厅覆盖;网关将其重写为内部 `/:businessId/restaurants/:restaurantId/upsell-settings`。所有路线都需要现有的火地无记名标志。 有一个 **没有功能级别编辑权限**. 企业成员(即使没有特性权限)和拥有现有所有者/代理/代理企业接入的呼叫者可以编辑。 餐馆的检查要求 仍然检查 餐厅属于该行业.

保存的餐厅文档会覆盖整个业务配置,包括当其 `items` 明确为空。 没有一家,餐馆就按要求返回企业违约 `restaurantId` 和衍生 `inherited: true`;它不创建副本。 保存继承的编辑器会创建餐厅覆盖 。 餐厅路线上的DELETE移除了该功能,返回当前默认值. 业务路线DELETE被拒绝. 当 API 适配器提供时, UI 提供“ 使用商业默认值 ” `reset()`; 获取适配器支持它, Axios 主机必须提供 `delete()` 这个控制。 不从两个范围合并单个产品. 推荐引擎在应用分数前必须解决同一个餐厅-当时的经营倒计时问题;这种整合仍由Eric负责,不会被此设置放出所改变.

获取返回 `{ businessId, items: [], updatedAt: null }` 当未保存商业默认值时,不创建文档。 餐厅的答复包括所要求的 `restaurantId` 财务报告和审定财务报表 `inherited: true` 当不存在覆盖时。 PUT 只接受 `{ items: [...] }` ,并在解析时替换已配置的列表。 两者都返回设置;保存的响应也有 `_id` 和一个ISO `updatedAt`. PUT 拒绝未知字段,重复产品ID,非boole开关和非无限/外重. 技术限制:每个范围有一万个配置出的产品;产品标识为非空字符串可达256个字符.

```text
dataDB.upsellSettings {
  _id,
  businessId,
  restaurantId: null | restaurantId, // null for the business default
  items: [
    {
      productId,
      adjustWeight: Boolean,
      weight: Number // 0..1
    }
  ],
  updatedAt: Date
}
```

提供唯一的索引 `{ businessId: 1, restaurantId: 1 }`名称 `upsellSettings_business_restaurant`在授权写作之前, 应用程序启动时不创建索引 。 在实际部署数据库中确认该索引;在同时进行首次保存时,该索引可防止重复设置。 这个名字 `upsellDataDB` 连接使用已有的 `MONGODB_URL`,明确选择 `dataDB`;现有的公司数据库库保持不变。 运行时的证书需要读取/写入收藏,但此功能不需要索引创建许可. 这一新收集不需要数据迁移/回填。 同时期编辑器使用上次成功保存的胜负;没有版本字段.

## 构建和测试

```sh
pnpm install --frozen-lockfile
pnpm test
pnpm build
pnpm check:package
pnpm build:example
pnpm test:backend
```

`test:backend` 运行针对Nest HTTP/MongoDB的可支配回路MongoDB测试,然后停止. 它下载了MongoDB官方二进制在先使用的版本. Firebase 校验被屏蔽;没有使用应用程序数据库证书.

只用于单位后端测试, 运行 `yarn test --runInBand --testPathPattern=upsell-settings` 内 `packages/node`除非一次性绳子能提供核磁共振.

主机实例 `example/main.ts` 需求 `window.upsellingHost` 与 `apiBaseUrl`, (中文(简体) ), `businessId`选项 `restaurantId` 财务报告和审定财务报表 `restaurantName`, (中文(简体) ), `getToken()` 财务报告和审定财务报表 `loadProducts(scope)`。每个请求解析当前门户网站火地标;从不在Vite环境变量或浏览器存储中放入地标。 没有主机上下文,该示例不会提出请求.

`createUpsellFetchApi({ baseUrl, getToken })` 为没有Axios客户端的主机导出。 它使用相同的平面反应GET/PUT API,没有模拟倒置. 后端必须允许主机通过它的CORS配置来源.

设置 API 和建议 API 必须读取相同的保存设置数据集 。 一个与Mongo隔离的本地推荐主机需要一个与编辑器设置相匹配的明确的测试-业务快照;一个空的本地数据库不是一个有效的比较基线.

商业- 默认预览会保存输出的全覆盖, 匹配 applic; 草稿只覆盖继承的默认或正在编辑的输出 。 预览请求拒绝非本地HTTP URL和重定向,并绑定建议呼叫为15秒. 存储权限/ 输出/ 配置失败返回错误; 只有真正缺失的模型允许冷启动后退 。 缺失的模型共享一个有边框的30秒缓存来避免重复存储读取;新生成的历史最多需要30秒才能出现. 存储错误没有被缓存 .

Eric的精确输出特定缺失型号404显示为空预览,因此"前作"的空"不会隐藏"后作"后作"的加权". 其他404次和服务故障仍然是错误.

### 门户区域API一体化

`createUpsellPortalApi(coreStore, { loadProducts })` 拥有设置和建议 请求。 它读取了Portal的反应 `namespace`, (中文(简体) ), `currentCountry` 财务报告和审定财务报表 `sessionUser.token`; 连接不构建 API 主机. 使用 `getUpsellingEndpoints(country, namespace)` 用于出入口导航和渲染. 工厂解决所选区域,并为每次呼叫提供新标志.

配置的生产国:MY、SG、TH、VN、AE、AU。 Dev还包括JP和PH. My没有国家子域;其他国家使用小写国家代码: `query-engine.sg.feedmeapi.com` 财务报告和审定财务报表 `public-query-engine.sg.feedmeapi.com`。 。 。 . 设计用途 `feedmeapidev.com`。不支持的国家/名称空间会被拒绝,而无需 回到我身边。 区域探测器确定路线/校正反应, 未授权排名或区域能力.

## 常见问题

### @feedmepos/mf-upselling 是什么？

Connect 的商家设置微前端 。 所有功能 UI 都住在这里; API 运行于报表- query- service 下 packages/node连接导入用户界面,并供应其已认证的上下文。 没有新的服务或菜单编辑器 \.

### 如何安装 @feedmepos/mf-upselling？

在项目目录运行 npm install @feedmepos/mf-upselling，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：vue（^3\.4\.21）、vue-router（^4\.3\.0）、@feedmepos/ui-library（^1\.8\.8）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @feedmepos/mf-upselling 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @feedmepos/mf-upselling 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @feedmepos/mf-upselling 可以商用吗？

@feedmepos/mf-upselling 使用 UNLICENSED 许可。作者声明为 UNLICENSED，即不授予公开使用许可（与公共领域的 Unlicense 不同）。使用前需获得作者授权。以上为概括，不构成法律意见，请以许可原文为准。

### @feedmepos/mf-upselling 的下载量有多少？

根据 npm 官方下载统计，@feedmepos/mf-upselling 在 2026/10/15 – 2026/11/13 这 30 天内被下载 2,126 次，日均约 71 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @feedmepos/mf-upselling 还在维护吗？

最新版本 0\.3\.2 发布于 2026/10/29（16 天前）；至今共发布 12 个版本，其中过去 12 个月发布了 12 个；首次发布于 2026/10/14。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

