--- name: extension-slots description: MallBase 扩展槽边界规范;涉及会员、积分、分销、余额、优惠等权益扩展接入订单、商品编辑或 UniApp 展示时使用。 --- # 扩展槽边界规范 ## 适用场景 当需求涉及以下任一方向时,优先使用本规则: - 订单金额计算新增权益项,例如会员优惠、积分抵扣、优惠券、余额权益、分销相关金额。 - 订单状态流转新增副作用,例如支付后冻结、完成后发放、关闭后回滚、退款后扣回。 - 后台商品编辑页新增营销字段或 SKU 级权益字段。 - UniApp 商品详情、规格弹窗、订单确认页新增权益展示。 - 现有会员、积分、分销、余额能力需要接入统一扩展点。 ## 后端规则 1. 订单金额扩展优先实现 `OrderPriceContributorInterface`,通过 `OrderPricePipeline` 接入。 2. 订单状态副作用优先实现 `OrderEventListenerInterface`,通过 `OrderEventDispatcher` 接入。 3. 新扩展默认注册在 `ExtensionRegistry`,不要把新权益逻辑直接堆回 `OrderService`、`OrderStatusMachine` 或 `RefundOrderStatusMachine`。 4. 扩展实现必须保持 Service 无状态,不能依赖实例属性保存请求态。 5. 扩展中的落库副作用必须幂等,尤其是支付、完成、关闭、退款等可重复触发的事件。 6. 金额扩展必须以分为边界做精确分配,避免浮点误差;返回给前端的金额统一保留两位小数。 7. 多个扩展同时作用于订单金额时,必须明确优先级,避免互相覆盖或重复扣减。 8. 不要为了单次、局部、不会复用的逻辑强行新增扩展点;局部简单逻辑可以留在原模块内。 ## 后台商品编辑规则 1. 商品营销字段、SKU 扩展字段优先集中在 `frontend/admin/apps/web-antd/src/views/goods/goods/extension-slots.ts`。 2. `goods-edit.vue` 和 `useGoodsEdit.ts` 只负责渲染、透传、批量应用、提交转换,不再散落具体权益字段判断。 3. 新增 SKU 字段必须同时覆盖默认值、编辑回填、批量设置、提交转换和列显隐。 4. 字段显隐必须由功能开关和当前表单模式共同决定,避免功能关闭后仍提交隐藏字段。 ## UniApp 规则 1. 商品详情、规格弹窗、订单确认页的权益展示优先集中在 `frontend/uniapp/utils/extension-slots.js`。 2. 展示层只消费扩展槽返回的展示项,避免每个页面重复判断会员价、积分赠送、成长值等细节。 3. 订单确认页的权益卡片、商品行提示、价格汇总行应从同一扩展状态构建,避免展示和提交金额不一致。 4. 新增可交互权益项时,必须明确默认状态、禁用条件、提交参数和接口预览结果的对应关系。 ## 测试要求 1. 后端新增价格贡献器或事件监听器时,至少补充管线或监听器单测。 2. 影响订单主链路时,必须覆盖预览、创建、支付、完成、关闭或退款中的相关边界。 3. 影响前端展示时,至少执行对应前端构建;涉及真实用户链路时,用本地接口和浏览器抽样验证。 4. 如果只调整扩展槽结构但不改变行为,测试可以聚焦在原有合同不变和关键页面不报错。 ## 反模式 - 在 `OrderService::calculateAmounts()` 中继续追加会员、积分、分销、优惠券等分支。 - 在状态机里直接调用具体业务 Service,绕过统一事件分发。 - 前端多个页面分别复制同一套会员价、积分赠送、成长值判断。 - 功能开关关闭后仍显示字段、提交字段或触发副作用。 - 为一次性页面排版创建新的扩展槽,增加不必要复杂度。