补齐后台埋点导出和任务事件选择
后台埋点查询支持日期筛选和导出全部模式 新增后台真实 event key 列表接口 任务配置页改用真实 user 埋点 key 候选 更新后台埋点查询文档和定向测试
This commit is contained in:
@@ -1,16 +1,20 @@
|
||||
import {describe, expect, test} from 'vitest';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import {
|
||||
adminProfileTaskTrackingEventDefinitions,
|
||||
adminTrackingEventDefinitions,
|
||||
buildAdminTrackingEventKeyOptions,
|
||||
filterAdminProfileTaskTrackingEventDefinitions,
|
||||
filterAdminTrackingEventKeyOptions,
|
||||
filterAdminTrackingEventDefinitions,
|
||||
findAdminTrackingEventDefinition,
|
||||
} from './trackingEventDefinitions';
|
||||
|
||||
describe('admin tracking event definitions', () => {
|
||||
test('后台埋点筛选候选包含后端通用埋点清单', () => {
|
||||
const keys = adminTrackingEventDefinitions.map((definition) => definition.key);
|
||||
const keys = adminTrackingEventDefinitions.map(
|
||||
(definition) => definition.key,
|
||||
);
|
||||
|
||||
expect(keys.length).toBeGreaterThan(40);
|
||||
expect(keys).toContain('daily_login');
|
||||
@@ -22,21 +26,48 @@ describe('admin tracking event definitions', () => {
|
||||
});
|
||||
|
||||
test('任务配置候选只开放适合个人任务的事件', () => {
|
||||
expect(adminProfileTaskTrackingEventDefinitions.map(({key}) => key)).toEqual([
|
||||
'daily_login',
|
||||
]);
|
||||
expect(filterAdminProfileTaskTrackingEventDefinitions('').map(({key}) => key)).toEqual([
|
||||
'daily_login',
|
||||
expect(
|
||||
adminProfileTaskTrackingEventDefinitions.map(({ key }) => key),
|
||||
).toEqual(['daily_login']);
|
||||
expect(
|
||||
filterAdminProfileTaskTrackingEventDefinitions('').map(({ key }) => key),
|
||||
).toEqual(['daily_login']);
|
||||
});
|
||||
|
||||
test('后台埋点 key 候选从真实库响应合并静态标题', () => {
|
||||
const options = buildAdminTrackingEventKeyOptions([
|
||||
{
|
||||
eventKey: 'work_play_start',
|
||||
eventTitle: 'work_play_start',
|
||||
scopeKinds: ['work', 'user'],
|
||||
},
|
||||
{
|
||||
eventKey: 'unknown_event',
|
||||
eventTitle: '未知事件',
|
||||
scopeKinds: ['user'],
|
||||
},
|
||||
]);
|
||||
|
||||
expect(options.find(({ key }) => key === 'work_play_start')?.title).toBe(
|
||||
'作品开始游玩',
|
||||
);
|
||||
expect(options.find(({ key }) => key === 'unknown_event')?.title).toBe(
|
||||
'未知事件',
|
||||
);
|
||||
expect(
|
||||
filterAdminTrackingEventKeyOptions(options, '作品').map(({ key }) => key),
|
||||
).toEqual(['work_play_start']);
|
||||
});
|
||||
|
||||
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('每日登录');
|
||||
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(
|
||||
'每日登录',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import type {TrackingScopeKind} from '../api/adminApiTypes';
|
||||
import type {
|
||||
AdminTrackingEventKeyPayload,
|
||||
TrackingScopeKind,
|
||||
} from '../api/adminApiTypes';
|
||||
|
||||
export interface AdminTrackingEventDefinition {
|
||||
key: string;
|
||||
@@ -8,6 +11,14 @@ export interface AdminTrackingEventDefinition {
|
||||
taskConfigEligible?: boolean;
|
||||
}
|
||||
|
||||
export interface AdminTrackingEventKeyOption {
|
||||
key: string;
|
||||
title: string;
|
||||
scopeKind: TrackingScopeKind | string;
|
||||
scopeKinds: string[];
|
||||
remark: string;
|
||||
}
|
||||
|
||||
export const adminTrackingEventDefinitions: AdminTrackingEventDefinition[] = [
|
||||
{
|
||||
key: 'auth_login_options_view',
|
||||
@@ -25,7 +36,8 @@ export const adminTrackingEventDefinitions: AdminTrackingEventDefinition[] = [
|
||||
key: 'daily_login',
|
||||
title: '每日登录',
|
||||
scopeKind: 'user',
|
||||
remark: '认证成功或 refresh 续期后由后端幂等记录,用于每日登录任务进度校验。',
|
||||
remark:
|
||||
'认证成功或 refresh 续期后由后端幂等记录,用于每日登录任务进度校验。',
|
||||
taskConfigEligible: true,
|
||||
},
|
||||
{
|
||||
@@ -368,7 +380,8 @@ export const adminTrackingEventDefinitions: AdminTrackingEventDefinition[] = [
|
||||
key: 'match3d_route_success',
|
||||
title: '抓大鹅路由成功',
|
||||
scopeKind: 'user',
|
||||
remark: '抓大鹅创作或运行接口成功响应后兜底记录;GET 入口可能按 site 统计。',
|
||||
remark:
|
||||
'抓大鹅创作或运行接口成功响应后兜底记录;GET 入口可能按 site 统计。',
|
||||
},
|
||||
{
|
||||
key: 'square_hole_route_success',
|
||||
@@ -392,12 +405,15 @@ export const adminTrackingEventDefinitions: AdminTrackingEventDefinition[] = [
|
||||
key: 'work_play_start',
|
||||
title: '作品开始游玩',
|
||||
scopeKind: 'work',
|
||||
remark: '拼图、抓大鹅、方洞、自定义世界、大鱼吃小鱼、Visual Novel 正式开始游玩时记录。',
|
||||
remark:
|
||||
'拼图、抓大鹅、方洞、自定义世界、大鱼吃小鱼、Visual Novel 正式开始游玩时记录。',
|
||||
},
|
||||
];
|
||||
|
||||
export const adminProfileTaskTrackingEventDefinitions =
|
||||
adminTrackingEventDefinitions.filter((definition) => definition.taskConfigEligible);
|
||||
adminTrackingEventDefinitions.filter(
|
||||
(definition) => definition.taskConfigEligible,
|
||||
);
|
||||
|
||||
export function findAdminTrackingEventDefinition(eventKey: string) {
|
||||
const normalizedEventKey = eventKey.trim();
|
||||
@@ -412,6 +428,41 @@ export function filterAdminTrackingEventDefinitions(query: string) {
|
||||
return filterTrackingEventDefinitions(adminTrackingEventDefinitions, query);
|
||||
}
|
||||
|
||||
export function buildAdminTrackingEventKeyOptions(
|
||||
eventKeys: AdminTrackingEventKeyPayload[],
|
||||
): AdminTrackingEventKeyOption[] {
|
||||
const options = new Map<string, AdminTrackingEventKeyOption>();
|
||||
for (const payload of eventKeys) {
|
||||
const key = payload.eventKey.trim();
|
||||
if (!key || options.has(key)) {
|
||||
continue;
|
||||
}
|
||||
const definition = findAdminTrackingEventDefinition(key);
|
||||
const scopeKinds = payload.scopeKinds.length
|
||||
? payload.scopeKinds
|
||||
: definition
|
||||
? [definition.scopeKind]
|
||||
: [];
|
||||
options.set(key, {
|
||||
key,
|
||||
title: definition?.title ?? (payload.eventTitle || key),
|
||||
scopeKind: definition?.scopeKind ?? scopeKinds[0] ?? '',
|
||||
scopeKinds,
|
||||
remark: definition?.remark ?? '真实埋点库中已出现的 event key。',
|
||||
});
|
||||
}
|
||||
return [...options.values()].sort((left, right) =>
|
||||
left.key.localeCompare(right.key),
|
||||
);
|
||||
}
|
||||
|
||||
export function filterAdminTrackingEventKeyOptions(
|
||||
options: AdminTrackingEventKeyOption[],
|
||||
query: string,
|
||||
) {
|
||||
return filterTrackingEventDefinitions(options, query);
|
||||
}
|
||||
|
||||
export function filterAdminProfileTaskTrackingEventDefinitions(query: string) {
|
||||
return filterTrackingEventDefinitions(
|
||||
adminProfileTaskTrackingEventDefinitions,
|
||||
@@ -420,7 +471,9 @@ export function filterAdminProfileTaskTrackingEventDefinitions(query: string) {
|
||||
}
|
||||
|
||||
function filterTrackingEventDefinitions(
|
||||
definitions: AdminTrackingEventDefinition[],
|
||||
definitions: Array<
|
||||
AdminTrackingEventDefinition | AdminTrackingEventKeyOption
|
||||
>,
|
||||
query: string,
|
||||
) {
|
||||
const normalizedQuery = query.trim().toLowerCase();
|
||||
|
||||
Reference in New Issue
Block a user