mirror of
https://github.com/crmeb/CRMEB.git
synced 2026-10-28 21:40:50 +00:00
117 lines
6.4 KiB
Markdown
117 lines
6.4 KiB
Markdown
# modules/ — 业务扩展层
|
||
|
||
## 层定位
|
||
|
||
`modules/` 是 CRMEB v8.0 架构的**业务扩展层**,位于 `app/` 之上,**可以调用 `app/` 和 `crmeb/` 的所有服务**。
|
||
|
||
本层存放所有可插拔的业务模块,按业务域分类组织。
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
modules/
|
||
├── trade/ 交易域 —— 订单管线扩展(全部实现 TradeModeHandlerInterface)
|
||
│ ├── combination/ 拼团 activity_combination
|
||
│ ├── seckill/ 秒杀 activity_seckill
|
||
│ ├── bargain/ 砍价 activity_bargain
|
||
│ ├── integral/ 积分商城 activity_integral
|
||
├── product/ 商品域 —— 产品类型(全部实现 ProductTypeHandlerInterface)
|
||
│ ├── normal/ 实物商品 product_normal
|
||
│ ├── virtual/ 虚拟商品 product_virtual
|
||
│ └── cardkey/ 卡密商品 product_cardkey
|
||
├── marketing/ 运营域 —— 权益与奖励(纯事件观察者)
|
||
│ ├── signin/ 签到 user_signin
|
||
│ ├── lottery/ 抽奖 activity_lottery
|
||
│ ├── newuser/ 新人专区 marketing_newuser
|
||
│ ├── channel_code/ 渠道码 user_channel_code
|
||
│ └── recharge/ 充值 user_recharge(已与订单中台解耦,独立充值单)
|
||
├── agent/ 分销代理模块
|
||
└── channel/ 用户/端渠道扩展(APP/H5/小程序/公众号)
|
||
```
|
||
|
||
> 第三方驱动(支付/短信/上传等)不在 `modules/` 下,统一位于根目录 `driver/{category}/{name}/`,
|
||
> 由各 `app/services/driver/*/*DriverServices` 扫描发现,安装时按 plugin.json 的
|
||
> `path`(`driver/{category}/{name}`)落位。
|
||
|
||
`trade/`(怎么卖)× `product/`(卖什么)是两个**正交维度**,可自由组合
|
||
(同一商品既能拼团卖也能秒杀卖),各自有独立注册表:
|
||
`crmeb/trade/mode/TradeModeRegistry` 与 `crmeb/trade/product/ProductTypeRegistry`。
|
||
|
||
## 模块内部目录规范
|
||
|
||
每个模块(`{域}/{type}/`)内部的子目录命名与职责**全 modules 统一**,新增模块必须按下表搭建:
|
||
|
||
### 根文件(必备)
|
||
|
||
| 文件 | 职责 |
|
||
|------|------|
|
||
| `App.php` | 模块注册入口(`register()` 注册处理器,`boot()` 加载 `event.php`) |
|
||
| `Installer.php` | 安装/卸载/启用/禁用(建表/菜单/种子,幂等) |
|
||
| `plugin.json` | 插件元数据(`key`/`name`/`type`/`path`) |
|
||
| `event.php` | 事件监听器注册表 |
|
||
| `Handler.php` | 产品类型处理器(**仅 `product/` 域模块**,实现 `ProductTypeHandlerInterface`) |
|
||
|
||
### 子目录(按需,命名固定)
|
||
|
||
| 目录 | 命名 | 职责 | 备注 |
|
||
|------|------|------|------|
|
||
| `controller/` | — | 控制器,固定双端结构:`admin/` + `user/v1/` | |
|
||
| `route/` | — | 路由文件:`admin.php` / `user.php`(`manage.php` 可选),自动扫描加载 | |
|
||
| `service/` | — | 服务层(类名 `XxxServices`) | |
|
||
| `dao/` | — | 数据访问层(类名 `XxxDao`) | 纯事件观察者模块(如 `marketing/newuser`)可缺省 |
|
||
| `model/` | — | 模型层 | 同上可缺省 |
|
||
| `validate/` | — | 验证器 | 按需 |
|
||
| `listener/` | — | 事件监听器(类名 `XxxListener`,与 `event.php` 对应) | |
|
||
| `jobs/` | **复数** | 队列任务(继承 `BaseJobs`) | ⚠️ 单数 `job/` 已废弃(2026-08 统一迁移),禁止新建 |
|
||
| `handler/` | — | 域内处理器子目录:`trade/` 域放 `{Mode}ActivityHandler`;`product/` 域放 `{Type}OrderAdapter` + `{Type}AfterSaleHandler` | 根 `Handler.php` 为产品类型主处理器(仅 `product/` 域有) |
|
||
| `crontab/` | — | 定时任务(如拼团到期、分销员解绑) | 按需 |
|
||
|
||
### 特殊目录(已有模块使用,新模块按需参照)
|
||
|
||
| 目录 | 使用方 | 职责 |
|
||
|------|--------|------|
|
||
| `sdk/` + `notify/` | `channel/wechat_mp`、`channel/wechat_mini` | 第三方 SDK 封装 + 回调处理 |
|
||
| `pipeline/` | `product/cardkey`、`product/virtual` | 履约管线 |
|
||
| `frontend/dist` | `product/virtual` | 模块内前端构建产物 |
|
||
|
||
## 边界规则(新模块放哪?)
|
||
|
||
**一句话:改变一笔订单如何成交的 → `trade/`;决定卖什么形态商品的 → `product/`;
|
||
只发放权益、奖励行为、不改变成交的 → `marketing/`。**
|
||
|
||
"牵扯订单"要拆成三种性质再判断:
|
||
|
||
| 性质 | 含义 | 判别方法 | 归属 |
|
||
|------|------|---------|------|
|
||
| **改变成交** | 实现交易契约,订单管线主动调用它 | 实现 `TradeModeHandlerInterface`(定价/下单校验/支付前后/退款/完成等钩子) | `trade/` |
|
||
| **决定商品形态** | 决定 SKU 模型、履约方式(发货/发卡/核销)、售后规则 | 实现 `ProductTypeHandlerInterface` + `OrderTypeAdapter` | `product/` |
|
||
| **观察订单** | 监听订单事件发权益,移除后订单流程完全不受影响 | 只在 `event.php` 里 listen(如 `OrderPayLottery`) | `marketing/` |
|
||
| **自建迷你流程** | 奖品/权益发放挂在活动记录上,不创建订单 | 有自己的发放记录表,不写 `eb_order_center` | `marketing/` |
|
||
|
||
> 会员订单不在 `trade/`:已独立为 `app/` 层 `eb_member_order` 体系。
|
||
|
||
## 扩展点一览
|
||
|
||
| 扩展点 | 目录 | 解决什么 |
|
||
|--------|------|---------|
|
||
| 交易域 | `trade/` | 怎么卖:交易模式(定价策略、成团/限量规则、订单生命周期钩子) |
|
||
| 商品域 | `product/` | 卖什么:产品类型(履约形态、库存方式、售后规则) |
|
||
| 运营域 | `marketing/` | 送什么:权益与奖励(签到/抽奖/新人礼/渠道码) |
|
||
| 分销代理 | `agent/` | 分销员管理、分销等级、事业部、佣金结算 |
|
||
| 用户渠道 | `channel/` | 用户从哪来、如何识别登录、推送消息 |
|
||
|
||
## 依赖铁律
|
||
|
||
- `modules/` 内各模块之间**不可互相引用**
|
||
- 跨模块通信必须走 `crmeb/` 核心层契约或通过事件机制(`event()`)
|
||
- 每个目录都是独立插件包,包含 `plugin.json` + `Installer.php` + `App.php` + 标准 MVC 目录结构
|
||
|
||
## 自动发现机制
|
||
|
||
- 路由文件放入 `route/` 目录(`admin.php`/`user.php`/`manage.php`)后自动扫描加载
|
||
- 菜单生命周期由 `BaseModuleInstaller` 统一管理
|
||
- `plugin.json` 中的 `type` 字段决定插件分类(`mode`→trade、`product`/`product_type`→product、`marketing`→marketing)
|
||
|
||
> 历史参考:2026-08 由 `trade/mode/*` 拍平为 `trade/*`、`trade/product/*` 提升为 `product/*`,
|
||
> 模块 key 不变,plugin.json `path` 已同步。
|