Browse Source

feat(tracking): 添加埋点功能并实现页面浏览和点击事件上报

实现埋点功能,包括:
1. 创建埋点工具类 utils/tracking.ts
2. 在所有页面添加页面浏览埋点
3. 为关键交互元素添加点击事件埋点
4. 更新埋点规划文档 tracking_plan.md
master
kola-web 1 day ago
parent
commit
4d593ce5ea
  1. 566
      .trae/documents/tracking_plan.md
  2. 4
      src/doctor/pages/article/index.ts
  3. 6
      src/doctor/pages/articleList/index.ts
  4. 3
      src/doctor/pages/changeNickname/index.ts
  5. 4
      src/doctor/pages/changeTel/index.ts
  6. 21
      src/doctor/pages/home/index.ts
  7. 2
      src/doctor/pages/home/index.wxml
  8. 4
      src/doctor/pages/invite/index.ts
  9. 12
      src/doctor/pages/login/index.ts
  10. 10
      src/doctor/pages/loginForm/index.ts
  11. 8
      src/doctor/pages/my/index.ts
  12. 24
      src/doctor/pages/patientList/index.ts
  13. 10
      src/doctor/pages/stat/index.ts
  14. 3
      src/ground/pages/changeNickname/index.ts
  15. 5
      src/ground/pages/changeTel/index.ts
  16. 34
      src/ground/pages/home/index.ts
  17. 2
      src/ground/pages/home/index.wxml
  18. 4
      src/ground/pages/invite/index.ts
  19. 12
      src/ground/pages/login/index.ts
  20. 8
      src/ground/pages/my/index.ts
  21. 8
      src/ground/pages/pharmacist/index.ts
  22. 5
      src/ground/pages/stat/index.ts
  23. 16
      src/pages/index/index.ts
  24. 2
      src/pages/start/index.ts
  25. 5
      src/pages/tourists/index.ts
  26. 7
      src/pages/work/index.ts
  27. 5
      src/privacy/pages/policy/index.ts
  28. 4
      src/privacy/pages/policy1/index.ts
  29. 39
      src/utils/tracking.ts

566
.trae/documents/tracking_plan.md

