From 643161a1686ba2ad12923aa28e19a7b866d6a851 Mon Sep 17 00:00:00 2001 From: kdletters Date: Sun, 10 May 2026 14:48:10 +0800 Subject: [PATCH] fix(admin): populate tracking event key options --- .../config/trackingEventDefinitions.test.ts | 42 ++ .../src/config/trackingEventDefinitions.ts | 403 +++++++++++++++++- .../src/pages/AdminTaskConfigPage.tsx | 4 +- ...TRACKING_EVENT_DETAIL_EXPORT_2026-05-07.md | 2 +- ...ILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md | 2 +- 5 files changed, 446 insertions(+), 7 deletions(-) create mode 100644 apps/admin-web/src/config/trackingEventDefinitions.test.ts diff --git a/apps/admin-web/src/config/trackingEventDefinitions.test.ts b/apps/admin-web/src/config/trackingEventDefinitions.test.ts new file mode 100644 index 00000000..0c04ba47 --- /dev/null +++ b/apps/admin-web/src/config/trackingEventDefinitions.test.ts @@ -0,0 +1,42 @@ +import {describe, expect, test} from 'vitest'; + +import { + adminProfileTaskTrackingEventDefinitions, + adminTrackingEventDefinitions, + filterAdminProfileTaskTrackingEventDefinitions, + filterAdminTrackingEventDefinitions, + findAdminTrackingEventDefinition, +} from './trackingEventDefinitions'; + +describe('admin tracking event definitions', () => { + test('后台埋点筛选候选包含后端通用埋点清单', () => { + const keys = adminTrackingEventDefinitions.map((definition) => definition.key); + + expect(keys.length).toBeGreaterThan(40); + expect(keys).toContain('daily_login'); + expect(keys).toContain('auth_login_options_view'); + expect(keys).toContain('task_center_view'); + expect(keys).toContain('asset_upload_ticket_create'); + expect(keys).toContain('creative_agent_route_success'); + expect(keys).toContain('work_play_start'); + }); + + test('任务配置候选只开放适合个人任务的事件', () => { + expect(adminProfileTaskTrackingEventDefinitions.map(({key}) => key)).toEqual([ + 'daily_login', + ]); + expect(filterAdminProfileTaskTrackingEventDefinitions('').map(({key}) => key)).toEqual([ + 'daily_login', + ]); + }); + + test('后台埋点筛选支持按中文名称和 key 搜索', () => { + expect(filterAdminTrackingEventDefinitions('上传票据').map(({key}) => key)).toEqual([ + 'asset_upload_ticket_create', + ]); + expect(filterAdminTrackingEventDefinitions('work_play').map(({key}) => key)).toEqual([ + 'work_play_start', + ]); + expect(findAdminTrackingEventDefinition(' daily_login ')?.title).toBe('每日登录'); + }); +}); diff --git a/apps/admin-web/src/config/trackingEventDefinitions.ts b/apps/admin-web/src/config/trackingEventDefinitions.ts index 2e068809..dd18ea35 100644 --- a/apps/admin-web/src/config/trackingEventDefinitions.ts +++ b/apps/admin-web/src/config/trackingEventDefinitions.ts @@ -5,17 +5,400 @@ export interface AdminTrackingEventDefinition { title: string; scopeKind: TrackingScopeKind; remark: string; + taskConfigEligible?: boolean; } export const adminTrackingEventDefinitions: AdminTrackingEventDefinition[] = [ + { + key: 'auth_login_options_view', + title: '登录方式查看', + scopeKind: 'site', + remark: '读取当前可用登录方式时记录,用于观察登录入口曝光。', + }, + { + key: 'auth_phone_code_send', + title: '发送手机验证码', + scopeKind: 'site', + remark: '提交手机验证码发送请求成功后记录。', + }, { key: 'daily_login', title: '每日登录', scopeKind: 'user', - remark: '用户打开任务中心时由后端幂等记录,用于每日登录任务进度校验。', + remark: '认证成功或 refresh 续期后由后端幂等记录,用于每日登录任务进度校验。', + taskConfigEligible: true, + }, + { + key: 'auth_phone_login_success', + title: '手机号登录成功', + scopeKind: 'user', + remark: '手机号验证码登录成功后记录。', + }, + { + key: 'auth_me_view', + title: '当前账号查看', + scopeKind: 'user', + remark: '读取当前登录账号信息成功后记录。', + }, + { + key: 'auth_sessions_view', + title: '登录会话查看', + scopeKind: 'user', + remark: '读取当前账号登录会话列表成功后记录。', + }, + { + key: 'auth_refresh_success', + title: '登录续期成功', + scopeKind: 'site', + remark: 'refresh cookie 续期成功后记录。', + }, + { + key: 'auth_logout', + title: '退出登录', + scopeKind: 'user', + remark: '退出当前登录会话成功后记录。', + }, + { + key: 'auth_logout_all', + title: '退出全部会话', + scopeKind: 'user', + remark: '退出全部登录会话成功后记录。', + }, + { + key: 'auth_wechat_bind_phone_success', + title: '微信绑定手机成功', + scopeKind: 'user', + remark: '微信账号绑定手机号成功后记录。', + }, + { + key: 'profile_identity_update', + title: '资料更新', + scopeKind: 'user', + remark: '用户资料更新成功后记录。', + }, + { + key: 'profile_dashboard_view', + title: '个人看板查看', + scopeKind: 'user', + remark: '读取个人看板成功后记录。', + }, + { + key: 'wallet_ledger_view', + title: '钱包流水查看', + scopeKind: 'user', + remark: '读取光点钱包流水成功后记录。', + }, + { + key: 'recharge_center_view', + title: '充值中心查看', + scopeKind: 'user', + remark: '读取充值中心信息成功后记录。', + }, + { + key: 'recharge_order_create', + title: '充值订单创建', + scopeKind: 'user', + remark: '创建充值订单成功后记录。', + }, + { + key: 'feedback_submit', + title: '反馈提交', + scopeKind: 'user', + remark: '资料页反馈提交成功后记录。', + }, + { + key: 'invite_center_view', + title: '邀请中心查看', + scopeKind: 'user', + remark: '读取邀请中心成功后记录。', + }, + { + key: 'referral_invite_code_redeem', + title: '邀请码绑定', + scopeKind: 'user', + remark: '绑定推荐邀请码成功后记录。', + }, + { + key: 'redeem_code_submit', + title: '兑换码提交', + scopeKind: 'user', + remark: '提交运营兑换码成功后记录。', + }, + { + key: 'task_center_view', + title: '任务中心查看', + scopeKind: 'user', + remark: '读取个人任务中心成功后记录。', + }, + { + key: 'task_reward_claim', + title: '任务奖励领取', + scopeKind: 'user', + remark: '领取个人任务奖励成功后记录。', + }, + { + key: 'save_archive_list_view', + title: '存档列表查看', + scopeKind: 'user', + remark: '读取个人存档列表成功后记录。', + }, + { + key: 'save_archive_detail_view', + title: '存档详情查看', + scopeKind: 'user', + remark: '读取个人存档详情成功后记录。', + }, + { + key: 'browse_history_view', + title: '浏览历史查看', + scopeKind: 'user', + remark: '读取浏览历史成功后记录。', + }, + { + key: 'browse_history_record', + title: '浏览历史写入', + scopeKind: 'user', + remark: '记录浏览历史成功后记录。', + }, + { + key: 'browse_history_clear', + title: '浏览历史清空', + scopeKind: 'user', + remark: '清空浏览历史成功后记录。', + }, + { + key: 'play_stats_view', + title: '游玩统计查看', + scopeKind: 'user', + remark: '读取个人游玩统计成功后记录。', + }, + { + key: 'profile_analytics_metric_view', + title: '个人指标查看', + scopeKind: 'user', + remark: '读取个人埋点指标成功后记录。', + }, + { + key: 'ai_task_create', + title: 'AI 任务创建', + scopeKind: 'user', + remark: '创建 AI 任务成功后记录。', + }, + { + key: 'ai_task_start', + title: 'AI 任务启动', + scopeKind: 'user', + remark: '启动 AI 任务成功后记录。', + }, + { + key: 'ai_task_stage_start', + title: 'AI 阶段启动', + scopeKind: 'user', + remark: '启动 AI 任务阶段成功后记录。', + }, + { + key: 'ai_task_chunk_append', + title: 'AI 分片追加', + scopeKind: 'user', + remark: '追加 AI 文本分片成功后记录。', + }, + { + key: 'ai_task_stage_complete', + title: 'AI 阶段完成', + scopeKind: 'user', + remark: '完成 AI 任务阶段成功后记录。', + }, + { + key: 'ai_task_reference_attach', + title: 'AI 结果引用绑定', + scopeKind: 'user', + remark: '绑定 AI 结果引用成功后记录。', + }, + { + key: 'ai_task_complete', + title: 'AI 任务完成', + scopeKind: 'user', + remark: '完成 AI 任务成功后记录。', + }, + { + key: 'ai_task_fail', + title: 'AI 任务失败标记', + scopeKind: 'user', + remark: '标记 AI 任务失败成功后记录。', + }, + { + key: 'ai_task_cancel', + title: 'AI 任务取消', + scopeKind: 'user', + remark: '取消 AI 任务成功后记录。', + }, + { + key: 'asset_upload_ticket_create', + title: '资产上传票据创建', + scopeKind: 'user', + remark: '创建直传票据成功后记录,metadata 包含低敏资产定位字段。', + }, + { + key: 'asset_sts_credentials_create', + title: '资产 STS 凭证创建', + scopeKind: 'user', + remark: '创建临时上传凭证成功后记录。', + }, + { + key: 'asset_upload_confirm', + title: '资产上传确认', + scopeKind: 'user', + remark: '确认 OSS 对象为平台资产成功后记录。', + }, + { + key: 'asset_bind', + title: '资产绑定', + scopeKind: 'user', + remark: '把平台资产绑定到业务实体成功后记录。', + }, + { + key: 'asset_character_visual_generate', + title: '角色形象生成', + scopeKind: 'user', + remark: '角色主图生成请求成功后记录。', + }, + { + key: 'asset_character_visual_publish', + title: '角色形象发布', + scopeKind: 'user', + remark: '角色主图发布成功后记录。', + }, + { + key: 'asset_character_animation_generate', + title: '角色动画生成', + scopeKind: 'user', + remark: '角色动画生成请求成功后记录。', + }, + { + key: 'asset_character_animation_publish', + title: '角色动画发布', + scopeKind: 'user', + remark: '角色动画发布成功后记录。', + }, + { + key: 'asset_character_animation_import', + title: '角色动画视频导入', + scopeKind: 'user', + remark: '角色动画导入视频成功后记录。', + }, + { + key: 'asset_character_workflow_cache_save', + title: '角色工作流缓存保存', + scopeKind: 'user', + remark: '保存角色工作流缓存成功后记录。', + }, + { + key: 'asset_history_view', + title: '资产历史查看', + scopeKind: 'user', + remark: '读取资产历史成功后记录。', + }, + { + key: 'llm_request', + title: 'LLM 请求', + scopeKind: 'user', + remark: '调用后端 LLM 门面成功后记录。', + }, + { + key: 'speech_config_view', + title: '语音配置查看', + scopeKind: 'user', + remark: '读取语音配置成功后记录。', + }, + { + key: 'asr_stream_start', + title: 'ASR 流启动', + scopeKind: 'user', + remark: '启动语音识别流成功后记录。', + }, + { + key: 'tts_bidirection_start', + title: 'TTS 双向流启动', + scopeKind: 'user', + remark: '启动双向语音合成流成功后记录。', + }, + { + key: 'tts_sse_start', + title: 'TTS SSE 启动', + scopeKind: 'user', + remark: '启动 SSE 语音合成成功后记录。', + }, + { + key: 'runtime_settings_view', + title: '运行设置查看', + scopeKind: 'user', + remark: '读取运行设置成功后记录。', + }, + { + key: 'runtime_settings_update', + title: '运行设置更新', + scopeKind: 'user', + remark: '更新运行设置成功后记录。', + }, + { + key: 'runtime_snapshot_view', + title: '运行快照查看', + scopeKind: 'user', + remark: '读取运行快照成功后记录。', + }, + { + key: 'runtime_snapshot_save', + title: '运行快照保存', + scopeKind: 'user', + remark: '保存运行快照成功后记录。', + }, + { + key: 'runtime_snapshot_delete', + title: '运行快照删除', + scopeKind: 'user', + remark: '删除运行快照成功后记录。', + }, + { + key: 'puzzle_route_success', + title: '拼图路由成功', + scopeKind: 'user', + remark: '拼图运行或创作接口成功响应后兜底记录;GET 入口可能按 site 统计。', + }, + { + key: 'match3d_route_success', + title: '抓大鹅路由成功', + scopeKind: 'user', + remark: '抓大鹅创作或运行接口成功响应后兜底记录;GET 入口可能按 site 统计。', + }, + { + key: 'square_hole_route_success', + title: '方洞路由成功', + scopeKind: 'user', + remark: '方洞创作或运行接口成功响应后兜底记录;GET 入口可能按 site 统计。', + }, + { + key: 'custom_world_route_success', + title: '自定义世界路由成功', + scopeKind: 'user', + remark: '自定义世界运行接口成功响应后兜底记录;GET 入口可能按 site 统计。', + }, + { + key: 'creative_agent_route_success', + title: '创意 Agent 路由成功', + scopeKind: 'user', + remark: '创意 Agent 接口成功响应后兜底记录;GET 入口可能按 site 统计。', + }, + { + key: 'work_play_start', + title: '作品开始游玩', + scopeKind: 'work', + remark: '拼图、抓大鹅、方洞、自定义世界、大鱼吃小鱼、Visual Novel 正式开始游玩时记录。', }, ]; +export const adminProfileTaskTrackingEventDefinitions = + adminTrackingEventDefinitions.filter((definition) => definition.taskConfigEligible); + export function findAdminTrackingEventDefinition(eventKey: string) { const normalizedEventKey = eventKey.trim(); return ( @@ -26,12 +409,26 @@ export function findAdminTrackingEventDefinition(eventKey: string) { } export function filterAdminTrackingEventDefinitions(query: string) { + return filterTrackingEventDefinitions(adminTrackingEventDefinitions, query); +} + +export function filterAdminProfileTaskTrackingEventDefinitions(query: string) { + return filterTrackingEventDefinitions( + adminProfileTaskTrackingEventDefinitions, + query, + ); +} + +function filterTrackingEventDefinitions( + definitions: AdminTrackingEventDefinition[], + query: string, +) { const normalizedQuery = query.trim().toLowerCase(); if (!normalizedQuery) { - return adminTrackingEventDefinitions; + return definitions; } - return adminTrackingEventDefinitions.filter((definition) => { + return definitions.filter((definition) => { const haystack = [ definition.key, definition.title, diff --git a/apps/admin-web/src/pages/AdminTaskConfigPage.tsx b/apps/admin-web/src/pages/AdminTaskConfigPage.tsx index 2834003e..a8436199 100644 --- a/apps/admin-web/src/pages/AdminTaskConfigPage.tsx +++ b/apps/admin-web/src/pages/AdminTaskConfigPage.tsx @@ -13,7 +13,7 @@ import type { } from '../api/adminApiTypes'; import {useAdminWriteConfirm} from '../components/useAdminWriteConfirm'; import { - filterAdminTrackingEventDefinitions, + filterAdminProfileTaskTrackingEventDefinitions, findAdminTrackingEventDefinition, } from '../config/trackingEventDefinitions'; import {handlePageError} from './pageUtils'; @@ -68,7 +68,7 @@ export function AdminTaskConfigPage({ [eventKey], ); const filteredEventDefinitions = useMemo( - () => filterAdminTrackingEventDefinitions(eventKeySearch), + () => filterAdminProfileTaskTrackingEventDefinitions(eventKeySearch), [eventKeySearch], ); diff --git a/docs/technical/ADMIN_TRACKING_EVENT_DETAIL_EXPORT_2026-05-07.md b/docs/technical/ADMIN_TRACKING_EVENT_DETAIL_EXPORT_2026-05-07.md index 65c75a40..06d9f83d 100644 --- a/docs/technical/ADMIN_TRACKING_EVENT_DETAIL_EXPORT_2026-05-07.md +++ b/docs/technical/ADMIN_TRACKING_EVENT_DETAIL_EXPORT_2026-05-07.md @@ -72,7 +72,7 @@ GET /admin/api/tracking/events?eventKey=&userId=&scopeKind=&scopeId=&limit= 页面能力: -1. 顶部筛选区:Event Key、用户 ID、Scope Kind、Scope ID、刷新、导出 Excel。 +1. 顶部筛选区:Event Key、用户 ID、Scope Kind、Scope ID、刷新、导出 Excel。Event Key 候选来自后台前端的埋点定义注册表,需覆盖 `BACKEND_TRACKING_EVENT_COVERAGE_2026-05-09.md` 中已接入的通用埋点事件,不能只保留 `daily_login`。 2. 列表区:移动端可横向滚动,桌面端表格展示。 3. 详情区:每行有“详情”按钮,弹出独立面板展示完整字段与格式化后的 metadata JSON。 4. 导出:导出当前页面已加载结果,文件名形如 `tracking-events-2026-05-07.xls`。 diff --git a/docs/technical/PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md b/docs/technical/PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md index 41013165..a8567454 100644 --- a/docs/technical/PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md +++ b/docs/technical/PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md @@ -46,7 +46,7 @@ 用户成功登录时,认证链路会通过统一后端埋点 helper 幂等记录当日 `daily_login` 并刷新任务进度;用户打开任务中心只记录 `task_center_view` 浏览事件,不再承担每日登录事实写入。用户点击领取时,后端校验当日进度、领奖记录和配置状态,然后同事务写入领奖记录与钱包流水。 -后台任务配置页的 `Event Key` 使用可搜索下拉控件,选项来自前端后台的埋点定义注册表。当前注册表默认包含 `daily_login`,展示中文名称和备注;后续新增任务依赖的埋点时,应先补充注册表,再开放运营配置。 +后台任务配置页的 `Event Key` 使用可搜索下拉控件,选项来自前端后台的埋点定义注册表。后台全量埋点筛选候选应对齐 `BACKEND_TRACKING_EVENT_COVERAGE_2026-05-09.md` 的事件清单;任务配置页只展示标记为个人任务可用的事件,当前仅开放 `daily_login`,展示中文名称和备注。后续新增任务依赖的埋点时,应先补充注册表并显式标记任务可用,再开放运营配置。 ## 6. 接口