feat: 添加日志

This commit is contained in:
zdl
2025-10-18 08:08:58 +08:00
parent 36558e0715
commit b46ee4a18e
5 changed files with 74 additions and 45 deletions

View File

@@ -11,6 +11,7 @@ import {
import { FaQrcode } from "react-icons/fa"; import { FaQrcode } from "react-icons/fa";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { authService, WECHAT_STATUS, STATUS_MESSAGES } from "../../services/authService"; import { authService, WECHAT_STATUS, STATUS_MESSAGES } from "../../services/authService";
import { logger } from "../../utils/logger";
// 配置常量 // 配置常量
const POLL_INTERVAL = 2000; // 轮询间隔2秒 const POLL_INTERVAL = 2000; // 轮询间隔2秒
@@ -109,7 +110,7 @@ export default function WechatRegister() {
throw new Error(response?.error || '登录失败'); throw new Error(response?.error || '登录失败');
} }
} catch (error) { } catch (error) {
console.error('登录失败:', error); logger.error('WechatRegister', 'handleLoginSuccess', error, { sessionId });
showError("登录失败", error.message || "请重试"); showError("登录失败", error.message || "请重试");
} }
}, [navigate, showSuccess, showError]); }, [navigate, showSuccess, showError]);
@@ -126,7 +127,7 @@ export default function WechatRegister() {
// 安全检查:确保 response 存在且包含 status // 安全检查:确保 response 存在且包含 status
if (!response || typeof response.status === 'undefined') { if (!response || typeof response.status === 'undefined') {
console.warn('微信状态检查返回无效数据:', response); logger.warn('WechatRegister', '微信状态检查返回无效数据', { response });
return; return;
} }
@@ -156,7 +157,7 @@ export default function WechatRegister() {
} }
} }
} catch (error) { } catch (error) {
console.error("检查微信状态失败:", error); logger.error('WechatRegister', 'checkWechatStatus', error, { sessionId: wechatSessionId });
// 轮询过程中的错误不显示给用户,避免频繁提示 // 轮询过程中的错误不显示给用户,避免频繁提示
// 但如果错误持续发生,停止轮询避免无限重试 // 但如果错误持续发生,停止轮询避免无限重试
if (error.message.includes('网络连接失败')) { if (error.message.includes('网络连接失败')) {
@@ -222,7 +223,7 @@ export default function WechatRegister() {
// 启动轮询检查扫码状态 // 启动轮询检查扫码状态
startPolling(); startPolling();
} catch (error) { } catch (error) {
console.error('获取微信授权失败:', error); logger.error('WechatRegister', 'getWechatQRCode', error);
if (isMountedRef.current) { if (isMountedRef.current) {
showError("获取微信授权失败", error.message || "请稍后重试"); showError("获取微信授权失败", error.message || "请稍后重试");
} }
@@ -241,7 +242,7 @@ export default function WechatRegister() {
await getWechatQRCode(); await getWechatQRCode();
} catch (error) { } catch (error) {
// 错误已经在 getWechatQRCode 中处理,这里只需要防止未捕获的 Promise rejection // 错误已经在 getWechatQRCode 中处理,这里只需要防止未捕获的 Promise rejection
console.error('QR code button click error (caught in handler):', error); logger.error('WechatRegister', 'handleGetQRCodeClick', error);
} }
}, [getWechatQRCode]); }, [getWechatQRCode]);
@@ -264,20 +265,20 @@ export default function WechatRegister() {
useEffect(() => { useEffect(() => {
// 只在有auth_url、session_id且状态为waiting时启动备用轮询 // 只在有auth_url、session_id且状态为waiting时启动备用轮询
if (wechatAuthUrl && wechatSessionId && wechatStatus === WECHAT_STATUS.WAITING) { if (wechatAuthUrl && wechatSessionId && wechatStatus === WECHAT_STATUS.WAITING) {
console.log('备用轮询:启动备用轮询机制'); logger.debug('WechatRegister', '备用轮询:启动备用轮询机制');
backupPollIntervalRef.current = setInterval(() => { backupPollIntervalRef.current = setInterval(() => {
try { try {
if (wechatStatus === WECHAT_STATUS.WAITING && isMountedRef.current) { if (wechatStatus === WECHAT_STATUS.WAITING && isMountedRef.current) {
console.log('备用轮询:检查微信状态'); logger.debug('WechatRegister', '备用轮询:检查微信状态');
// 添加 .catch() 静默处理异步错误,防止被 ErrorBoundary 捕获 // 添加 .catch() 静默处理异步错误,防止被 ErrorBoundary 捕获
checkWechatStatus().catch(error => { checkWechatStatus().catch(error => {
console.warn('备用轮询检查失败(静默处理):', error); logger.warn('WechatRegister', '备用轮询检查失败(静默处理)', { error: error.message });
}); });
} }
} catch (error) { } catch (error) {
// 捕获所有同步错误,防止被 ErrorBoundary 捕获 // 捕获所有同步错误,防止被 ErrorBoundary 捕获
console.warn('备用轮询执行出错(静默处理):', error); logger.warn('WechatRegister', '备用轮询执行出错(静默处理)', { error: error.message });
} }
}, BACKUP_POLL_INTERVAL); }, BACKUP_POLL_INTERVAL);
} }

View File

@@ -74,10 +74,11 @@ import TransmissionChainAnalysis from './components/TransmissionChainAnalysis';
// 导入你的 Flask API 服务 // 导入你的 Flask API 服务
import { eventService } from '../../services/eventService'; import { eventService } from '../../services/eventService';
import { debugEventService } from '../../utils/debugEventService'; import { debugEventService } from '../../utils/debugEventService';
import { logger } from '../../utils/logger';
// 临时调试代码 - 生产环境测试后请删除 // 临时调试代码 - 生产环境测试后请删除
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
console.log('EventDetail - 调试 eventService'); logger.debug('EventDetail', '调试 eventService');
debugEventService(); debugEventService();
} }
@@ -131,7 +132,7 @@ const PostItem = ({ post, onRefresh }) => {
setComments(result.data); setComments(result.data);
} }
} catch (error) { } catch (error) {
console.error('Failed to load comments:', error); logger.error('PostItem', 'loadComments', error, { postId: post.id });
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
@@ -383,7 +384,7 @@ const EventDetail = () => {
const stocksResponse = await eventService.getRelatedStocks(actualEventId); const stocksResponse = await eventService.getRelatedStocks(actualEventId);
setRelatedStocks(stocksResponse.data || []); setRelatedStocks(stocksResponse.data || []);
} catch (e) { } catch (e) {
console.warn('加载相关股票失败:', e); logger.warn('EventDetail', '加载相关股票失败', { eventId: actualEventId, error: e.message });
setRelatedStocks([]); setRelatedStocks([]);
} }
@@ -393,7 +394,7 @@ const EventDetail = () => {
const conceptsResponse = await eventService.getRelatedConcepts(actualEventId); const conceptsResponse = await eventService.getRelatedConcepts(actualEventId);
setRelatedConcepts(conceptsResponse.data || []); setRelatedConcepts(conceptsResponse.data || []);
} catch (e) { } catch (e) {
console.warn('加载相关概念失败:', e); logger.warn('EventDetail', '加载相关概念失败', { eventId: actualEventId, error: e.message });
} }
} }
@@ -402,11 +403,11 @@ const EventDetail = () => {
const eventsResponse = await eventService.getHistoricalEvents(actualEventId); const eventsResponse = await eventService.getHistoricalEvents(actualEventId);
setHistoricalEvents(eventsResponse.data || []); setHistoricalEvents(eventsResponse.data || []);
} catch (e) { } catch (e) {
console.warn('历史事件加载失败', e); logger.warn('EventDetail', '历史事件加载失败', { eventId: actualEventId, error: e.message });
} }
} catch (err) { } catch (err) {
console.error('Error loading event data:', err); logger.error('EventDetail', 'loadEventData', err, { eventId: actualEventId });
setError(err.message || '加载事件数据失败'); setError(err.message || '加载事件数据失败');
} finally { } finally {
setLoading(false); setLoading(false);
@@ -419,7 +420,7 @@ const EventDetail = () => {
const stocksResponse = await eventService.getRelatedStocks(actualEventId); const stocksResponse = await eventService.getRelatedStocks(actualEventId);
setRelatedStocks(stocksResponse.data); setRelatedStocks(stocksResponse.data);
} catch (err) { } catch (err) {
console.error('重新获取股票数据失败:', err); logger.error('EventDetail', 'refetchStocks', err, { eventId: actualEventId });
} }
}; };
@@ -435,7 +436,7 @@ const EventDetail = () => {
: prev.follower_count + 1 : prev.follower_count + 1
})); }));
} catch (err) { } catch (err) {
console.error('关注操作失败:', err); logger.error('EventDetail', 'handleFollowToggle', err, { eventId: actualEventId });
} }
}; };
@@ -448,7 +449,7 @@ const EventDetail = () => {
setPosts(result.data || []); setPosts(result.data || []);
} }
} catch (err) { } catch (err) {
console.error('加载帖子失败:', err); logger.error('EventDetail', 'loadPosts', err, { eventId: actualEventId });
} finally { } finally {
setPostsLoading(false); setPostsLoading(false);
} }