@ -0,0 +1,566 @@
# 小程序埋点规划文档
## 一、项目概述
本项目是一个基于微信小程序的药品查询应用,包含三个主要角色端:
* **患者端** (pages/): 患者用户访问
* **地推端** (ground/): 邀约专员使用
* **店员端** (doctor/): 药店工作人员使用
***
## 二、页面结构梳理
### 2.1 主包页面 (pages/)
| 页面路径 | 页面名称 | 说明 |
| -------------------- | ------ | ---------------- |
| pages/start/index | 启动页 | 应用入口,处理扫码参数和身份跳转 |
| pages/tourists/index | 游客页 | 未登录用户选择身份入口 |
| pages/work/index | 工作人员入口 | 选择地推/店员/患者身份 |
| pages/index/index | 患者首页 | 患者主页面,项目选择、适应症选择 |
### 2.2 地推端分包 (ground/)
| 页面路径 | 页面名称 | 说明 |
| --------------------------------- | ----- | ------------ |
| ground/pages/login/index | 地推登录 | 地推人员登录/注册 |
| ground/pages/home/index | 地推首页 | 数据统计看板、图表展示 |
| ground/pages/pharmacist/index | 店员列表 | 邀约的店员列表及搜索筛选 |
| ground/pages/my/index | 地推我的 | 个人信息、设置 |
| ground/pages/invite/index | 地推邀约码 | 专属邀约二维码展示 |
| ground/pages/stat/index | 邀约明细 | 详细统计数据 |
| ground/pages/changeNickname/index | 修改姓名 | 修改地推人员姓名 |
| ground/pages/changeTel/index | 修改手机号 | 修改地推人员手机号 |
### 2.3 店员端分包 (doctor/)
| 页面路径 | 页面名称 | 说明 |
| --------------------------------- | ----- | ------------ |
| doctor/pages/login/index | 店员登录 | 店员登录/注册第一步 |
| doctor/pages/loginForm/index | 店员注册 | 店员注册表单 |
| doctor/pages/home/index | 店员首页 | 数据统计看板、待处理事项 |
| doctor/pages/patientList/index | 患者列表 | 邀约的患者列表及状态管理 |
| doctor/pages/articleList/index | 教育列表 | 健康教育文章列表 |
| doctor/pages/article/index | 文章详情 | 教育文章详情 |
| doctor/pages/my/index | 店员我的 | 个人信息、设置 |
| doctor/pages/invite/index | 店员邀约码 | 专属邀约二维码展示 |
| doctor/pages/stat/index | 邀约明细 | 详细统计数据 |
| doctor/pages/changeNickname/index | 修改姓名 | 修改店员姓名 |
| doctor/pages/changeTel/index | 修改手机号 | 修改店员手机号 |
### 2.4 隐私协议分包 (privacy/)
| 页面路径 | 页面名称 | 说明 |
| --------------------------- | ---- | ----------- |
| privacy/pages/policy/index | 隐私政策 | 个人信息及隐私保护政策 |
| privacy/pages/policy1/index | 用户协议 | 用户与隐私保护协议 |
***
## 三、埋点事件规划
### 3.1 页面浏览埋点 (Page View)
所有页面都需要在 `onLoad``onShow` 中上报页面浏览事件。
| pageName 编码 | 页面路径 | 说明 |
| ----------------------------- | --------------------------------- | ------- |
| **患者端** | <br /> | <br /> |
| patient\_start\_view | pages/start/index | 启动页 |
| patient\_tourists\_view | pages/tourists/index | 游客页 |
| patient\_work\_view | pages/work/index | 工作人员入口 |
| patient\_home\_view | pages/index/index | 患者首页 |
| **地推端** | <br /> | <br /> |
| ground\_login\_view | ground/pages/login/index | 地推登录 |
| ground\_home\_view | ground/pages/home/index | 地推首页 |
| ground\_pharmacist\_view | ground/pages/pharmacist/index | 店员列表 |
| ground\_my\_view | ground/pages/my/index | 地推我的 |
| ground\_invite\_view | ground/pages/invite/index | 地推邀约码 |
| ground\_stat\_view | ground/pages/stat/index | 地推邀约明细 |
| ground\_change\_name\_view | ground/pages/changeNickname/index | 地推修改姓名 |
| ground\_change\_tel\_view | ground/pages/changeTel/index | 地推修改手机号 |
| **店员端** | <br /> | <br /> |
| doctor\_login\_view | doctor/pages/login/index | 店员登录 |
| doctor\_register\_view | doctor/pages/loginForm/index | 店员注册 |
| doctor\_home\_view | doctor/pages/home/index | 店员首页 |
| doctor\_patient\_view | doctor/pages/patientList/index | 患者列表 |
| doctor\_article\_view | doctor/pages/articleList/index | 教育列表 |
| doctor\_article\_detail\_view | doctor/pages/article/index | 文章详情 |
| doctor\_my\_view | doctor/pages/my/index | 店员我的 |
| doctor\_invite\_view | doctor/pages/invite/index | 店员邀约码 |
| doctor\_stat\_view | doctor/pages/stat/index | 店员邀约明细 |
| doctor\_change\_name\_view | doctor/pages/changeNickname/index | 店员修改姓名 |
| doctor\_change\_tel\_view | doctor/pages/changeTel/index | 店员修改手机号 |
| **隐私协议** | <br /> | <br /> |
| privacy\_policy\_view | privacy/pages/policy/index | 隐私政策 |
| user\_agreement\_view | privacy/pages/policy1/index | 用户协议 |
***
### 3.2 点击事件埋点 (Click Event)
#### 3.2.1 启动页 (pages/start/index)
| pageName 编码 | 触发元素 | 说明 |
| --------------------------- | ---- | ----------- |
| patient\_start\_scan\_click | 扫码进入 | 用户通过扫码进入小程序 |
#### 3.2.2 游客页 (pages/tourists/index)
| 事件名 | 触发元素 | 说明 |
| --------------------------- | ---------- | ------- |
| click\_tourists\_pharmacist | "我是药店工作人员" | 跳转店员登录 |
| click\_tourists\_promoter | "我是地推人员" | 跳转地推登录 |
| click\_avatar\_upload | 头像选择 | 选择/上传头像 |
| click\_nickname\_save | 昵称输入框失焦 | 保存昵称 |
#### 3.2.3 工作人员入口 (pages/work/index)
| 事件名 | 触发元素 | 说明 |
| -------------------- | ---------- | ------ |
| click\_work\_ground | "我是邀约专员"卡片 | 进入地推登录 |
| click\_work\_doctor | "我是店员"卡片 | 进入店员登录 |
| click\_work\_patient | "我是患者"按钮 | 进入患者端 |
#### 3.2.4 患者首页 (pages/index/index)
| 事件名 | 触发元素 | 说明 |
| ---------------------------------- | ------------ | --------- |
| click\_patient\_project\_switch | 项目切换picker | 切换当前项目 |
| click\_patient\_avatar | 头像选择按钮 | 选择/上传头像 |
| click\_patient\_nickname\_save | 昵称输入框 | 保存昵称 |
| click\_patient\_indication\_select | 适应症选项 | 选择适应症并登录 |
| click\_patient\_agreement\_toggle | 协议同意checkbox | 切换协议同意状态 |
| click\_patient\_agreement\_view | 《用户与隐私保护协议》 | 查看用户协议 |
| click\_patient\_work\_entry | "我是工作人员" | 进入工作人员入口 |
| click\_patient\_jump\_miniprogram | "去腾讯药箱看看" | 跳转腾讯药箱小程序 |
#### 3.2.5 地推登录页 (ground/pages/login/index)
| 事件名 | 触发元素 | 说明 |
| --------------------------------- | ------------- | -------- |
| click\_ground\_login\_wx | "手机号快捷登录"按钮 | 微信一键登录 |
| click\_ground\_login\_sms\_switch | "使用手机号验证码" | 切换验证码登录 |
| click\_ground\_login\_sms\_code | "发送验证码" | 发送短信验证码 |
| click\_ground\_login\_submit | "立即加入"按钮 | 验证码登录提交 |
| click\_ground\_login\_agreement | 协议勾选 | 切换协议同意状态 |
| click\_ground\_login\_privacy | 《个人信息及隐私保护政策》 | 查看隐私政策 |
| click\_ground\_login\_patient | "我是患者" | 切换到患者端 |
#### 3.2.6 地推首页 (ground/pages/home/index)
| 事件名 | 触发元素 | 说明 |
| -------------------------------------- | ---------- | --------- |
| click\_ground\_home\_project\_switch | 项目切换picker | 切换项目 |
| click\_ground\_home\_invite\_code | 右上角邀约码图标 | 查看邀约码 |
| click\_ground\_home\_fold1 | "累计邀约"折叠 | 展开/收起累计数据 |
| click\_ground\_home\_fold2 | "邀约患者统计"折叠 | 展开/收起日度数据 |
| click\_ground\_home\_stat\_type\_day | "日统计"切换 | 切换到日统计 |
| click\_ground\_home\_stat\_type\_month | "月统计"切换 | 切换到月统计 |
| click\_ground\_home\_date\_picker | 日期选择器 | 选择统计日期 |
| click\_ground\_home\_date\_prev | 日期左箭头 | 上一天/上月 |
| click\_ground\_home\_date\_next | 日期右箭头 | 下一天/下月 |
| click\_ground\_home\_chart1\_start | 图表1开始日期 | 选择图表开始日期 |
| click\_ground\_home\_chart1\_end | 图表1结束日期 | 选择图表结束日期 |
| click\_ground\_home\_chart2\_start | 图表2开始日期 | 选择图表开始日期 |
| click\_ground\_home\_chart2\_end | 图表2结束日期 | 选择图表结束日期 |
| click\_ground\_home\_chart3\_start | 图表3开始日期 | 选择图表开始日期 |
| click\_ground\_home\_chart3\_end | 图表3结束日期 | 选择图表结束日期 |
| click\_ground\_home\_detail | "查看明细"按钮 | 进入邀约明细 |
#### 3.2.7 地推店员列表 (ground/pages/pharmacist/index)
| 事件名 | 触发元素 | 说明 |
| ------------------------------------------ | ---------- | ------- |
| click\_ground\_pharmacist\_project\_switch | 项目切换picker | 切换项目 |
| click\_ground\_pharmacist\_search | 搜索框 | 搜索店员/药店 |
| click\_ground\_pharmacist\_start\_date | 开始时间picker | 选择开始时间 |
| click\_ground\_pharmacist\_end\_date | 结束时间picker | 选择结束时间 |
| click\_ground\_pharmacist\_card | 店员卡片 | 查看店员详情 |
#### 3.2.8 地推我的页 (ground/pages/my/index)
| 事件名 | 触发元素 | 说明 |
| --------------------------- | ------- | -------- |
| click\_ground\_my\_avatar | 头像区域 | 修改头像 |
| click\_ground\_my\_nickname | "修改姓名" | 进入修改姓名页 |
| click\_ground\_my\_tel | "修改手机号" | 进入修改手机号页 |
| click\_ground\_my\_invite | "我的邀约码" | 查看邀约码 |
| click\_ground\_my\_exit | "退出登录" | 退出登录 |
#### 3.2.9 地推邀约码 (ground/pages/invite/index)
| 事件名 | 触发元素 | 说明 |
| --------------------------- | ----- | -------- |
| click\_ground\_invite\_save | 二维码区域 | 保存二维码到相册 |
#### 3.2.10 地推邀约明细 (ground/pages/stat/index)
| 事件名 | 触发元素 | 说明 |
| -------------------------------- | ---------- | ------ |
| click\_ground\_stat\_start\_date | 开始日期picker | 选择开始日期 |
| click\_ground\_stat\_end\_date | 结束日期picker | 选择结束日期 |
#### 3.2.11 店员登录页 (doctor/pages/login/index)
| 事件名 | 触发元素 | 说明 |
| --------------------------------- | ------------- | -------- |
| click\_doctor\_login\_wx | "手机号快捷登录"按钮 | 微信一键登录 |
| click\_doctor\_login\_sms\_switch | "使用手机号验证码" | 切换验证码登录 |
| click\_doctor\_login\_sms\_code | "发送验证码" | 发送短信验证码 |
| click\_doctor\_login\_submit | "立即加入"按钮 | 验证码登录提交 |
| click\_doctor\_login\_agreement | 协议勾选 | 切换协议同意状态 |
| click\_doctor\_login\_privacy | 《个人信息及隐私保护政策》 | 查看隐私政策 |
| click\_doctor\_login\_patient | "我是患者" | 切换到患者端 |
#### 3.2.12 店员注册页 (doctor/pages/loginForm/index)
| 事件名 | 触发元素 | 说明 |
| ----------------------------------------- | ---------- | -------- |
| click\_doctor\_register\_name\_input | 姓名输入框 | 输入姓名 |
| click\_doctor\_register\_pharmacy | 所属药店选择 | 打开药店选择弹窗 |
| click\_doctor\_register\_project | 项目选择picker | 选择项目 |
| click\_doctor\_register\_submit | "立即加入店员端" | 提交注册 |
| click\_doctor\_register\_pharmacy\_search | 药店搜索框 | 搜索药店 |
| click\_doctor\_register\_area\_picker | 省市区选择 | 选择省市区 |
| click\_doctor\_register\_pharmacy\_select | 药店列表项 | 选择药店 |
#### 3.2.13 店员首页 (doctor/pages/home/index)
| 事件名 | 触发元素 | 说明 |
| -------------------------------------- | ---------- | --------- |
| click\_doctor\_home\_project\_switch | 项目切换picker | 切换项目 |
| click\_doctor\_home\_invite\_code | 右上角邀约码图标 | 查看邀约码 |
| click\_doctor\_home\_fold1 | "累计邀约"折叠 | 展开/收起累计数据 |
| click\_doctor\_home\_fold2 | "邀约患者统计"折叠 | 展开/收起日度数据 |
| click\_doctor\_home\_stat\_type\_day | "日统计"切换 | 切换到日统计 |
| click\_doctor\_home\_stat\_type\_month | "月统计"切换 | 切换到月统计 |
| click\_doctor\_home\_date\_picker | 日期选择器 | 选择统计日期 |
| click\_doctor\_home\_date\_prev | 日期左箭头 | 上一天/上月 |
| click\_doctor\_home\_date\_next | 日期右箭头 | 下一天/下月 |
| click\_doctor\_home\_chart\_start | 图表开始日期 | 选择图表开始日期 |
| click\_doctor\_home\_chart\_end | 图表结束日期 | 选择图表结束日期 |
| click\_doctor\_home\_detail | "查看明细"按钮 | 进入邀约明细 |
#### 3.2.14 店员患者列表 (doctor/pages/patientList/index)
| 事件名 | 触发元素 | 说明 |
| ---------------------------------------- | ---------- | -------- |
| click\_doctor\_patient\_project\_switch | 项目切换picker | 切换项目 |
| click\_doctor\_patient\_search | 搜索框 | 搜索患者 |
| click\_doctor\_patient\_jump\_status | 跳转状态picker | 筛选跳转状态 |
| click\_doctor\_patient\_enroll\_status | 入组状态picker | 筛选入组状态 |
| click\_doctor\_patient\_jump\_start | 跳转开始时间 | 选择跳转开始时间 |
| click\_doctor\_patient\_jump\_end | 跳转结束时间 | 选择跳转结束时间 |
| click\_doctor\_patient\_enroll\_start | 入组开始时间 | 选择入组开始时间 |
| click\_doctor\_patient\_enroll\_end | 入组结束时间 | 选择入组结束时间 |
| click\_doctor\_patient\_preview | "查看提交材料" | 预览材料图片 |
| click\_doctor\_patient\_upload\_jump | "提交"跳转材料 | 上传跳转材料 |
| click\_doctor\_patient\_upload\_enroll | "提交"入组材料 | 上传入组材料 |
| click\_doctor\_patient\_reupload\_jump | "重新提交"跳转 | 重新上传跳转材料 |
| click\_doctor\_patient\_reupload\_enroll | "重新提交"入组 | 重新上传入组材料 |
#### 3.2.15 教育列表 (doctor/pages/articleList/index)
| 事件名 | 触发元素 | 说明 |
| ------------------------------ | -------- | -------- |
| click\_doctor\_article\_tab | 分类tab | 切换文章分类 |
| click\_doctor\_article\_banner | Banner轮播 | 点击Banner |
| click\_doctor\_article\_card | 文章卡片 | 查看文章详情 |
| click\_doctor\_article\_like | 点赞按钮 | 点赞文章 |
#### 3.2.16 文章详情 (doctor/pages/article/index)
| 事件名 | 触发元素 | 说明 |
| ------------------------------------ | ---- | ---- |
| click\_doctor\_article\_detail\_like | 点赞按钮 | 点赞文章 |
#### 3.2.17 店员我的页 (doctor/pages/my/index)
| 事件名 | 触发元素 | 说明 |
| --------------------------- | ------- | -------- |
| click\_doctor\_my\_avatar | 头像区域 | 修改头像 |
| click\_doctor\_my\_nickname | "修改姓名" | 进入修改姓名页 |
| click\_doctor\_my\_tel | "修改手机号" | 进入修改手机号页 |
| click\_doctor\_my\_invite | "我的邀约码" | 查看邀约码 |
| click\_doctor\_my\_exit | "退出登录" | 退出登录 |
#### 3.2.18 店员邀约码 (doctor/pages/invite/index)
| 事件名 | 触发元素 | 说明 |
| --------------------------- | ----- | -------- |
| click\_doctor\_invite\_save | 二维码区域 | 保存二维码到相册 |
#### 3.2.19 店员邀约明细 (doctor/pages/stat/index)
| 事件名 | 触发元素 | 说明 |
| -------------------------------- | ---------- | ------ |
| click\_doctor\_stat\_type\_day | "日统计"切换 | 切换到日统计 |
| click\_doctor\_stat\_type\_month | "月统计"切换 | 切换到月统计 |
| click\_doctor\_stat\_start\_date | 开始日期picker | 选择开始日期 |
| click\_doctor\_stat\_end\_date | 结束日期picker | 选择结束日期 |
***
## 四、埋点事件汇总
### 4.1 事件类型统计
| 事件类型 | 事件数量 | 说明 |
| ------------ | -------- | ------- |
| 页面浏览 (view) | 25 | 所有页面 |
| 点击事件 (click) | 115+ | 所有可点击元素 |
| **总计** | **140+** | - |
### 4.2 用户类型定义
```typescript
enum UserType {
PATIENT = 2, // 患者
PROMOTER = 3, // 地推/邀约专员
PHARMACIST = 4, // 店员
}
```
### 4.3 页面名称映射
```typescript
const PageNameMap = {
// 患者端
'pages/start/index': '启动页',
'pages/tourists/index': '游客页',
'pages/work/index': '工作人员入口',
'pages/index/index': '患者首页',
// 地推端
'ground/pages/login/index': '地推登录',
'ground/pages/home/index': '地推首页',
'ground/pages/pharmacist/index': '店员列表',
'ground/pages/my/index': '地推我的',
'ground/pages/invite/index': '地推邀约码',
'ground/pages/stat/index': '地推邀约明细',
'ground/pages/changeNickname/index': '地推修改姓名',
'ground/pages/changeTel/index': '地推修改手机号',
// 店员端
'doctor/pages/login/index': '店员登录',
'doctor/pages/loginForm/index': '店员注册',
'doctor/pages/home/index': '店员首页',
'doctor/pages/patientList/index': '患者列表',
'doctor/pages/articleList/index': '教育列表',
'doctor/pages/article/index': '文章详情',
'doctor/pages/my/index': '店员我的',
'doctor/pages/invite/index': '店员邀约码',
'doctor/pages/stat/index': '店员邀约明细',
'doctor/pages/changeNickname/index': '店员修改姓名',
'doctor/pages/changeTel/index': '店员修改手机号',
// 隐私协议
'privacy/pages/policy/index': '隐私政策',
'privacy/pages/policy1/index': '用户协议',
}
```
***
## 五、埋点接口规范
### 5.1 接口信息
**请求地址:** `POST /app/common/common/report-behavior`
**请求参数:**
| 参数名 | 类型 | 必填 | 说明 |
| -------- | ------ | -- | -------------- |
| pageName | string | 是 | 页面名称编码(埋点事件标识) |
### 5.2 技术实现方案
1. **创建埋点工具类** (`utils/tracking.ts`)
* 封装埋点上报方法,调用 `report-behavior` 接口
* 管理通用参数
* 处理埋点队列和批量上报
2. **页面混入 (Mixin)**
* 在页面生命周期中自动上报页面浏览事件
* 统一处理页面参数
3. **点击事件拦截**
* 使用自定义属性标记可埋点元素
* 统一监听并上报点击事件
### 5.3 代码示例
```typescript
// utils/tracking.ts
/**
* 上报用户行为埋点
* @param pageName 埋点事件标识,格式:page_action_element
*/
export function reportBehavior(pageName: string) {
const app = getApp<IAppOption>()
wx.ajax({
method: 'POST',
url: '/app/common/common/report-behavior',
data: {
pageName,
},
}).catch(() => {
// 埋点上报失败不阻塞业务流程
})
}
/**
* 页面浏览埋点
* @param pagePath 页面路径
*/
export function trackPageView(pagePath: string) {
const pageNameMap: Record<string, string> = {
// 患者端
'pages/start/index': 'patient_start_view',
'pages/tourists/index': 'patient_tourists_view',
'pages/work/index': 'patient_work_view',
'pages/index/index': 'patient_home_view',
// 地推端
'ground/pages/login/index': 'ground_login_view',
'ground/pages/home/index': 'ground_home_view',
'ground/pages/pharmacist/index': 'ground_pharmacist_view',
'ground/pages/my/index': 'ground_my_view',
'ground/pages/invite/index': 'ground_invite_view',
'ground/pages/stat/index': 'ground_stat_view',
'ground/pages/changeNickname/index': 'ground_change_name_view',
'ground/pages/changeTel/index': 'ground_change_tel_view',
// 店员端
'doctor/pages/login/index': 'doctor_login_view',
'doctor/pages/loginForm/index': 'doctor_register_view',
'doctor/pages/home/index': 'doctor_home_view',
'doctor/pages/patientList/index': 'doctor_patient_view',
'doctor/pages/articleList/index': 'doctor_article_view',
'doctor/pages/article/index': 'doctor_article_detail_view',
'doctor/pages/my/index': 'doctor_my_view',
'doctor/pages/invite/index': 'doctor_invite_view',
'doctor/pages/stat/index': 'doctor_stat_view',
'doctor/pages/changeNickname/index': 'doctor_change_name_view',
'doctor/pages/changeTel/index': 'doctor_change_tel_view',
// 隐私协议
'privacy/pages/policy/index': 'privacy_policy_view',
'privacy/pages/policy1/index': 'user_agreement_view',
}
const pageName = pageNameMap[pagePath]
if (pageName) {
reportBehavior(pageName)
}
}
/**
* 点击事件埋点
* @param eventName 事件标识
*/
export function trackClick(eventName: string) {
reportBehavior(eventName)
}
```
```typescript
// 页面中使用示例
import { trackPageView, trackClick } from '@/utils/tracking'
const app = getApp<IAppOption>()
Page({
onLoad() {
// 页面浏览埋点需要在登录后上报
app.waitLogin().then(() => {
trackPageView('pages/index/index')
})
},
handleWork() {
// 上报点击事件
trackClick('patient_home_work_click')
wx.navigateTo({
url: '/pages/work/index',
})
},
})
```
### 5.3 埋点验证清单
实施完成后,需要验证以下埋点是否正常上报:
* [ ] 所有页面的 view 事件
* [ ] 所有可点击元素的 click 事件
***
## 六、数据统计维度
### 6.1 用户行为分析
* **日活跃用户 (DAU)**:按用户类型统计
* **页面访问热度**:各页面PV/UV排名
* **用户留存率**:次日/7日/30日留存
* **使用时长**:平均使用时长、页面停留时长
### 6.2 功能使用分析
* **登录转化率**:各端登录成功率
* **项目切换频次**:用户切换项目的频率
* **功能使用分布**:各功能按钮点击率
* **搜索使用情况**:搜索功能使用频次
### 6.3 业务数据分析
* **邀约转化漏斗**:扫码 -> 注册 -> 绑定 -> 跳转 -> 入组
* **材料上传完成率**:各状态转化情况
* **内容互动数据**:文章阅读、点赞数据
* **邀约码使用**:邀约码查看、保存次数
***
## 七、附录
### 7.1 埋点事件汇总表
| 事件类型 | 事件数量 | 说明 |
| ------------ | -------- | ------- |
| 页面浏览 (view) | 25 | 所有页面 |
| 点击事件 (click) | 115+ | 所有可点击元素 |
| **总计** | **140+** | - |
### 7.2 版本记录
| 版本 | 日期 | 说明 |
| ---- | ---------- | ------ |
| v1.0 | 2026-03-10 | <br /> |

