# 用户端埋点需求完整方案文档

## 一、需求概述

为 alien-store 模块的用户端实现完整的埋点系统，用于统计和分析用户行为数据，并通过AI提供智能推荐服务。

### 1.1 埋点数据类型

根据原型图，需要收集以下类型的数据：

#### 1.1.1 流量数据
- 店铺搜索量
- 浏览量
- 访客数
- 新增访客数
- 访问时长
- 平均访问时长

#### 1.1.2 互动数据
- 店铺收藏次数
- 店铺分享次数
- 店铺打卡次数
- 咨询商家次数
- 好友数量
- 关注数量
- 粉丝数量
- 发布动态数量
- 动态点赞数量
- 动态评论数量
- 动态转发数量
- 被举报次数
- 被拉黑次数

#### 1.1.3 优惠券数据
- 赠送好友数量
- 赠送好友金额合计
- 赠送好友使用数量
- 赠送好友使用金额合计
- 赠送好友使用金额占比
- 好友赠送数量
- 好友赠送金额合计
- 好友赠送使用数量
- 好友赠送使用金额合计
- 好友赠送使用金额占比

#### 1.1.4 代金券数据
- 赠送好友数量
- 赠送好友金额合计
- 赠送好友使用数量
- 赠送好友使用金额合计
- 赠送好友使用金额占比
- 好友赠送数量
- 好友赠送金额合计
- 好友赠送使用数量
- 好友赠送使用金额合计
- 好友赠送使用金额占比

#### 1.1.5 服务质量数据
- 店铺评分
- 评分1
- 评分2
- 评分3
- 评价数量
- 好评数量
- 中评数量
- 差评数量
- 差评占比
- 差评申诉次数
- 差评申诉成功次数
- 差评申诉成功占比

#### 1.1.6 价目表排名数据
- 价目表浏览量
- 价目表访客数
- 价目表分享数

## 二、技术架构

### 2.1 架构设计

```
前端 (客户端)
  ↓ HTTP请求 / WebSocket消息
Controller / WebSocketProcess (埋点触发)
  ↓ 异步写入
Redis List (消息队列)
  ↓ 定时任务批量消费
数据库 (MySQL)
  ↓ 统计分析
统计查询接口
  ↓ AI分析
AI推荐服务
```

### 2.2 核心组件

1. **埋点注解** (`@TrackEvent`): 标注需要埋点的HTTP接口方法
2. **AOP切面** (`TrackEventAspect`): 拦截标注的方法，自动收集数据
3. **WebSocket处理** (`WebSocketProcess`): 处理WebSocket消息时触发埋点
4. **Redis List**: 作为消息队列，异步存储埋点数据
5. **消费服务** (`TrackEventConsumer`): 定时从Redis List批量消费数据并写入数据库
6. **前端接口** (`TrackEventController`): 提供前端主动上报埋点和手动触发统计的接口
7. **统计接口** (`BusinessDataController`): 提供经营数据统计查询
8. **AI推荐接口** (`AIRecoveryController`): 基于埋点数据提供AI推荐

### 2.3 埋点方式

系统支持三种埋点方式：

| 方式 | 说明 | 适用场景 |
|-----|------|---------|
| `@TrackEvent`注解 | AOP自动拦截，无侵入式 | 标准HTTP接口 |
| WebSocket埋点 | 在WebSocket消息处理中主动记录 | 实时消息场景（咨询、分享） |
| 前端主动上报 | 通过`/track/event`接口上报 | 前端特有行为（浏览时长等） |

## 三、数据库表设计

### 3.1 埋点事件主表 (store_track_event)