View File

@@ -24,6 +24,7 @@ import {
useDisclosure, useDisclosure,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { useAuth } from "../../../contexts/AuthContext"; import { useAuth } from "../../../contexts/AuthContext";
import { logger } from "../../../utils/logger";
export default function Profile() { export default function Profile() {
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
@@ -32,7 +33,10 @@ export default function Profile() {
const { isOpen, onOpen, onClose } = useDisclosure(); const { isOpen, onOpen, onClose } = useDisclosure();
const handleLogout = () => { const handleLogout = () => {
logger.info('Profile', '用户登出', { userId: user?.id });
logout(); logout();
// ✅ 保留登出成功toast关键操作提示
toast({ toast({
title: "已登出", title: "已登出",
description: "您已成功退出登录", description: "您已成功退出登录",

View File

@@ -43,6 +43,7 @@ import {
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { EditIcon, CheckIcon, CloseIcon, AddIcon } from '@chakra-ui/icons'; import { EditIcon, CheckIcon, CloseIcon, AddIcon } from '@chakra-ui/icons';
import { useAuth } from '../../contexts/AuthContext'; import { useAuth } from '../../contexts/AuthContext';
import { logger } from '../../utils/logger';
export default function ProfilePage() { export default function ProfilePage() {
const { user, updateUser } = useAuth(); const { user, updateUser } = useAuth();
@@ -86,12 +87,15 @@ export default function ProfilePage() {
creator_tags: formData.creator_tags.join(',') creator_tags: formData.creator_tags.join(',')
}; };
logger.debug('ProfilePage', '保存个人资料', { userId: user?.id });
// 模拟API调用 // 模拟API调用
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));
updateUser(updatedData); updateUser(updatedData);
setIsEditing(false); setIsEditing(false);
// ✅ 保留关键操作提示
toast({ toast({
title: "个人资料更新成功", title: "个人资料更新成功",
status: "success", status: "success",
@@ -99,6 +103,9 @@ export default function ProfilePage() {
isClosable: true, isClosable: true,
}); });
} catch (error) { } catch (error) {
logger.error('ProfilePage', 'handleSaveProfile', error, { userId: user?.id });
// ✅ 保留错误提示
toast({ toast({
title: "更新失败", title: "更新失败",
description: error.message, description: error.message,
@@ -114,10 +121,14 @@ export default function ProfilePage() {
const handleAvatarUpload = (event) => { const handleAvatarUpload = (event) => {
const file = event.target.files[0]; const file = event.target.files[0];
if (file) { if (file) {
logger.debug('ProfilePage', '上传头像', { fileName: file.name, fileSize: file.size });
// 这里应该上传文件到服务器 // 这里应该上传文件到服务器
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (e) => { reader.onload = (e) => {
updateUser({ avatar_url: e.target.result }); updateUser({ avatar_url: e.target.result });
// ✅ 保留关键操作提示
toast({ toast({
title: "头像更新成功", title: "头像更新成功",
status: "success", status: "success",

View File

@@ -57,6 +57,7 @@ import {
} from '@chakra-ui/icons'; } from '@chakra-ui/icons';
import { FaWeixin, FaMobile, FaEnvelope } from 'react-icons/fa'; import { FaWeixin, FaMobile, FaEnvelope } from 'react-icons/fa';
import { useAuth } from '../../contexts/AuthContext'; import { useAuth } from '../../contexts/AuthContext';
import { logger } from '../../utils/logger';
export default function SettingsPage() { export default function SettingsPage() {
const { user, updateUser, logout } = useAuth(); const { user, updateUser, logout } = useAuth();
@@ -117,24 +118,28 @@ export default function SettingsPage() {
// 获取密码状态 // 获取密码状态
const fetchPasswordStatus = async () => { const fetchPasswordStatus = async () => {
try { try {
const API_BASE_URL = process.env.NODE_ENV === 'production' const API_BASE_URL = process.env.NODE_ENV === 'production'
? "" ? ""
: process.env.REACT_APP_API_URL || "http://49.232.185.254:5001"; : process.env.REACT_APP_API_URL || "http://49.232.185.254:5001";
logger.api.request('GET', '/api/account/password-status', null);
const response = await fetch(`${API_BASE_URL}/api/account/password-status`, { const response = await fetch(`${API_BASE_URL}/api/account/password-status`, {
method: 'GET', method: 'GET',
credentials: 'include' credentials: 'include'
}); });
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
logger.api.response('GET', '/api/account/password-status', response.status, data);
if (data.success) { if (data.success) {
console.log('密码状态数据:', data.data); // 调试信息 logger.debug('SettingsPage', '密码状态获取成功', data.data);
setPasswordStatus(data.data); setPasswordStatus(data.data);
} }
} }
} catch (error) { } catch (error) {
console.error('获取密码状态失败:', error); logger.error('SettingsPage', 'fetchPasswordStatus', error);
} finally { } finally {
setPasswordStatusLoading(false); setPasswordStatusLoading(false);
} }
@@ -249,34 +254,41 @@ export default function SettingsPage() {
setIsLoading(true); setIsLoading(true);
try { try {
if (type === 'phone') { if (type === 'phone') {
const res = await fetch((process.env.NODE_ENV === 'production' ? '' : process.env.REACT_APP_API_URL || 'http://49.232.185.254:5001') + '/api/account/phone/send-code', { const url = '/api/account/phone/send-code';
logger.api.request('POST', url, { phone: phoneForm.phone.substring(0, 3) + '****' });
const res = await fetch((process.env.NODE_ENV === 'production' ? '' : process.env.REACT_APP_API_URL || 'http://49.232.185.254:5001') + url, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
credentials: 'include', credentials: 'include',
body: JSON.stringify({ phone: phoneForm.phone }) body: JSON.stringify({ phone: phoneForm.phone })
}); });
const data = await res.json(); const data = await res.json();
logger.api.response('POST', url, res.status, data);
if (!res.ok) throw new Error(data.error || '发送失败'); if (!res.ok) throw new Error(data.error || '发送失败');
} else { } else {
const url = '/api/account/email/send-bind-code';
logger.api.request('POST', url, { email: emailForm.email.substring(0, 3) + '***@***' });
// 使用绑定邮箱的验证码API // 使用绑定邮箱的验证码API
const res = await fetch((process.env.NODE_ENV === 'production' ? '' : process.env.REACT_APP_API_URL || 'http://49.232.185.254:5001') + '/api/account/email/send-bind-code', { const res = await fetch((process.env.NODE_ENV === 'production' ? '' : process.env.REACT_APP_API_URL || 'http://49.232.185.254:5001') + url, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
credentials: 'include', credentials: 'include',
body: JSON.stringify({ email: emailForm.email }) body: JSON.stringify({ email: emailForm.email })
}); });
const data = await res.json(); const data = await res.json();
logger.api.response('POST', url, res.status, data);
if (!res.ok) throw new Error(data.error || '发送失败'); if (!res.ok) throw new Error(data.error || '发送失败');
} }
toast({ // ❌ 移除验证码发送成功toast
title: "验证码已发送", logger.info('SettingsPage', `${type === 'phone' ? '短信' : '邮件'}验证码已发送`);
description: `请查收${type === 'phone' ? '短信' : '邮件'}`,
status: "success",
duration: 3000,
isClosable: true,
});
} catch (error) { } catch (error) {
logger.error('SettingsPage', 'sendVerificationCode', error, { type });
toast({ toast({
title: "发送失败", title: "发送失败",
description: error.message, description: error.message,
@@ -381,18 +393,18 @@ export default function SettingsPage() {
const saveNotificationSettings = async () => { const saveNotificationSettings = async () => {
setIsLoading(true); setIsLoading(true);
try { try {
logger.debug('SettingsPage', '保存通知设置', notifications);
// 这里应该调用后端API保存设置 // 这里应该调用后端API保存设置
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));
updateUser(notifications); updateUser(notifications);
toast({ // ❌ 移除设置保存成功toast
title: "通知设置已保存", logger.info('SettingsPage', '通知设置已保存');
status: "success",
duration: 3000,
isClosable: true,
});
} catch (error) { } catch (error) {
logger.error('SettingsPage', 'saveNotificationSettings', error);
toast({ toast({
title: "保存失败", title: "保存失败",
description: error.message, description: error.message,
@@ -409,6 +421,8 @@ export default function SettingsPage() {
const savePrivacySettings = async () => { const savePrivacySettings = async () => {
setIsLoading(true); setIsLoading(true);
try { try {
logger.debug('SettingsPage', '保存隐私设置', { privacy, blockedKeywords });
// 这里应该调用后端API保存设置 // 这里应该调用后端API保存设置
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));
@@ -417,13 +431,11 @@ export default function SettingsPage() {
blocked_keywords: blockedKeywords blocked_keywords: blockedKeywords
}); });
toast({ // ❌ 移除设置保存成功toast
title: "隐私设置已保存", logger.info('SettingsPage', '隐私设置已保存');
status: "success",
duration: 3000,
isClosable: true,
});
} catch (error) { } catch (error) {
logger.error('SettingsPage', 'savePrivacySettings', error);
toast({ toast({
title: "保存失败", title: "保存失败",
description: error.message, description: error.message,