# 商品推荐规则引擎 — 实现计划 > 基于 `docs/superpowers/specs/2026-09-17-product-recommendation-rule-engine-design.md` ## 阶段 0:数据库迁移 **目标**:创建 `recommendation_rules` 表,同步 schema.sql **步骤:** 1. 在 `cfc-backend/src/main/resources/schema.sql` 末尾追加 `CREATE TABLE recommendation_rules (...)` 定义(含索引) 2. 在 `DatabaseInitializer.java` 末尾的 `runMigrations()` 中添加新迁移(迁移编号递增,当前最大编号搜索确认) 3. 执行 `mvn clean compile` 验证无编译错误 **文件:** - `cfc-backend/src/main/resources/schema.sql` - `cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java` --- ## 阶段 1:新实体 + Mapper + Service **目标**:基础 CRUD 能力 **步骤:** 1. 新建 `entity/RecommendationRule.java`(对应 recommendation_rules 表,字段见设计文档 3.1) 2. 新建 `mapper/RecommendationRuleMapper.java`(使用 MyBatis-Plus,提供按 scene、rule_type、enabled 查询方法) 3. 新建 `service/RecommendationRuleService.java` - `listRules(sceneCode, page, size)` — 分页列表 - `getRuleById(id)` — 详情 - `createRule(rule)` — 创建,含参数校验(rule_type 1-5、priority>0、trigger/target 非空等) - `updateRule(id, rule)` — 更新 - `deleteRule(id)` — 删除(设 enabled=0,软停用) - `batchUpdateEnabled(ids, enabled)` — 批量启用/停用 4. 新建 `controller/recommendation/RecommendationRuleAdminController.java` - `POST /api/admin/recommendation-rules/list` - `POST /api/admin/recommendation-rules/create` - `POST /api/admin/recommendation-rules/update` - `POST /api/admin/recommendation-rules/delete` - `POST /api/admin/recommendation-rules/batch-enable` 5. 运行 `mvn clean compile` 验证 --- ## 阶段 2:推荐引擎核心实现 **目标**:`RecommendationRuleEngine.recommend(ctx, limit)` 完成 5 种规则计算 **步骤:** 1. 新建 `service/RecommendationRuleEngine.java`(实现 `RecommendationRuleEngine` 接口) 2. 内部方法设计: - `loadRules(String sceneCode)` — 加载匹配的启用规则,按 priority DESC - `queryPurchasedProducts(RecommendationContext ctx)` — 查购买记录,返回 `Map`(productId → 最早购买日期) - `buildBaseCandidates(RecommendationContext ctx)` — 按场景构建候选池(保留现有维度页推荐逻辑) - `applyRules(List rules, Set purchasedIds, List candidates)` — 应用所有规则 - 先处理规则4(排除类,从高 priority 开始) - 再处理规则1(排除类) - 再处理规则3(推荐类) - 再处理规则5(推荐类 + boost) - 再处理规则2(定时复购类) - `sortAndTruncate(List candidates, int limit)` — 排序截断 3. 保留 `ProductRecommendationService.getDimensionRecommendations` 现有逻辑作为 `buildBaseCandidates` 的基础实现,但不再直接调用 `getPurchasedProductIds`,改由引擎统一处理 4. 在 `ProductRecommendationController.getDimensionProducts` 中: - 保留 Controller 接口签名不变 - 内部改为调用 `engine.recommend(ctx, limit)`,将 `RecommendedProduct` 映射为现有 `Map` 格式返回 5. 运行 `mvn clean compile` 验证 --- ## 阶段 3:RepurchaseReminderService 改造 **目标**:规则2 配置从 `recommendation_rules` 读取,旧 `repurchase_reminder_config` 不再被代码引用 **步骤:** 1. 修改 `RepurchaseReminderService.scanAndCreateReminders()` - 旧逻辑:读 `repurchase_reminder_config` 表 - 新逻辑:读 `recommendation_rules` 表中 `rule_type=2 AND enabled=1` 的规则 - 映射关系: - `trigger_product_id` → 触发商品 - `delay_days` → 复购延迟天数 - `target_product_id` → 复购提醒的商品(与 trigger 相同或不同均可) - `max_reminders` → `recommendation_rules` 表暂无此字段,暂时复用 `repurchase_reminder_record` 中的已发送次数判断 2. 保留定时任务 `@Scheduled(cron = "0 0 9 * * ?")`,不修改触发时间 3. 运行 `mvn clean compile` 验证 --- ## 阶段 4:新增推荐场景接口(可选) **目标**:商城首页、商品详情页、下单成功页的推荐接口 **步骤:** 1. 新增 `POST /api/recommend/mall-home` - 入参:`{ "limit": 10 }` - 内部:`engine.recommend(ctx, limit)` 其中 `scene="mall_home"` 2. 新增 `POST /api/recommend/product-detail` - 入参:`{ "productId": 123, "limit": 6 }` - 内部:`engine.recommend(ctx, limit)` 其中 `scene="product_detail"`, `currentProductId=123` 3. 新增 `POST /api/recommend/after-order` - 入参:`{ "orderId": 456, "limit": 6 }` - 内部:`engine.recommend(ctx, limit)` 其中 `scene="after_order"` 4. 修改 `ProductRecommendationService.getReportRelatedProducts` - 内部改为调用 `engine.recommend(ctx, limit)` 其中 `scene="report_related"` 5. 运行 `mvn clean compile` 验证 --- ## 阶段 5:前端管理端页面 **目标**:cfc-web 新增「商品推荐规则」管理页面 **步骤:** 1. 在 `cfc-web/src/views/` 下新建 `RecommendationRules.vue` - 页面标题:商品推荐规则 - 功能:列表展示 + 新建/编辑弹窗 + 启用/停用开关 - 字段:rule_type(类型下拉)、rule_name、trigger_product_id、target_product_id、priority、enabled(开关)、scene_codes(多选) 2. 在 `cfc-web/src/router/` 下新增路由 `/admin/recommendation-rules` 3. 在 `cfc-web/src/api/` 下封装推荐规则接口 4. 运行 `npm run build` 验证编译通过 --- ## 阶段 6:单元测试与集成验证 **目标**:规则计算正确,降级场景正常 **步骤:** 1. 编写 `ProductRecommendationEngineTest`(或 `RecommendationRuleEngineTest`) - 测试5种规则各自命中场景 - 测试 priority 排序 - 测试 scope family vs individual - 测试 time_window_days 边界 - 测试降级:规则表为空时仍能返回候选(退化为全局已购排除) 2. 运行 `mvn clean test` 3. 运行 `mvn clean compile` 最终验证 4. 如有运行时条件,在测试库 `192.168.16.251:3306` 执行迁移,验证接口返回正常 --- ## 变更文件清单 | 新增文件 | 说明 | |---------|------| | `cfc-backend/.../entity/RecommendationRule.java` | 新实体 | | `cfc-backend/.../mapper/RecommendationRuleMapper.java` | Mapper | | `cfc-backend/.../service/RecommendationRuleService.java` | CRUD Service | | `cfc-backend/.../service/RecommendationRuleEngine.java` | 引擎核心 | | `cfc-backend/.../controller/recommendation/RecommendationRuleAdminController.java` | 管理端 Controller | | `cfc-web/src/views/RecommendationRules.vue` | 管理端页面 | | `cfc-web/src/api/recommendationRule.js` | 管理端 API 封装 | | 修改文件 | 说明 | |---------|------| | `cfc-backend/.../service/ProductRecommendationService.java` | 改为调用引擎 | | `cfc-backend/.../service/RepurchaseReminderService.java` | 规则2 配置改读 recommendation_rules | | `cfc-backend/.../config/DatabaseInitializer.java` | 新增 DDL 迁移 | | `cfc-backend/src/main/resources/schema.sql` | 新增 recommendation_rules 表定义 | | `cfc-web/src/router/index.js` | 新增路由 | | `docs/superpowers/api/API_REFERENCE.md` | 同步新增接口文档 |