```sql
CREATE TABLE `store_track_event` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `event_type` varchar(50) NOT NULL COMMENT '事件类型(VIEW-浏览,SEARCH-搜索,COLLECT-收藏,SHARE-分享,CHECKIN-打卡,CONSULT-咨询,FOLLOW-关注,UNFOLLOW-取消关注,FRIEND_ADD-添加好友,POST_PUBLISH-发布动态,POST_LIKE-动态点赞,POST_COMMENT-动态评论,POST_REPOST-动态转发,REPORT-举报,BLOCK-拉黑,COUPON_GIVE-赠送优惠券,COUPON_USE-使用优惠券,VOUCHER_GIVE-赠送代金券,VOUCHER_USE-使用代金券,PRICE_VIEW-价目表浏览,PRICE_SHARE-价目表分享,RATING-评价,APPEAL-申诉)',
  `event_category` varchar(50) NOT NULL COMMENT '事件分类(TRAFFIC-流量数据,INTERACTION-互动数据,COUPON-优惠券,VOUCHER-代金券,SERVICE-服务质量,PRICE-价目表)',
  `user_id` int(11) DEFAULT NULL COMMENT '用户ID',
  `store_id` int(11) DEFAULT NULL COMMENT '店铺ID',
  `target_id` int(11) DEFAULT NULL COMMENT '目标对象ID(如价目表ID、动态ID等)',
  `target_type` varchar(50) DEFAULT NULL COMMENT '目标对象类型(PRICE-价目表,POST-动态,STORE-店铺等)',
  `event_data` text COMMENT '事件附加数据(JSON格式)',
  `amount` decimal(10,2) DEFAULT NULL COMMENT '金额(用于优惠券、代金券等)',
  `duration` bigint(20) DEFAULT NULL COMMENT '时长(毫秒,用于访问时长等)',
  `ip_address` varchar(50) DEFAULT NULL COMMENT 'IP地址',
  `user_agent` varchar(500) DEFAULT NULL COMMENT '用户代理',
  `device_type` varchar(20) DEFAULT NULL COMMENT '设备类型(IOS,ANDROID,WEB)',
  `app_version` varchar(20) DEFAULT NULL COMMENT 'APP版本号',
  `event_time` datetime NOT NULL COMMENT '事件发生时间',
  `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `delete_flag` int(1) NOT NULL DEFAULT '0' COMMENT '删除标记(0:未删除,1:已删除)',
  PRIMARY KEY (`id`),
  KEY `idx_store_id` (`store_id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_event_type` (`event_type`),
  KEY `idx_event_category` (`event_category`),
  KEY `idx_event_time` (`event_time`),
  KEY `idx_store_event_time` (`store_id`,`event_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='埋点事件表';
```

### 3.2 埋点统计数据表 (store_track_statistics)

用于存储按店铺、日期聚合的统计数据，提升查询性能：

```sql
CREATE TABLE `store_track_statistics` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `store_id` int(11) NOT NULL COMMENT '店铺ID',
  `stat_date` date NOT NULL COMMENT '统计日期',
  `stat_type` varchar(50) NOT NULL COMMENT '统计类型(DAILY-日统计,WEEKLY-周统计,MONTHLY-月统计)',
  `traffic_data` text COMMENT '流量数据(JSON格式)',
  `interaction_data` text COMMENT '互动数据(JSON格式)',
  `coupon_data` text COMMENT '优惠券数据(JSON格式)',
  `voucher_data` text COMMENT '代金券数据(JSON格式)',
  `service_data` text COMMENT '服务质量数据(JSON格式)',
  `price_ranking_data` text COMMENT '价目表排名数据(JSON格式)',
  `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_store_date_type` (`store_id`,`stat_date`,`stat_type`),
  KEY `idx_store_id` (`store_id`),
  KEY `idx_stat_date` (`stat_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='埋点统计表';
```

## 四、后端实现

### 4.1 埋点注解 (@TrackEvent)

定义在 `alien-store/src/main/java/shop/alien/store/annotation/TrackEvent.java`

```java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TrackEvent {
    String eventType();           // 事件类型
    String eventCategory();       // 事件分类
    String storeId() default "";  // 店铺ID的SpEL表达式
    String targetId() default ""; // 目标对象ID的SpEL表达式
    String targetType() default "";// 目标对象类型
    String userId() default "";   // 用户ID的SpEL表达式
    boolean async() default true; // 是否异步执行
}
```

### 4.2 AOP切面实现

定义在 `alien-store/src/main/java/shop/alien/store/aspect/TrackEventAspect.java`

**主要功能**：
- 拦截带有`@TrackEvent`注解的方法
- 使用SpEL表达式从方法参数或返回值中提取数据
- 自动获取IP地址、User-Agent、设备类型等信息
- 支持业务逻辑兜底查询storeId（适用于SpEL无法直接获取的场景）

### 4.3 WebSocket埋点实现

定义在 `alien-store/src/main/java/shop/alien/store/config/WebSocketProcess.java`

**支持的WebSocket埋点**：

| 事件类型 | 触发条件 | 说明 |
|---------|---------|------|
| CONSULT | receiverId以`store_`开头的普通消息 | 用户咨询店铺 |
| SHARE | 消息type为"3"(链接分享)或"14"(人员分享) | 用户分享店铺 |

**WebSocket配置**：
- `WebSocketConfig.java`: 配置WebSocket并提供自定义Configurator
- `WebSocketConfigurator`: 在握手阶段获取IP地址和User-Agent

### 4.4 Redis List 异步存储

使用现有的 `BaseRedisService` 的 `setListRight` 方法将埋点数据写入Redis List

**Redis Key**:
- 埋点队列: `track:event:queue`
- 消费锁: `track:event:consumer:lock`

### 4.5 定时任务消费

定义在 `alien-store/src/main/java/shop/alien/store/service/TrackEventConsumer.java`

使用 `@Scheduled` 注解定时从Redis List批量取出数据并写入数据库

**消费策略**：
- 消费频率: 每10秒执行一次
- 使用分布式锁防止多实例重复消费
- 批量保存到数据库

### 4.6 前端上报接口

定义在 `alien-store/src/main/java/shop/alien/store/controller/TrackEventController.java`

## 五、埋点接口清单

### 5.1 HTTP接口埋点（16个）

#### 流量数据（TRAFFIC）- 1个

| 接口路径 | 方法名 | 事件类型 |
|---------|--------|---------|
| `/aiSearch/search` | search | SEARCH |

#### 互动数据（INTERACTION）- 9个

| 接口路径 | 方法名 | 事件类型 |
|---------|--------|---------|
| `/collect/addCollect` | addCollect | COLLECT |
| `/storeClockIn/addStoreClockIn` | addStoreClockIn | CHECKIN |
| `/renovation/requirement/consultRequirement` | consultRequirement | CONSULT |
| `/userDynamics/addOrUpdate` | addOrUpdate | POST_PUBLISH |
| `/userDynamics/addTransferCount` | addTransferCount | POST_REPOST |
| `/comment/like` | like | POST_LIKE |
| `/commonComment/addComment` | addComment | POST_COMMENT |
| `/user-violation/reporting` | reporting | REPORT |
| `/life-blacklist/blackList` | blackList | BLOCK |

#### 服务质量（SERVICE）- 2个

| 接口路径 | 方法名 | 事件类型 |
|---------|--------|---------|
| `/commonRating/addRating` | add | RATING_ADD |
| `/storeCommentAppeal/addAppealNew` | addAppealNew | APPEAL |

#### 价目表（PRICE）- 2个

| 接口路径 | 方法名 | 事件类型 |
|---------|--------|---------|
| `/store/price/getById` | getById | PRICE_VIEW |
| `/store/cuisine/getByCuisineType` | getByCuisineType | PRICE_VIEW |

#### 优惠券（COUPON）- 2个

| 接口路径 | 方法名 | 事件类型 |
|---------|--------|---------|
| `/life-discount-coupon-store-friend/setFriendCoupon` | setFriendCoupon | COUPON_GIVE |
| `/coupon/verify` | verify | COUPON_USE |

### 5.2 WebSocket埋点（2个）

| 触发场景 | 消息类型 | 事件类型 | 说明 |
|---------|---------|---------|------|
| 用户咨询店铺 | WebSocket消息 | CONSULT | receiverId以store_开头时触发 |
| 用户分享店铺 | type="3"或"14" | SHARE | 从消息内容中解析storeId |

### 5.3 统计汇总

- **总埋点数**: 18个
- **HTTP接口**: 16个
- **WebSocket埋点**: 2个

## 六、前端联调

### 6.1 前端主动调用埋点上报接口

**接口路径**: `POST /track/event`

**接口说明**: 前端主动上报埋点数据

**请求参数**:
```json
{
  "eventType": "VIEW",
  "eventCategory": "TRAFFIC",
  "storeId": 1001,
  "targetId": 2001,
  "targetType": "PRICE",
  "eventData": "{}",
  "amount": 100.00,
  "duration": 3000
}
```

**响应示例**:
```json
{
  "code": 200,
  "success": true,
  "msg": "上报成功",
  "data": null
}
```

#### 6.2 手动触发统计接口（测试用）

**接口路径**: `POST /track/statistics/calculate`

**接口说明**: 手动触发统计数据计算

**请求参数**:
- `storeId`: 店铺ID (必填)
- `statDate`: 统计日期 (格式: yyyy-MM-dd)
- `statType`: 统计类型 (DAILY/WEEKLY/MONTHLY)

**响应示例**:
```json
{
  "code": 200,
  "success": true,
  "msg": "统计数据计算成功",
  "data": null
}
```

## 七、事件类型枚举

```java
public enum EventType {
    // 流量数据
    VIEW("VIEW", "浏览"),
    SEARCH("SEARCH", "搜索"),
    
    // 互动数据
    COLLECT("COLLECT", "收藏"),
    SHARE("SHARE", "分享"),
    CHECKIN("CHECKIN", "打卡"),
    CONSULT("CONSULT", "咨询"),
    FOLLOW("FOLLOW", "关注"),
    UNFOLLOW("UNFOLLOW", "取消关注"),
    FRIEND_ADD("FRIEND_ADD", "添加好友"),
    POST_PUBLISH("POST_PUBLISH", "发布动态"),
    POST_LIKE("POST_LIKE", "动态点赞"),
    POST_COMMENT("POST_COMMENT", "动态评论"),
    POST_REPOST("POST_REPOST", "动态转发"),
    REPORT("REPORT", "举报"),
    BLOCK("BLOCK", "拉黑"),
    
    // 优惠券
    COUPON_GIVE("COUPON_GIVE", "赠送优惠券"),
    COUPON_USE("COUPON_USE", "使用优惠券"),
    
    // 代金券
    VOUCHER_GIVE("VOUCHER_GIVE", "赠送代金券"),
    VOUCHER_USE("VOUCHER_USE", "使用代金券"),
    
    // 价目表
    PRICE_VIEW("PRICE_VIEW", "价目表浏览"),
    PRICE_SHARE("PRICE_SHARE", "价目表分享"),
    
    // 服务质量
    RATING_ADD("RATING_ADD", "添加评价"),
    APPEAL("APPEAL", "申诉");
}
```

## 八、统计数据说明

### 8.1 数据统计规则

| 数据类型 | 统计规则 | 说明 |
|---------|---------|------|
| 大部分数据 | **累计统计** | 统计截止到统计日期的所有数据 |
| 新增访客数 | **增量统计** | 统计周期内的新增访客（排除之前访问过的用户） |

### 8.2 统计时间范围计算

| 统计类型 | 开始时间 | 结束时间 |
|---------|---------|---------|
| DAILY | statDate 00:00:00 | statDate+1 00:00:00 |
| WEEKLY | statDate所在周的周一 00:00:00 | 周日+1 00:00:00 |
| MONTHLY | statDate所在月的1号 00:00:00 | 下月1号 00:00:00 |

### 8.3 JSON格式说明

详见：[埋点统计数据JSON格式说明.md](./埋点统计数据JSON格式说明.md)

## 九、部署和运维

### 9.1 配置项

- Redis List最大长度: 100000
- 批量消费大小: 100
- 消费间隔: 10秒
- 统计数据保留期: 2年

### 9.2 监控指标

- Redis List长度
- 消费延迟
- 消费失败率
- 统计查询响应时间

### 9.3 Maven编译配置

确保pom.xml中配置了`-parameters`参数，以保留方法参数名称（SpEL表达式需要）：

```xml
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <parameters>true</parameters>
    </configuration>
</plugin>
```

## 十、注意事项

1. **埋点数据量可能很大**，需要定期清理历史数据
2. **Redis List需要设置最大长度**，防止内存溢出
3. **消费服务需要异常处理和重试机制**
4. **统计数据建议使用定时任务预计算**，提升查询性能
5. **AI推荐接口需要缓存**，避免频繁调用AI服务
6. **WebSocket埋点通过握手阶段获取IP和User-Agent**，需要配置自定义Configurator
7. **SpEL表达式无法直接获取storeId时**，切面会通过业务逻辑兜底查询

---

**文档版本**：v2.0  
**最后更新**：2026-01-24
