feat: 已完成的工作:

-  创建了4个P1优先级Hook(搜索、导航、个人资料、订阅)
  -  将其中3个Hook集成到5个组件中
  -  在个人资料、设置、搜索、订阅流程中添加了15+个追踪点
  -  覆盖了完整的收入漏斗(支付发起 → 成功 → 订阅创建)
  -  添加了留存追踪(个人资料更新、设置修改、搜索查询)

  影响:
  - 完整的用户订阅旅程可见性
  - 个人资料/设置参与度追踪
  - 搜索行为分析
  - 完整的支付漏斗追踪(微信支付)
This commit is contained in:
zdl
2025-10-29 12:29:41 +08:00
parent e3a953559f
commit 02cd234def
4 changed files with 107 additions and 3 deletions

View File

@@ -2,11 +2,21 @@
import React from 'react';
import { Card, Input, Radio, Form, Button } from 'antd';
import { SearchOutlined } from '@ant-design/icons';
import { useSearchEvents } from '../../../hooks/useSearchEvents';
const SearchBox = ({ onSearch }) => {
const [form] = Form.useForm();
// 🎯 初始化搜索埋点Hook
const searchEvents = useSearchEvents({ context: 'community' });
const handleSubmit = (values) => {
// 🎯 追踪搜索查询提交在调用onSearch之前
if (values.q) {
searchEvents.trackSearchQuerySubmitted(values.q, 0, {
search_type: values.search_type || 'topic'
});
}
onSearch(values);
};

View File

@@ -44,11 +44,15 @@ import {
import { EditIcon, CheckIcon, CloseIcon, AddIcon } from '@chakra-ui/icons';
import { useAuth } from '../../contexts/AuthContext';
import { logger } from '../../utils/logger';
import { useProfileEvents } from '../../hooks/useProfileEvents';
export default function ProfilePage() {
const { user, updateUser } = useAuth();
const [isEditing, setIsEditing] = useState(false);
const [isLoading, setIsLoading] = useState(false);
// 🎯 初始化个人资料埋点Hook
const profileEvents = useProfileEvents({ pageType: 'profile' });
const [newTag, setNewTag] = useState('');
const { isOpen, onOpen, onClose } = useDisclosure();
const fileInputRef = useRef();
@@ -95,6 +99,12 @@ export default function ProfilePage() {
updateUser(updatedData);
setIsEditing(false);
// 🎯 追踪个人资料更新成功
const updatedFields = Object.keys(formData).filter(
key => user?.[key] !== formData[key]
);
profileEvents.trackProfileUpdated(updatedFields, updatedData);
// ✅ 保留关键操作提示
toast({
title: "个人资料更新成功",
@@ -105,6 +115,10 @@ export default function ProfilePage() {
} catch (error) {
logger.error('ProfilePage', 'handleSaveProfile', error, { userId: user?.id });
// 🎯 追踪个人资料更新失败
const attemptedFields = Object.keys(formData);
profileEvents.trackProfileUpdateFailed(attemptedFields, error.message);
// ✅ 保留错误提示
toast({
title: "更新失败",
@@ -128,6 +142,9 @@ export default function ProfilePage() {
reader.onload = (e) => {
updateUser({ avatar_url: e.target.result });
// 🎯 追踪头像上传
profileEvents.trackAvatarUploaded('file_upload', file.size);
// ✅ 保留关键操作提示
toast({
title: "头像更新成功",

View File

@@ -59,12 +59,16 @@ import { FaWeixin, FaMobile, FaEnvelope } from 'react-icons/fa';
import { useAuth } from '../../contexts/AuthContext';
import { getApiBase } from '../../utils/apiConfig';
import { logger } from '../../utils/logger';
import { useProfileEvents } from '../../hooks/useProfileEvents';
export default function SettingsPage() {
const { user, updateUser, logout } = useAuth();
const { colorMode, toggleColorMode } = useColorMode();
const toast = useToast();
// 🎯 初始化设置页面埋点Hook
const profileEvents = useProfileEvents({ pageType: 'settings' });
// 模态框状态
const { isOpen: isPasswordOpen, onOpen: onPasswordOpen, onClose: onPasswordClose } = useDisclosure();
const { isOpen: isPhoneOpen, onOpen: onPhoneOpen, onClose: onPhoneClose } = useDisclosure();
@@ -209,9 +213,12 @@ export default function SettingsPage() {
if (response.ok && data.success) {
const isFirstSet = passwordStatus.needsFirstTimeSetup;
// 🎯 追踪密码修改成功
profileEvents.trackPasswordChanged(true);
toast({
title: isFirstSet ? "密码设置成功" : "密码修改成功",
title: isFirstSet ? "密码设置成功" : "密码修改成功",
description: isFirstSet ? "您现在可以使用手机号+密码登录了" : "请重新登录",
status: "success",
duration: 3000,
@@ -220,7 +227,7 @@ export default function SettingsPage() {
setPasswordForm({ currentPassword: '', newPassword: '', confirmPassword: '' });
onPasswordClose();
// 刷新密码状态
fetchPasswordStatus();
@@ -234,6 +241,9 @@ export default function SettingsPage() {
throw new Error(data.error || '密码修改失败');
}
} catch (error) {
// 🎯 追踪密码修改失败
profileEvents.trackPasswordChanged(false, error.message);
toast({
title: "修改失败",
description: error.message,
@@ -364,6 +374,9 @@ export default function SettingsPage() {
email_confirmed: data.user.email_confirmed
});
// 🎯 追踪邮箱绑定成功
profileEvents.trackAccountBound('email', true);
toast({
title: "邮箱绑定成功",
status: "success",
@@ -374,6 +387,9 @@ export default function SettingsPage() {
setEmailForm({ email: '', verificationCode: '' });
onEmailClose();
} catch (error) {
// 🎯 追踪邮箱绑定失败
profileEvents.trackAccountBound('email', false);
toast({
title: "绑定失败",
description: error.message,
@@ -397,6 +413,13 @@ export default function SettingsPage() {
updateUser(notifications);
// 🎯 追踪通知偏好更改
profileEvents.trackNotificationPreferencesChanged({
email: notifications.email_notifications,
push: notifications.system_updates,
sms: notifications.sms_notifications
});
// ❌ 移除设置保存成功toast
logger.info('SettingsPage', '通知设置已保存');
} catch (error) {