4
src/doctor/pages/article/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -14,6 +16,7 @@ Page({
onLoad(option: { id?: string }) { onLoad(option: { id?: string }) {
// 药店端文章详情页面,仅允许药店人员访问 // 药店端文章详情页面,仅允许药店人员访问
app.waitLogin({ types: [4] }).then(() => { app.waitLogin({ types: [4] }).then(() => {
trackPageView('doctor_article_detail_view')
const articleId = option.id ? Number.parseInt(option.id) : 0 const articleId = option.id ? Number.parseInt(option.id) : 0
this.setData({ articleId }) this.setData({ articleId })
@ -49,6 +52,7 @@ Page({
}, },
// 点赞(多次点赞只增加点赞数) // 点赞(多次点赞只增加点赞数)
handleLike() { handleLike() {
trackClick('click_doctor_article_detail_like')
const { articleId, articleDetail } = this.data const { articleId, articleDetail } = this.data
if (!articleId) return if (!articleId) return

6
src/doctor/pages/articleList/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -26,6 +28,7 @@ Page({
onLoad() { onLoad() {
// 药店端教育页面,仅允许药店人员访问 // 药店端教育页面,仅允许药店人员访问
app.waitLogin({ types: [4] }).then(() => { app.waitLogin({ types: [4] }).then(() => {
trackPageView('doctor_article_view')
this.getCategoryList() this.getCategoryList()
}) })
}, },
@ -118,6 +121,7 @@ Page({
}, },
// 切换分类 // 切换分类
handleTabChange(e: WechatMiniprogram.CustomEvent) { handleTabChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_article_tab')
const categoryId = e.currentTarget.dataset.id const categoryId = e.currentTarget.dataset.id
// 增加 requestId,使之前的请求失效 // 增加 requestId,使之前的请求失效
this.requestId++ this.requestId++
@ -140,6 +144,7 @@ Page({
}, },
// 查看文章详情 // 查看文章详情
handleDetail(e: WechatMiniprogram.CustomEvent) { handleDetail(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_article_card')
const { id } = e.currentTarget.dataset const { id } = e.currentTarget.dataset
wx.navigateTo({ wx.navigateTo({
url: `/doctor/pages/article/index?id=${id}`, url: `/doctor/pages/article/index?id=${id}`,
@ -147,6 +152,7 @@ Page({
}, },
// 点赞(多次点赞只增加点赞数) // 点赞(多次点赞只增加点赞数)
handleLike(e: WechatMiniprogram.CustomEvent) { handleLike(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_article_like')
const { id, index } = e.currentTarget.dataset const { id, index } = e.currentTarget.dataset
const article = this.data.articleList[index] const article = this.data.articleList[index]

3
src/doctor/pages/changeNickname/index.ts

@ -1,3 +1,5 @@
import { trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -8,6 +10,7 @@ Page({
onLoad() { onLoad() {
// 药店端修改昵称页面,仅允许药店人员访问 // 药店端修改昵称页面,仅允许药店人员访问
app.waitLogin({ types: [4] }).then(() => { app.waitLogin({ types: [4] }).then(() => {
trackPageView('doctor_change_name_view')
// 获取当前姓名 // 获取当前姓名
this.getCurrentName() this.getCurrentName()
}) })

4
src/doctor/pages/changeTel/index.ts

@ -1,3 +1,5 @@
import { trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
let timer = null as null | number let timer = null as null | number
@ -12,7 +14,7 @@ Page({
onLoad() { onLoad() {
// 药店端修改手机号页面,仅允许药店人员访问 // 药店端修改手机号页面,仅允许药店人员访问
app.waitLogin({ types: [4] }).then(() => { app.waitLogin({ types: [4] }).then(() => {
// 页面加载完成 trackPageView('doctor_change_tel_view')
}) })
}, },
onUnload() { onUnload() {

21
src/doctor/pages/home/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const echarts = require('../../../components/ec-canvas/echarts.js') const echarts = require('../../../components/ec-canvas/echarts.js')
Page({ Page({
@ -80,6 +82,7 @@ Page({
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
// 药店端页面,仅允许药店人员(4)访问 // 药店端页面,仅允许药店人员(4)访问
app.waitLogin({ types: [4] }).then(() => { app.waitLogin({ types: [4] }).then(() => {
trackPageView('doctor_home_view')
this.getUserInfo() this.getUserInfo()
this.getProjectList() this.getProjectList()
}) })
@ -160,6 +163,7 @@ Page({
// 切换项目 // 切换项目
onProjectChange(e: WechatMiniprogram.CustomEvent) { onProjectChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_home_project_switch')
const index = e.detail.value const index = e.detail.value
const project = this.data.projectList[index] const project = this.data.projectList[index]
if (project && project.projectId !== this.data.currentProjectId) { if (project && project.projectId !== this.data.currentProjectId) {
@ -299,6 +303,11 @@ Page({
// 切换统计类型 // 切换统计类型
switchStatType(e: WechatMiniprogram.CustomEvent) { switchStatType(e: WechatMiniprogram.CustomEvent) {
const type = e.currentTarget.dataset.type const type = e.currentTarget.dataset.type
if (type === 'day') {
trackClick('click_doctor_home_stat_type_day')
} else {
trackClick('click_doctor_home_stat_type_month')
}
const isMonth = type === 'month' const isMonth = type === 'month'
// 根据统计类型重置日期范围 // 根据统计类型重置日期范围
@ -344,6 +353,7 @@ Page({
// 日期选择变化 // 日期选择变化
onDateChange(e: WechatMiniprogram.CustomEvent) { onDateChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_home_date_picker')
const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM
// 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD // 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD
@ -361,6 +371,7 @@ Page({
// 切换到上一天/上月 // 切换到上一天/上月
prevDate() { prevDate() {
trackClick('click_doctor_home_date_prev')
const isMonth = this.data.statType === 'month' const isMonth = this.data.statType === 'month'
let newDate: Date let newDate: Date
let startDate: string let startDate: string
@ -387,6 +398,7 @@ Page({
// 切换到下一天/下月 // 切换到下一天/下月
nextDate() { nextDate() {
trackClick('click_doctor_home_date_next')
const isMonth = this.data.statType === 'month' const isMonth = this.data.statType === 'month'
const today = new Date() const today = new Date()
// 今天的 23:59:59,只要新日期小于等于这个时间就可以选择 // 今天的 23:59:59,只要新日期小于等于这个时间就可以选择
@ -437,6 +449,7 @@ Page({
// 图表日期选择变化(开始日期) // 图表日期选择变化(开始日期)
onChartStartDateChange(e: WechatMiniprogram.CustomEvent) { onChartStartDateChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_home_chart_start')
const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM
const chartEndDate = this.data.chartEndDate const chartEndDate = this.data.chartEndDate
@ -463,6 +476,7 @@ Page({
// 图表日期选择变化(结束日期) // 图表日期选择变化(结束日期)
onChartEndDateChange(e: WechatMiniprogram.CustomEvent) { onChartEndDateChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_home_chart_end')
const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM
const chartStartDate = this.data.chartStartDate const chartStartDate = this.data.chartStartDate
@ -624,12 +638,14 @@ Page({
}, },
handleInvite() { handleInvite() {
trackClick('click_doctor_home_invite_code')
wx.navigateTo({ wx.navigateTo({
url: '/doctor/pages/invite/index', url: '/doctor/pages/invite/index',
}) })
}, },
handleStat() { handleStat() {
trackClick('click_doctor_home_detail')
const { chartStartDate, chartEndDate, statType } = this.data const { chartStartDate, chartEndDate, statType } = this.data
wx.navigateTo({ wx.navigateTo({
url: `/doctor/pages/stat/index?startDate=${chartStartDate}&endDate=${chartEndDate}&type=${statType}`, url: `/doctor/pages/stat/index?startDate=${chartStartDate}&endDate=${chartEndDate}&type=${statType}`,
@ -638,6 +654,11 @@ Page({
handleFold(e) { handleFold(e) {
const { key } = e.currentTarget.dataset const { key } = e.currentTarget.dataset
if (key === 'fold1') {
trackClick('click_doctor_home_fold1')
} else if (key === 'fold2') {
trackClick('click_doctor_home_fold2')
}
this.setData({ this.setData({
[key]: !this.data[key], [key]: !this.data[key],
}) })

2
src/doctor/pages/home/index.wxml

@ -58,7 +58,7 @@
<van-icon class="icon" name="arrow-down" /> <van-icon class="icon" name="arrow-down" />
</view> </view>
</view> </view>
<view class="tip">截止昨日数据</view> <view class="tip">展示实时数据</view>
</view> </view>
<view class="card"> <view class="card">
<view class="row2"> <view class="row2">

4
src/doctor/pages/invite/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -17,6 +19,7 @@ Page({
onLoad() { onLoad() {
// 药店端邀约页面,仅允许药店人员访问 // 药店端邀约页面,仅允许药店人员访问
app.waitLogin({ types: [4] }).then(() => { app.waitLogin({ types: [4] }).then(() => {
trackPageView('doctor_invite_view')
// 生成小程序码(接口会返回所有需要的信息) // 生成小程序码(接口会返回所有需要的信息)
this.generateQrCode() this.generateQrCode()
}) })
@ -43,6 +46,7 @@ Page({
}, },
// 保存二维码到相册 // 保存二维码到相册
saveQrCode() { saveQrCode() {
trackClick('click_doctor_invite_save')
const { qrCodeUrl } = this.data const { qrCodeUrl } = this.data
if (!qrCodeUrl) { if (!qrCodeUrl) {
wx.showToast({ wx.showToast({

12
src/doctor/pages/login/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
let timer = null as null | number let timer = null as null | number
@ -17,7 +19,11 @@ Page({
}) })
} }
}, },
onShow() {
trackPageView('doctor_login_view')
},
getCode() { getCode() {
trackClick('click_doctor_login_sms_code')
if (timer) return if (timer) return
const mobile = this.data.mobile const mobile = this.data.mobile
if (!mobile) { if (!mobile) {
@ -64,6 +70,7 @@ Page({
}) })
}, },
handleSubmit() { handleSubmit() {
trackClick('click_doctor_login_submit')
if (!this.data.mobile) { if (!this.data.mobile) {
wx.showToast({ wx.showToast({
icon: 'none', icon: 'none',
@ -101,6 +108,7 @@ Page({
}) })
}, },
handleWxSubmit(e: WechatMiniprogram.CustomEvent) { handleWxSubmit(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_login_wx')
if (!this.data.check) { if (!this.data.check) {
wx.showToast({ wx.showToast({
icon: 'none', icon: 'none',
@ -146,21 +154,25 @@ Page({
} }
}, },
handleTelCode() { handleTelCode() {
trackClick('click_doctor_login_sms_switch')
this.setData({ this.setData({
showForm: !this.data.showForm, showForm: !this.data.showForm,
}) })
}, },
handleLink() { handleLink() {
trackClick('click_doctor_login_privacy')
wx.navigateTo({ wx.navigateTo({
url: '/privacy/pages/policy/index', url: '/privacy/pages/policy/index',
}) })
}, },
handleCheck() { handleCheck() {
trackClick('click_doctor_login_agreement')
this.setData({ this.setData({
check: !this.data.check, check: !this.data.check,
}) })
}, },
handlePatient() { handlePatient() {
trackClick('click_doctor_login_patient')
wx.restartMiniProgram({ wx.restartMiniProgram({
path: '/pages/start/index', path: '/pages/start/index',
}) })

10
src/doctor/pages/loginForm/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -43,6 +45,7 @@ Page({
}, },
}, },
onLoad() { onLoad() {
trackPageView('doctor_register_view')
// 如果通过扫码进入,存在项目ID,则回显并禁用选择 // 如果通过扫码进入,存在项目ID,则回显并禁用选择
const projectId = app.globalData.projectId const projectId = app.globalData.projectId
if (projectId) { if (projectId) {
@ -95,6 +98,7 @@ Page({
// 项目选择变化 // 项目选择变化
onProjectChange(e: WechatMiniprogram.CustomEvent) { onProjectChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_register_project')
const index = e.detail.value const index = e.detail.value
const project = this.data.projectList[index] const project = this.data.projectList[index]
this.setData({ this.setData({
@ -105,12 +109,14 @@ Page({
}, },
// 输入姓名 // 输入姓名
handleNameInput(e: WechatMiniprogram.CustomEvent) { handleNameInput(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_register_name_input')
this.setData({ this.setData({
name: e.detail.value, name: e.detail.value,
}) })
}, },
// 打开药店选择弹窗 // 打开药店选择弹窗
handleDrug() { handleDrug() {
trackClick('click_doctor_register_pharmacy')
this.setData({ this.setData({
show: true, show: true,
page: 1, page: 1,
@ -188,6 +194,7 @@ Page({
}, },
// 省市区选择变化 // 省市区选择变化
handleChange(e: WechatMiniprogram.CustomEvent) { handleChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_register_area_picker')
const [province, city, district] = e.detail const [province, city, district] = e.detail
this.setData({ this.setData({
provinceId: province?.value || '', provinceId: province?.value || '',
@ -209,6 +216,7 @@ Page({
}, },
// 搜索药店 // 搜索药店
handleSearch(e: WechatMiniprogram.CustomEvent) { handleSearch(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_register_pharmacy_search')
this.setData({ this.setData({
keyword: e.detail.value, keyword: e.detail.value,
page: 1, page: 1,
@ -228,6 +236,7 @@ Page({
}, },
// 选择药店 // 选择药店
selectPharmacy(e: WechatMiniprogram.CustomEvent) { selectPharmacy(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_register_pharmacy_select')
const { id, name } = e.currentTarget.dataset const { id, name } = e.currentTarget.dataset
this.setData({ this.setData({
pharmacyId: id, pharmacyId: id,
@ -237,6 +246,7 @@ Page({
}, },
// 提交注册 // 提交注册
handleSubmit() { handleSubmit() {
trackClick('click_doctor_register_submit')
const { name, pharmacyId, projectId, projectDisabled } = this.data const { name, pharmacyId, projectId, projectDisabled } = this.data
if (!name.trim()) { if (!name.trim()) {

8
src/doctor/pages/my/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -24,6 +26,7 @@ Page({
onShow() { onShow() {
// 药店端我的页面,仅允许药店人员访问 // 药店端我的页面,仅允许药店人员访问
app.waitLogin({ types: [4] }).then(() => { app.waitLogin({ types: [4] }).then(() => {
trackPageView('doctor_my_view')
this.getProfile() this.getProfile()
this.getProjectList() this.getProjectList()
}) })
@ -88,6 +91,7 @@ Page({
}, },
// 修改头像 // 修改头像
handleAvatar() { handleAvatar() {
trackClick('click_doctor_my_avatar')
wx.chooseMedia({ wx.chooseMedia({
count: 1, count: 1,
mediaType: ['image'], mediaType: ['image'],
@ -158,21 +162,25 @@ Page({
}) })
}, },
handleNickname() { handleNickname() {
trackClick('click_doctor_my_nickname')
wx.navigateTo({ wx.navigateTo({
url: '/doctor/pages/changeNickname/index', url: '/doctor/pages/changeNickname/index',
}) })
}, },
handleTel() { handleTel() {
trackClick('click_doctor_my_tel')
wx.navigateTo({ wx.navigateTo({
url: '/doctor/pages/changeTel/index', url: '/doctor/pages/changeTel/index',
}) })
}, },
handleInvite() { handleInvite() {
trackClick('click_doctor_my_invite')
wx.navigateTo({ wx.navigateTo({
url: '/doctor/pages/invite/index', url: '/doctor/pages/invite/index',
}) })
}, },
handleExit() { handleExit() {
trackClick('click_doctor_my_exit')
wx.showModal({ wx.showModal({
title: '提示', title: '提示',
content: '确定要退出登录吗?', content: '确定要退出登录吗?',

24
src/doctor/pages/patientList/index.ts

@ -1,4 +1,6 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -59,6 +61,7 @@ Page({
onLoad() { onLoad() {
// 药店端患者列表页面,仅允许药店人员访问 // 药店端患者列表页面,仅允许药店人员访问
app.waitLogin({ types: [4] }).then(() => { app.waitLogin({ types: [4] }).then(() => {
trackPageView('doctor_patient_view')
this.getProjectList() this.getProjectList()
}) })
}, },
@ -90,6 +93,7 @@ Page({
}, },
// 切换项目 // 切换项目
onProjectChange(e: WechatMiniprogram.CustomEvent) { onProjectChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_patient_project_switch')
const index = e.detail.value const index = e.detail.value
const project = this.data.projectList[index] const project = this.data.projectList[index]
if (!project || project.projectId === this.data.currentProjectId) return if (!project || project.projectId === this.data.currentProjectId) return
@ -211,6 +215,7 @@ Page({
}, },
// 搜索患者 // 搜索患者
handleSearch(e: WechatMiniprogram.CustomEvent) { handleSearch(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_patient_search')
this.setData({ this.setData({
keyword: e.detail.value, keyword: e.detail.value,
page: 1, page: 1,
@ -221,6 +226,7 @@ Page({
}, },
// 跳转状态筛选 // 跳转状态筛选
handleJumpStatusChange(e: WechatMiniprogram.CustomEvent) { handleJumpStatusChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_patient_jump_status')
const index = e.detail.value const index = e.detail.value
const option = this.data.jumpStatusOptions[index] const option = this.data.jumpStatusOptions[index]
this.setData({ this.setData({
@ -235,6 +241,7 @@ Page({
}, },
// 入组状态筛选 // 入组状态筛选
handleEnrollStatusChange(e: WechatMiniprogram.CustomEvent) { handleEnrollStatusChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_patient_enroll_status')
const index = e.detail.value const index = e.detail.value
const option = this.data.enrollStatusOptions[index] const option = this.data.enrollStatusOptions[index]
this.setData({ this.setData({
@ -249,6 +256,7 @@ Page({
}, },
// 跳转开始时间选择 // 跳转开始时间选择
handleJumpStartTimeChange(e: WechatMiniprogram.CustomEvent) { handleJumpStartTimeChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_patient_jump_start')
const jumpStartTime = e.detail.value const jumpStartTime = e.detail.value
if (this.data.jumpEndTime && jumpStartTime > this.data.jumpEndTime) { if (this.data.jumpEndTime && jumpStartTime > this.data.jumpEndTime) {
wx.showToast({ wx.showToast({
@ -267,6 +275,7 @@ Page({
}, },
// 跳转结束时间选择 // 跳转结束时间选择
handleJumpEndTimeChange(e: WechatMiniprogram.CustomEvent) { handleJumpEndTimeChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_patient_jump_end')
const jumpEndTime = e.detail.value const jumpEndTime = e.detail.value
if (this.data.jumpStartTime && jumpEndTime < this.data.jumpStartTime) { if (this.data.jumpStartTime && jumpEndTime < this.data.jumpStartTime) {
wx.showToast({ wx.showToast({
@ -285,6 +294,7 @@ Page({
}, },
// 入组开始时间选择 // 入组开始时间选择
handleEnrollStartTimeChange(e: WechatMiniprogram.CustomEvent) { handleEnrollStartTimeChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_patient_enroll_start')
const enrollStartTime = e.detail.value const enrollStartTime = e.detail.value
if (this.data.enrollEndTime && enrollStartTime > this.data.enrollEndTime) { if (this.data.enrollEndTime && enrollStartTime > this.data.enrollEndTime) {
wx.showToast({ wx.showToast({
@ -303,6 +313,7 @@ Page({
}, },
// 入组结束时间选择 // 入组结束时间选择
handleEnrollEndTimeChange(e: WechatMiniprogram.CustomEvent) { handleEnrollEndTimeChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_patient_enroll_end')
const enrollEndTime = e.detail.value const enrollEndTime = e.detail.value
if (this.data.enrollStartTime && enrollEndTime < this.data.enrollStartTime) { if (this.data.enrollStartTime && enrollEndTime < this.data.enrollStartTime) {
wx.showToast({ wx.showToast({
@ -328,6 +339,7 @@ Page({
}, },
// 预览提交的材料图片 // 预览提交的材料图片
handlePreviewMaterial(e: WechatMiniprogram.CustomEvent) { handlePreviewMaterial(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_patient_preview')
const { url } = e.currentTarget.dataset const { url } = e.currentTarget.dataset
if (!url) { if (!url) {
wx.showToast({ wx.showToast({
@ -353,6 +365,18 @@ Page({
const auditType = isJumpMaterial ? 1 : 2 const auditType = isJumpMaterial ? 1 : 2
const title = isJumpMaterial ? '上传跳转证明材料' : '上传入组证明材料' const title = isJumpMaterial ? '上传跳转证明材料' : '上传入组证明材料'
// 根据类型和状态判断埋点事件
const materialType = isJumpMaterial ? 'jump' : 'enroll'
const patientItem = patient
const isReupload = isJumpMaterial
? patientItem.jumpMaterial?.auditStatus === 2
: patientItem.enrollMaterial?.auditStatus === 2
if (isReupload) {
trackClick(`click_doctor_patient_reupload_${materialType}`)
} else {
trackClick(`click_doctor_patient_upload_${materialType}`)
}
this.setData({ this.setData({
popupShow: true, popupShow: true,
popupType: 'uploadMaterial', popupType: 'uploadMaterial',

10
src/doctor/pages/stat/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -40,6 +42,7 @@ Page({
onLoad(options: any) { onLoad(options: any) {
// 药店端统计页面,仅允许药店人员访问 // 药店端统计页面,仅允许药店人员访问
app.waitLogin({ types: [4] }).then(() => { app.waitLogin({ types: [4] }).then(() => {
trackPageView('doctor_stat_view')
this.initDate(options) this.initDate(options)
}) })
}, },
@ -121,6 +124,11 @@ Page({
switchStatType(e: WechatMiniprogram.CustomEvent) { switchStatType(e: WechatMiniprogram.CustomEvent) {
const type = e.currentTarget.dataset.type const type = e.currentTarget.dataset.type
if (type === this.data.statType) return if (type === this.data.statType) return
if (type === 'day') {
trackClick('click_doctor_stat_type_day')
} else {
trackClick('click_doctor_stat_type_month')
}
this.setData({ this.setData({
statType: type, statType: type,
@ -133,6 +141,7 @@ Page({
// 开始日期变化 // 开始日期变化
handleStartDateChange(e: WechatMiniprogram.CustomEvent) { handleStartDateChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_stat_start_date')
const startDate = e.detail.value const startDate = e.detail.value
if (startDate > this.data.endDate) { if (startDate > this.data.endDate) {
wx.showToast({ wx.showToast({
@ -153,6 +162,7 @@ Page({
// 结束日期变化 // 结束日期变化
handleEndDateChange(e: WechatMiniprogram.CustomEvent) { handleEndDateChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_doctor_stat_end_date')
const endDate = e.detail.value const endDate = e.detail.value
if (endDate < this.data.startDate) { if (endDate < this.data.startDate) {
wx.showToast({ wx.showToast({

3
src/ground/pages/changeNickname/index.ts

@ -1,3 +1,5 @@
import { trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -8,6 +10,7 @@ Page({
onLoad() { onLoad() {
// 地推端修改昵称页面,仅允许地推人员访问 // 地推端修改昵称页面,仅允许地推人员访问
app.waitLogin({ types: [3] }).then(() => { app.waitLogin({ types: [3] }).then(() => {
trackPageView('ground_change_name_view')
// 获取当前姓名 // 获取当前姓名
this.getCurrentName() this.getCurrentName()
}) })

5
src/ground/pages/changeTel/index.ts

@ -1,5 +1,6 @@
const app = getApp<IAppOption>() import { trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>()
let timer = null as null | number let timer = null as null | number
Page({ Page({
@ -12,7 +13,7 @@ Page({
onLoad() { onLoad() {
// 地推端修改手机号页面,仅允许地推人员访问 // 地推端修改手机号页面,仅允许地推人员访问
app.waitLogin({ types: [3] }).then(() => { app.waitLogin({ types: [3] }).then(() => {
// 页面加载完成 trackPageView('ground_change_tel_view')
}) })
}, },
onUnload() { onUnload() {

34
src/ground/pages/home/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const echarts = require('../../../components/ec-canvas/echarts.js') const echarts = require('../../../components/ec-canvas/echarts.js')
Page({ Page({
@ -86,6 +88,7 @@ Page({
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
// 地推端页面,仅允许地推人员(3)访问 // 地推端页面,仅允许地推人员(3)访问
app.waitLogin({ types: [3] }).then(() => { app.waitLogin({ types: [3] }).then(() => {
trackPageView('ground_home_view')
this.getUserInfo() this.getUserInfo()
this.getProjectList() this.getProjectList()
}) })
@ -173,6 +176,7 @@ Page({
// 切换项目 // 切换项目
onProjectChange(e: WechatMiniprogram.CustomEvent) { onProjectChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_ground_home_project_switch')
const index = e.detail.value const index = e.detail.value
const project = this.data.projectList[index] const project = this.data.projectList[index]
if (project && project.projectId !== this.data.currentProjectId) { if (project && project.projectId !== this.data.currentProjectId) {
@ -330,6 +334,11 @@ Page({
// 切换统计类型 // 切换统计类型
switchStatType(e: WechatMiniprogram.CustomEvent) { switchStatType(e: WechatMiniprogram.CustomEvent) {
const type = e.currentTarget.dataset.type const type = e.currentTarget.dataset.type
if (type === 'day') {
trackClick('click_ground_home_stat_type_day')
} else {
trackClick('click_ground_home_stat_type_month')
}
const isMonth = type === 'month' const isMonth = type === 'month'
// 根据统计类型重置日期范围 // 根据统计类型重置日期范围
@ -413,6 +422,7 @@ Page({
// 日期选择变化(邀约患者统计卡片 - 单日选择) // 日期选择变化(邀约患者统计卡片 - 单日选择)
onDateChange(e: WechatMiniprogram.CustomEvent) { onDateChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_ground_home_date_picker')
const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM
// 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD // 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD
@ -431,6 +441,11 @@ Page({
// 图表1日期选择变化 // 图表1日期选择变化
onChart1DateChange(e: WechatMiniprogram.CustomEvent) { onChart1DateChange(e: WechatMiniprogram.CustomEvent) {
const { field } = e.currentTarget.dataset const { field } = e.currentTarget.dataset
if (field === 'startDate') {
trackClick('click_ground_home_chart1_start')
} else {
trackClick('click_ground_home_chart1_end')
}
const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM
// 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD // 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD
@ -474,6 +489,11 @@ Page({
// 图表2日期选择变化 // 图表2日期选择变化
onChart2DateChange(e: WechatMiniprogram.CustomEvent) { onChart2DateChange(e: WechatMiniprogram.CustomEvent) {
const { field } = e.currentTarget.dataset const { field } = e.currentTarget.dataset
if (field === 'startDate') {
trackClick('click_ground_home_chart2_start')
} else {
trackClick('click_ground_home_chart2_end')
}
const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM
// 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD // 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD
@ -517,6 +537,11 @@ Page({
// 图表3日期选择变化 // 图表3日期选择变化
onChart3DateChange(e: WechatMiniprogram.CustomEvent) { onChart3DateChange(e: WechatMiniprogram.CustomEvent) {
const { field } = e.currentTarget.dataset const { field } = e.currentTarget.dataset
if (field === 'startDate') {
trackClick('click_ground_home_chart3_start')
} else {
trackClick('click_ground_home_chart3_end')
}
const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM const value = e.detail.value // YYYY-MM-DD 或 YYYY-MM
// 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD // 月统计时,value 是 YYYY-MM 格式,需要补全为 YYYY-MM-DD
@ -559,6 +584,7 @@ Page({
// 切换到上一天/上月(只更新邀约患者统计卡片) // 切换到上一天/上月(只更新邀约患者统计卡片)
prevDate() { prevDate() {
trackClick('click_ground_home_date_prev')
const isMonth = this.data.statType === 'month' const isMonth = this.data.statType === 'month'
let newDate: Date let newDate: Date
let startDate: string let startDate: string
@ -585,6 +611,7 @@ Page({
// 切换到下一天/下月(只更新邀约患者统计卡片) // 切换到下一天/下月(只更新邀约患者统计卡片)
nextDate() { nextDate() {
trackClick('click_ground_home_date_next')
const isMonth = this.data.statType === 'month' const isMonth = this.data.statType === 'month'
const today = new Date() const today = new Date()
// 今天的 23:59:59,只要新日期小于等于这个时间就可以选择 // 今天的 23:59:59,只要新日期小于等于这个时间就可以选择
@ -892,12 +919,14 @@ Page({
}, },
handleInvite() { handleInvite() {
trackClick('click_ground_home_invite_code')
wx.navigateTo({ wx.navigateTo({
url: '/ground/pages/invite/index', url: '/ground/pages/invite/index',
}) })
}, },
handleInfo() { handleInfo() {
trackClick('click_ground_home_detail')
const { chart1StartDate, chart1EndDate, statType } = this.data const { chart1StartDate, chart1EndDate, statType } = this.data
wx.navigateTo({ wx.navigateTo({
url: `/ground/pages/stat/index?startDate=${chart1StartDate}&endDate=${chart1EndDate}&type=${statType}`, url: `/ground/pages/stat/index?startDate=${chart1StartDate}&endDate=${chart1EndDate}&type=${statType}`,
@ -906,6 +935,11 @@ Page({
handleFold(e) { handleFold(e) {
const { key } = e.currentTarget.dataset const { key } = e.currentTarget.dataset
if (key === 'fold1') {
trackClick('click_ground_home_fold1')
} else if (key === 'fold2') {
trackClick('click_ground_home_fold2')
}
this.setData({ this.setData({
[key]: !this.data[key], [key]: !this.data[key],
}) })

2
src/ground/pages/home/index.wxml

@ -29,7 +29,7 @@
<van-icon class="icon" name="arrow-down" /> <van-icon class="icon" name="arrow-down" />
</view> </view>
</view> </view>
<view class="tip">截止昨日数据</view> <view class="tip">展示实时数据</view>
</view> </view>
<view class="row1"> <view class="row1">
<view class="col"> <view class="col">

4
src/ground/pages/invite/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -17,6 +19,7 @@ Page({
onLoad() { onLoad() {
// 地推端邀约页面,仅允许地推人员访问 // 地推端邀约页面,仅允许地推人员访问
app.waitLogin({ types: [3] }).then(() => { app.waitLogin({ types: [3] }).then(() => {
trackPageView('ground_invite_view')
this.getUserInfo() this.getUserInfo()
}) })
}, },
@ -58,6 +61,7 @@ Page({
}, },
// 保存二维码到相册 // 保存二维码到相册
saveQrCode() { saveQrCode() {
trackClick('click_ground_invite_save')
const { qrCodeUrl } = this.data const { qrCodeUrl } = this.data
if (!qrCodeUrl) { if (!qrCodeUrl) {
wx.showToast({ wx.showToast({

12
src/ground/pages/login/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
let timer = null as null | number let timer = null as null | number
@ -17,7 +19,11 @@ Page({
}) })
} }
}, },
onShow() {
trackPageView('ground_login_view')
},
getCode() { getCode() {
trackClick('click_ground_login_sms_code')
if (timer) return if (timer) return
const mobile = this.data.mobile const mobile = this.data.mobile
if (!mobile) { if (!mobile) {
@ -64,6 +70,7 @@ Page({
}) })
}, },
handleSubmit() { handleSubmit() {
trackClick('click_ground_login_submit')
if (!this.data.mobile) { if (!this.data.mobile) {
wx.showToast({ wx.showToast({
icon: 'none', icon: 'none',
@ -99,6 +106,7 @@ Page({
}) })
}, },
handleWxSubmit(e: WechatMiniprogram.CustomEvent) { handleWxSubmit(e: WechatMiniprogram.CustomEvent) {
trackClick('click_ground_login_wx')
if (!this.data.check) { if (!this.data.check) {
wx.showToast({ wx.showToast({
icon: 'none', icon: 'none',
@ -131,21 +139,25 @@ Page({
}) })
}, },
handlePatient() { handlePatient() {
trackClick('click_ground_login_patient')
wx.restartMiniProgram({ wx.restartMiniProgram({
path: '/pages/start/index', path: '/pages/start/index',
}) })
}, },
handleTelCode() { handleTelCode() {
trackClick('click_ground_login_sms_switch')
this.setData({ this.setData({
showForm: !this.data.showForm, showForm: !this.data.showForm,
}) })
}, },
handleLink() { handleLink() {
trackClick('click_ground_login_privacy')
wx.navigateTo({ wx.navigateTo({
url: '/privacy/pages/policy/index', url: '/privacy/pages/policy/index',
}) })
}, },
handleCheck() { handleCheck() {
trackClick('click_ground_login_agreement')
this.setData({ this.setData({
check: !this.data.check, check: !this.data.check,
}) })

8
src/ground/pages/my/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -10,6 +12,7 @@ Page({
onShow() { onShow() {
// 地推端我的页面,仅允许地推人员访问 // 地推端我的页面,仅允许地推人员访问
app.waitLogin({ types: [3] }).then(() => { app.waitLogin({ types: [3] }).then(() => {
trackPageView('ground_my_view')
this.getUserInfo() this.getUserInfo()
}) })
}, },
@ -28,6 +31,7 @@ Page({
}, },
// 点击头像修改头像 // 点击头像修改头像
handleAvatar() { handleAvatar() {
trackClick('click_ground_my_avatar')
wx.chooseMedia({ wx.chooseMedia({
count: 1, count: 1,
mediaType: ['image'], mediaType: ['image'],
@ -101,21 +105,25 @@ Page({
}) })
}, },
handleNickname() { handleNickname() {
trackClick('click_ground_my_nickname')
wx.navigateTo({ wx.navigateTo({
url: '/ground/pages/changeNickname/index', url: '/ground/pages/changeNickname/index',
}) })
}, },
handleTel() { handleTel() {
trackClick('click_ground_my_tel')
wx.navigateTo({ wx.navigateTo({
url: '/ground/pages/changeTel/index', url: '/ground/pages/changeTel/index',
}) })
}, },
handleInvite() { handleInvite() {
trackClick('click_ground_my_invite')
wx.navigateTo({ wx.navigateTo({
url: '/ground/pages/invite/index', url: '/ground/pages/invite/index',
}) })
}, },
hadleExit() { hadleExit() {
trackClick('click_ground_my_exit')
wx.showModal({ wx.showModal({
title: '提示', title: '提示',
content: '确定要退出登录吗?', content: '确定要退出登录吗?',

8
src/ground/pages/pharmacist/index.ts

@ -1,4 +1,6 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -34,6 +36,7 @@ Page({
onLoad() { onLoad() {
// 地推端店员页面,仅允许地推人员访问 // 地推端店员页面,仅允许地推人员访问
app.waitLogin({ types: [3] }).then(() => { app.waitLogin({ types: [3] }).then(() => {
trackPageView('ground_pharmacist_view')
this.getProjectList() this.getProjectList()
}) })
}, },
@ -63,6 +66,7 @@ Page({
// 切换项目 // 切换项目
onProjectChange(e: WechatMiniprogram.CustomEvent) { onProjectChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_ground_pharmacist_project_switch')
const index = e.detail.value const index = e.detail.value
const project = this.data.projectList[index] const project = this.data.projectList[index]
if (project && project.projectId !== this.data.currentProjectId) { if (project && project.projectId !== this.data.currentProjectId) {
@ -143,6 +147,7 @@ Page({
}, },
// 搜索店员 // 搜索店员
handleSearch(e: WechatMiniprogram.CustomEvent) { handleSearch(e: WechatMiniprogram.CustomEvent) {
trackClick('click_ground_pharmacist_search')
this.setData({ this.setData({
keyword: e.detail.value, keyword: e.detail.value,
page: 1, page: 1,
@ -158,6 +163,7 @@ Page({
}, },
// 开始时间选择 // 开始时间选择
handleStartDateChange(e: WechatMiniprogram.CustomEvent) { handleStartDateChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_ground_pharmacist_start_date')
const startDate = e.detail.value const startDate = e.detail.value
const { endDate } = this.data const { endDate } = this.data
@ -185,6 +191,7 @@ Page({
}, },
// 结束时间选择 // 结束时间选择
handleEndDateChange(e: WechatMiniprogram.CustomEvent) { handleEndDateChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_ground_pharmacist_end_date')
const endDate = e.detail.value const endDate = e.detail.value
const { startDate } = this.data const { startDate } = this.data
@ -219,6 +226,7 @@ Page({
}, },
// 查看详情 // 查看详情
handleInfo(e: WechatMiniprogram.CustomEvent) { handleInfo(e: WechatMiniprogram.CustomEvent) {
trackClick('click_ground_pharmacist_card')
const { id } = e.currentTarget.dataset const { id } = e.currentTarget.dataset
const { startDate, endDate } = this.data const { startDate, endDate } = this.data
wx.navigateTo({ wx.navigateTo({

5
src/ground/pages/stat/index.ts

@ -1,4 +1,6 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -32,6 +34,7 @@ Page({
onLoad(options: any) { onLoad(options: any) {
// 地推端统计页面,仅允许地推人员访问 // 地推端统计页面,仅允许地推人员访问
app.waitLogin({ types: [3] }).then(() => { app.waitLogin({ types: [3] }).then(() => {
trackPageView('ground_stat_view')
// 设置参数 // 设置参数
this.setOptions(options) this.setOptions(options)
@ -226,6 +229,7 @@ Page({
}, },
// 开始时间选择 // 开始时间选择
handleStartDateChange(e: WechatMiniprogram.CustomEvent) { handleStartDateChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_ground_stat_start_date')
const startDate = e.detail.value const startDate = e.detail.value
const { endDate } = this.data const { endDate } = this.data
@ -243,6 +247,7 @@ Page({
}, },
// 结束时间选择 // 结束时间选择
handleEndDateChange(e: WechatMiniprogram.CustomEvent) { handleEndDateChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_ground_stat_end_date')
const endDate = e.detail.value const endDate = e.detail.value
const { startDate } = this.data const { startDate } = this.data

16
src/pages/index/index.ts

@ -1,3 +1,7 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>()
Page({ Page({
data: { data: {
background: 'transparent', background: 'transparent',
@ -38,8 +42,6 @@ Page({
hasBindPharmacist: false, hasBindPharmacist: false,
onLoad() { onLoad() {
const app = getApp<IAppOption>()
// 从 globalData 初始化扫码参数 // 从 globalData 初始化扫码参数
const pharmacistId = app.globalData.pharmacistId || '' const pharmacistId = app.globalData.pharmacistId || ''
const projectId = app.globalData.projectId || '' const projectId = app.globalData.projectId || ''
@ -50,6 +52,7 @@ Page({
}) })
app.waitLogin().then(() => { app.waitLogin().then(() => {
trackPageView('patient_home_view')
this.getBanner() this.getBanner()
this.checkStatus() this.checkStatus()
this.getUserInfo() this.getUserInfo()
@ -58,6 +61,7 @@ Page({
// 切换项目 // 切换项目
onProjectChange(e: WechatMiniprogram.CustomEvent) { onProjectChange(e: WechatMiniprogram.CustomEvent) {
trackClick('click_patient_project_switch')
const index = e.detail.value const index = e.detail.value
const project = this.data.projectList[index] const project = this.data.projectList[index]
@ -303,8 +307,8 @@ Page({
// 选择头像 // 选择头像
onChooseAvatar(e: WechatMiniprogram.CustomEvent) { onChooseAvatar(e: WechatMiniprogram.CustomEvent) {
trackClick('click_patient_avatar')
const { avatarUrl } = e.detail const { avatarUrl } = e.detail
const app = getApp<IAppOption>()
// 上传头像 // 上传头像
wx.uploadFile({ wx.uploadFile({
url: `${app.globalData.url }/app/common/common/upload`, url: `${app.globalData.url }/app/common/common/upload`,
@ -340,6 +344,7 @@ Page({
// 昵称失焦时保存 // 昵称失焦时保存
onNicknameBlur(e: WechatMiniprogram.CustomEvent) { onNicknameBlur(e: WechatMiniprogram.CustomEvent) {
trackClick('click_patient_nickname_save')
const nickname = e.detail.value const nickname = e.detail.value
this.setData({ this.setData({
nickname, nickname,
@ -419,6 +424,7 @@ Page({
}, },
selectOption(e) { selectOption(e) {
trackClick('click_patient_indication_select')
const indicationId = e.currentTarget.dataset.id as number const indicationId = e.currentTarget.dataset.id as number
const newOptions = this.data.options.map((option) => ({ const newOptions = this.data.options.map((option) => ({
...option, ...option,
@ -492,23 +498,27 @@ Page({
}, },
toggleAgreement() { toggleAgreement() {
trackClick('click_patient_agreement_toggle')
this.setData({ this.setData({
agreementChecked: !this.data.agreementChecked, agreementChecked: !this.data.agreementChecked,
}) })
}, },
handleAgreement() { handleAgreement() {
trackClick('click_patient_agreement_view')
wx.navigateTo({ wx.navigateTo({
url: '/privacy/pages/policy1/index', url: '/privacy/pages/policy1/index',
}) })
}, },
handleWork() { handleWork() {
trackClick('click_patient_work_entry')
wx.navigateTo({ wx.navigateTo({
url: '/pages/work/index', url: '/pages/work/index',
}) })
}, },
handleJump() { handleJump() {
trackClick('click_patient_jump_miniprogram')
// 跳转到腾讯药箱小程序 // 跳转到腾讯药箱小程序
wx.navigateToMiniProgram({ wx.navigateToMiniProgram({
appId: 'wx05551c5ee1fd1c12', appId: 'wx05551c5ee1fd1c12',

2
src/pages/start/index.ts

@ -1,3 +1,4 @@
import { trackPageView } from '@/utils/tracking'
import { parseScene } from '@/utils/util' import { parseScene } from '@/utils/util'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
@ -35,6 +36,7 @@ Page({
} }
app.waitLogin().then(() => { app.waitLogin().then(() => {
trackPageView('patient_start_view')
const { isLogin, isRegister, loginIdentity, patientId } = app.globalData.initLoginInfo const { isLogin, isRegister, loginIdentity, patientId } = app.globalData.initLoginInfo
// 扫码进入用户处理 // 扫码进入用户处理

5
src/pages/tourists/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -7,6 +9,7 @@ Page({
}, },
onLoad() { onLoad() {
app.waitLogin().then(() => { app.waitLogin().then(() => {
trackPageView('patient_tourists_view')
this.getUserInfo() this.getUserInfo()
}) })
}, },
@ -103,12 +106,14 @@ Page({
}, },
// 跳转到药店工作人员登录页 // 跳转到药店工作人员登录页
goToPharmacist() { goToPharmacist() {
trackClick('click_tourists_pharmacist')
wx.navigateTo({ wx.navigateTo({
url: '/doctor/pages/login/index', url: '/doctor/pages/login/index',
}) })
}, },
// 跳转到地推人员登录页 // 跳转到地推人员登录页
goToPromoter() { goToPromoter() {
trackClick('click_tourists_promoter')
wx.navigateTo({ wx.navigateTo({
url: '/ground/pages/login/index', url: '/ground/pages/login/index',
}) })

7
src/pages/work/index.ts

@ -1,3 +1,5 @@
import { trackClick, trackPageView } from '@/utils/tracking'
const app = getApp<IAppOption>() const app = getApp<IAppOption>()
Page({ Page({
@ -5,20 +7,23 @@ Page({
onLoad() { onLoad() {
// 工作入口页面,允许所有身份访问 // 工作入口页面,允许所有身份访问
app.waitLogin({ types: [] }).then(() => { app.waitLogin({ types: [] }).then(() => {
// 页面加载完成 trackPageView('patient_work_view')
}) })
}, },
handleGround() { handleGround() {
trackClick('click_work_ground')
wx.navigateTo({ wx.navigateTo({
url: '/ground/pages/login/index', url: '/ground/pages/login/index',
}) })
}, },
handleDoctor() { handleDoctor() {
trackClick('click_work_doctor')
wx.navigateTo({ wx.navigateTo({
url: '/doctor/pages/login/index', url: '/doctor/pages/login/index',
}) })
}, },
hadlePatient() { hadlePatient() {
trackClick('click_work_patient')
wx.navigateTo({ wx.navigateTo({
url: '/pages/tourists/index', url: '/pages/tourists/index',
}) })

5
src/privacy/pages/policy/index.ts

File diff suppressed because one or more lines are too long

4
src/privacy/pages/policy1/index.ts

File diff suppressed because one or more lines are too long

39
src/utils/tracking.ts

@ -0,0 +1,39 @@
/**
*
*
*/
/**
*
* @param pageName {role}_{page}_{action}_{element}
*/
export function reportBehavior(pageName: string) {
wx.ajax({
method: 'POST',
url: '/app/common/common/report-behavior',
data: {
pageName,
},
loading: false,
showMsg: false,
}).catch(() => {
// 埋点上报失败不阻塞业务流程
})
}
/**
*
* @param pageName 'patient_start_view'
*/
export function trackPageView(pageName: string) {
reportBehavior(pageName)
}
/**
*
* @param eventName 'patient_start_click_pharmacist'
*/
export function trackClick(eventName: string) {
reportBehavior(eventName)
}
Loading…
Cancel
Save