222 lines
7.8 KiB
Markdown
222 lines
7.8 KiB
Markdown
# 餐饮零售数据中台 (DataHub)
|
||
|
||
> 基于有赞云 API 的连锁餐饮数据中台系统,实现订单/商品/客户/库存数据的 T+1 自动同步,并提供商品洞察、会员 RFM 分层、购物篮挖掘、智能订货建议等 BI 分析能力。
|
||
|
||
---
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
AIMachineSystem/
|
||
├── server/ # Spring Boot 后端服务
|
||
│ ├── src/main/java/ # Java 源代码
|
||
│ ├── src/main/resources/application.yml # 应用配置
|
||
│ └── pom.xml # Maven 依赖管理
|
||
├── dashboard-ui/ # 前端 BI 大盘 (纯 HTML/CSS/JS)
|
||
│ ├── index.html # 主页面
|
||
│ ├── styles.css # 样式 (毛玻璃/苹果设计风格)
|
||
│ └── app.js # 数据交互 (ECharts 图表)
|
||
├── sql/ # 数据库 DDL & 补丁
|
||
│ ├── youzan_tplus1_ddl.sql # 全量建表 (一键建库)
|
||
│ └── phase4_alter_outer_item_id.sql # 增量补丁
|
||
├── docs/ # 产品需求文档 & 技术设计文档
|
||
└── prototype/ # 原型设计
|
||
```
|
||
|
||
---
|
||
|
||
## 技术栈
|
||
|
||
| 类别 | 技术 |
|
||
|------|------|
|
||
| 后端框架 | Java 17 + Spring Boot 3.2.x |
|
||
| ORM | MyBatis-Plus 3.5.x |
|
||
| 数据库 | MySQL 8.0 |
|
||
| 数据源 | 有赞云开放平台 API |
|
||
| 前端 | HTML5 + CSS3 + JavaScript + ECharts |
|
||
| 构建工具 | Maven |
|
||
|
||
---
|
||
|
||
## 安装部署
|
||
|
||
### 1. 环境要求
|
||
|
||
- **JDK 17+**
|
||
- **Maven 3.8+**
|
||
- **MySQL 8.0+**
|
||
- 有赞云自用型应用(需要 `client_id`、`client_secret`、`grant_id`)
|
||
|
||
### 2. 数据库初始化
|
||
|
||
```sql
|
||
-- 1. 创建数据库
|
||
CREATE DATABASE youzandatahub DEFAULT CHARSET utf8mb4;
|
||
|
||
-- 2. 执行全量建表脚本
|
||
SOURCE sql/youzan_tplus1_ddl.sql;
|
||
```
|
||
|
||
### 3. 修改配置
|
||
|
||
编辑 `server/src/main/resources/application.yml`:
|
||
|
||
```yaml
|
||
spring:
|
||
datasource:
|
||
url: jdbc:mysql://你的IP:3306/youzandatahub?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
|
||
username: 你的用户名
|
||
password: 你的密码
|
||
|
||
youzan:
|
||
api:
|
||
base-url: https://open.youzanyun.com
|
||
client-id: 你的client_id
|
||
client-secret: 你的client_secret
|
||
kdt-id: 你的kdt_id
|
||
```
|
||
|
||
### 4. 编译 & 启动
|
||
|
||
```bash
|
||
cd server
|
||
mvn clean compile
|
||
mvn spring-boot:run
|
||
```
|
||
|
||
服务启动后监听 `http://localhost:8080`。
|
||
|
||
### 5. 前端访问
|
||
|
||
直接用浏览器打开 `dashboard-ui/index.html` 即可,无需额外构建。
|
||
|
||
> 前端默认连接 `http://localhost:8080` 后端接口,如需修改请编辑 `app.js` 中的 `API_BASE` 变量。
|
||
|
||
---
|
||
|
||
## 定时任务 (自动执行)
|
||
|
||
系统启动后,以下任务每日自动执行,**无需人工干预**:
|
||
|
||
| 执行时间 | 任务名称 | Job 类 | 说明 |
|
||
|---------|---------|--------|------|
|
||
| 02:00 | 订单同步 | `TradeSyncJob` | 拉取前一天全量订单明细写入 `dwd_trade_order_detail` |
|
||
| 02:30 | 商品同步 | `ItemCustomerSyncJob` | 全量同步有赞商品目录到 `dim_item_sku` |
|
||
| 02:45 | 客户聚合 | `ItemCustomerSyncJob` | 从订单表聚合客户画像到 `dim_customer_info` |
|
||
| 03:00 | 门店同步 | `Phase3SyncJob` | 同步门店/网点信息到 `dim_offline_store` |
|
||
| 03:10 | 退款同步 | `Phase3SyncJob` | 拉取前一天退款单到 `dwd_trade_refund_detail` |
|
||
| 03:20 | 库存快照 | `Phase3SyncJob` | 采集各门店当日库存到 `dim_inventory_snapshot` |
|
||
| 04:00 | 洞察计算 | `InsightComputeJob` | 全域数据市集聚合(详见下方) |
|
||
|
||
### 04:00 洞察计算明细
|
||
|
||
| 步骤 | 计算内容 | 写入表 |
|
||
|------|---------|--------|
|
||
| 1 | 商品日销售趋势 | `adm_item_sales_trend` |
|
||
| 2 | 购物篮关联规则 (Apriori Top20) | `adm_item_basket` |
|
||
| 3 | 商品30天复购率 & 波士顿矩阵 | `adm_item_repurchase` |
|
||
| 4 | 会员 RFM 评分 & 客群分层 | `adm_customer_rfm` |
|
||
| 5 | 会员特征标签画像 | `adm_customer_tags` |
|
||
| 6 | 智能订货建议 (14天流速) | 实时计算,不落表 |
|
||
|
||
---
|
||
|
||
## 手动运行指令
|
||
|
||
### HTTP 接口 (浏览器直接访问)
|
||
|
||
| 接口地址 | 用途 |
|
||
|---------|------|
|
||
| `GET /api/insight/compute-all` | 手动触发全量洞察计算(等同于 04:00 的定时任务) |
|
||
| `GET /api/admin/backfill/january-to-now` | 补全今年1月至今全量历史订单+退款+客户(后台异步执行,按天拉取) |
|
||
|
||
### BI 查询接口 (前端调用)
|
||
|
||
| 接口地址 | 返回内容 |
|
||
|---------|---------|
|
||
| `GET /api/dashboard/overview` | 过去14天大盘概览(GMV、订单数、退款额、客单价) |
|
||
| `GET /api/dashboard/trend` | 过去14天日维销售趋势 |
|
||
| `GET /api/product/repurchase` | 商品30天复购率 & 波士顿矩阵打标 |
|
||
| `GET /api/product/basket` | 购物篮关联 Top20 |
|
||
| `GET /api/product/advice` | 智能订货预测单(基于14天日均流速) |
|
||
| `GET /api/customer/rfm/distribution` | RFM 客群金字塔分布 |
|
||
| `GET /api/customer/tags` | 会员标签统计 |
|
||
|
||
### 诊断测试脚本 (独立 main 方法)
|
||
|
||
在 `server/` 目录下执行:
|
||
|
||
```powershell
|
||
# 有赞 Token 连通性测试
|
||
mvn -q compile exec:java `-Dexec.mainClass="com.chuyishidai.datahub.YouzanTokenTest"
|
||
|
||
# 订单数据诊断 (分页、总量对比)
|
||
mvn -q compile exec:java `-Dexec.mainClass="com.chuyishidai.datahub.YouzanOrderDiagTest"
|
||
|
||
# 商品 item_id 比对诊断
|
||
mvn -q compile exec:java `-Dexec.mainClass="com.chuyishidai.datahub.ItemIdDiagTest"
|
||
|
||
# 退款数据诊断
|
||
mvn -q compile exec:java `-Dexec.mainClass="com.chuyishidai.datahub.RefundDiagTest"
|
||
```
|
||
|
||
> **注意**: 在 PowerShell 中 `-D` 前需加反引号 `` ` `` 转义。
|
||
|
||
---
|
||
|
||
## 数据分层架构
|
||
|
||
```
|
||
有赞云 API ──► DWD 明细层 (事实表) ──► DIM 维度层 ──► ADM 数据市集层 (洞察)
|
||
│
|
||
▼
|
||
REST API
|
||
│
|
||
▼
|
||
前端 BI 大盘
|
||
```
|
||
|
||
| 层级 | 前缀 | 表 | 说明 |
|
||
|-----|------|------|------|
|
||
| 明细层 | `dwd_` | `dwd_trade_order_detail` | 交易订单明细 |
|
||
| | | `dwd_trade_refund_detail` | 退款明细 |
|
||
| | | `dwd_inventory_flow_di` | 库存流水 |
|
||
| | | `dwd_coupon_flow` | 优惠券流水 |
|
||
| 维度层 | `dim_` | `dim_item_sku` | 商品维度 |
|
||
| | | `dim_customer_info` | 客户维度 (OneID) |
|
||
| | | `dim_offline_store` | 门店维度 |
|
||
| | | `dim_inventory_snapshot` | 库存快照 |
|
||
| 市集层 | `adm_` | `adm_item_sales_trend` | 商品日销趋势 |
|
||
| | | `adm_item_basket` | 购物篮关联 |
|
||
| | | `adm_item_repurchase` | 复购率 & 波士顿矩阵 |
|
||
| | | `adm_customer_rfm` | RFM 评分 |
|
||
| | | `adm_customer_tags` | 客户标签 |
|
||
|
||
### 重要设计决策
|
||
|
||
- **商品聚合维度**: 有赞连锁模式下同一商品在不同门店有不同 `item_id`,系统统一使用 `outer_item_id`(商家编码)作为跨门店商品唯一标识。
|
||
- **数据同步策略**: 采用 `INSERT ... ON DUPLICATE KEY UPDATE` (Upsert) 保证幂等性。
|
||
- **快照表刷新**: `adm_` 前缀的快照型表(除 `adm_item_sales_trend` 外)每次计算前先 `DELETE` 再 `INSERT`,确保全量覆盖。
|
||
- **餐具过滤**: 购物篮和复购率计算自动过滤 `title LIKE '%餐具%'` 的必选附加品。
|
||
|
||
---
|
||
|
||
## 配置参数说明
|
||
|
||
在 `application.yml` 中可调整的关键参数:
|
||
|
||
```yaml
|
||
sync:
|
||
trade:
|
||
cron: "0 0 2 * * ?" # 订单同步 cron 表达式
|
||
page-size: 100 # 每页拉取条数
|
||
overlap-minutes: 30 # 时间窗口重叠 (防止遗漏边界订单)
|
||
```
|
||
|
||
其他定时任务 cron 通过系统属性覆盖:
|
||
- `sync.item.cron` — 商品同步 (默认 02:30)
|
||
- `sync.customer.cron` — 客户同步 (默认 02:45)
|
||
- `sync.store.cron` — 门店同步 (默认 03:00)
|
||
- `sync.refund.cron` — 退款同步 (默认 03:10)
|
||
- `sync.inventory.cron` — 库存快照 (默认 03:20)
|