From b46ee4a18eed8a2c2182f207dbc049d7a15fdaf5 Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Sat, 18 Oct 2025 08:08:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Auth/WechatRegister.js | 19 ++++---- src/views/EventDetail/index.js | 19 ++++---- src/views/Pages/Profile/Profile.js | 4 ++ src/views/Profile/ProfilePage.js | 11 +++++ src/views/Settings/SettingsPage.js | 66 ++++++++++++++++----------- 5 files changed, 74 insertions(+), 45 deletions(-) diff --git a/src/components/Auth/WechatRegister.js b/src/components/Auth/WechatRegister.js index c55689b1..3771abe8 100644 --- a/src/components/Auth/WechatRegister.js +++ b/src/components/Auth/WechatRegister.js @@ -11,6 +11,7 @@ import { import { FaQrcode } from "react-icons/fa"; import { useNavigate } from "react-router-dom"; import { authService, WECHAT_STATUS, STATUS_MESSAGES } from "../../services/authService"; +import { logger } from "../../utils/logger"; // 配置常量 const POLL_INTERVAL = 2000; // 轮询间隔:2秒 @@ -109,7 +110,7 @@ export default function WechatRegister() { throw new Error(response?.error || '登录失败'); } } catch (error) { - console.error('登录失败:', error); + logger.error('WechatRegister', 'handleLoginSuccess', error, { sessionId }); showError("登录失败", error.message || "请重试"); } }, [navigate, showSuccess, showError]); @@ -126,7 +127,7 @@ export default function WechatRegister() { // 安全检查:确保 response 存在且包含 status if (!response || typeof response.status === 'undefined') { - console.warn('微信状态检查返回无效数据:', response); + logger.warn('WechatRegister', '微信状态检查返回无效数据', { response }); return; } @@ -156,7 +157,7 @@ export default function WechatRegister() { } } } catch (error) { - console.error("检查微信状态失败:", error); + logger.error('WechatRegister', 'checkWechatStatus', error, { sessionId: wechatSessionId }); // 轮询过程中的错误不显示给用户,避免频繁提示 // 但如果错误持续发生,停止轮询避免无限重试 if (error.message.includes('网络连接失败')) { @@ -222,7 +223,7 @@ export default function WechatRegister() { // 启动轮询检查扫码状态 startPolling(); } catch (error) { - console.error('获取微信授权失败:', error); + logger.error('WechatRegister', 'getWechatQRCode', error); if (isMountedRef.current) { showError("获取微信授权失败", error.message || "请稍后重试"); } @@ -241,7 +242,7 @@ export default function WechatRegister() { await getWechatQRCode(); } catch (error) { // 错误已经在 getWechatQRCode 中处理,这里只需要防止未捕获的 Promise rejection - console.error('QR code button click error (caught in handler):', error); + logger.error('WechatRegister', 'handleGetQRCodeClick', error); } }, [getWechatQRCode]); @@ -264,20 +265,20 @@ export default function WechatRegister() { useEffect(() => { // 只在有auth_url、session_id且状态为waiting时启动备用轮询 if (wechatAuthUrl && wechatSessionId && wechatStatus === WECHAT_STATUS.WAITING) { - console.log('备用轮询:启动备用轮询机制'); + logger.debug('WechatRegister', '备用轮询:启动备用轮询机制'); backupPollIntervalRef.current = setInterval(() => { try { if (wechatStatus === WECHAT_STATUS.WAITING && isMountedRef.current) { - console.log('备用轮询:检查微信状态'); + logger.debug('WechatRegister', '备用轮询:检查微信状态'); // 添加 .catch() 静默处理异步错误,防止被 ErrorBoundary 捕获 checkWechatStatus().catch(error => { - console.warn('备用轮询检查失败(静默处理):', error); + logger.warn('WechatRegister', '备用轮询检查失败(静默处理)', { error: error.message }); }); } } catch (error) { // 捕获所有同步错误,防止被 ErrorBoundary 捕获 - console.warn('备用轮询执行出错(静默处理):', error); + logger.warn('WechatRegister', '备用轮询执行出错(静默处理)', { error: error.message }); } }, BACKUP_POLL_INTERVAL); } diff --git a/src/views/EventDetail/index.js b/src/views/EventDetail/index.js index 2eec4d6f..e18e3b61 100644 --- a/src/views/EventDetail/index.js +++ b/src/views/EventDetail/index.js @@ -74,10 +74,11 @@ import TransmissionChainAnalysis from './components/TransmissionChainAnalysis'; // 导入你的 Flask API 服务 import { eventService } from '../../services/eventService'; import { debugEventService } from '../../utils/debugEventService'; +import { logger } from '../../utils/logger'; // 临时调试代码 - 生产环境测试后请删除 if (typeof window !== 'undefined') { - console.log('EventDetail - 调试 eventService'); + logger.debug('EventDetail', '调试 eventService'); debugEventService(); } @@ -131,7 +132,7 @@ const PostItem = ({ post, onRefresh }) => { setComments(result.data); } } catch (error) { - console.error('Failed to load comments:', error); + logger.error('PostItem', 'loadComments', error, { postId: post.id }); } finally { setIsLoading(false); } @@ -383,7 +384,7 @@ const EventDetail = () => { const stocksResponse = await eventService.getRelatedStocks(actualEventId); setRelatedStocks(stocksResponse.data || []); } catch (e) { - console.warn('加载相关股票失败:', e); + logger.warn('EventDetail', '加载相关股票失败', { eventId: actualEventId, error: e.message }); setRelatedStocks([]); } @@ -393,7 +394,7 @@ const EventDetail = () => { const conceptsResponse = await eventService.getRelatedConcepts(actualEventId); setRelatedConcepts(conceptsResponse.data || []); } 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); setHistoricalEvents(eventsResponse.data || []); } catch (e) { - console.warn('历史事件加载失败', e); + logger.warn('EventDetail', '历史事件加载失败', { eventId: actualEventId, error: e.message }); } } catch (err) { - console.error('Error loading event data:', err); + logger.error('EventDetail', 'loadEventData', err, { eventId: actualEventId }); setError(err.message || '加载事件数据失败'); } finally { setLoading(false); @@ -419,7 +420,7 @@ const EventDetail = () => { const stocksResponse = await eventService.getRelatedStocks(actualEventId); setRelatedStocks(stocksResponse.data); } catch (err) { - console.error('重新获取股票数据失败:', err); + logger.error('EventDetail', 'refetchStocks', err, { eventId: actualEventId }); } }; @@ -435,7 +436,7 @@ const EventDetail = () => { : prev.follower_count + 1 })); } catch (err) { - console.error('关注操作失败:', err); + logger.error('EventDetail', 'handleFollowToggle', err, { eventId: actualEventId }); } }; @@ -448,7 +449,7 @@ const EventDetail = () => { setPosts(result.data || []); } } catch (err) { - console.error('加载帖子失败:', err); + logger.error('EventDetail', 'loadPosts', err, { eventId: actualEventId }); } finally { setPostsLoading(false); } diff --git a/src/views/Pages/Profile/Profile.js b/src/views/Pages/Profile/Profile.js index 7b1dc8f4..5f976988 100755 --- a/src/views/Pages/Profile/Profile.js +++ b/src/views/Pages/Profile/Profile.js @@ -24,6 +24,7 @@ import { useDisclosure, } from "@chakra-ui/react"; import { useAuth } from "../../../contexts/AuthContext"; +import { logger } from "../../../utils/logger"; export default function Profile() { const { colorMode } = useColorMode(); @@ -32,7 +33,10 @@ export default function Profile() { const { isOpen, onOpen, onClose } = useDisclosure(); const handleLogout = () => { + logger.info('Profile', '用户登出', { userId: user?.id }); logout(); + + // ✅ 保留登出成功toast(关键操作提示) toast({ title: "已登出", description: "您已成功退出登录", diff --git a/src/views/Profile/ProfilePage.js b/src/views/Profile/ProfilePage.js index 688033b1..b5099c65 100644 --- a/src/views/Profile/ProfilePage.js +++ b/src/views/Profile/ProfilePage.js @@ -43,6 +43,7 @@ import { } from '@chakra-ui/react'; import { EditIcon, CheckIcon, CloseIcon, AddIcon } from '@chakra-ui/icons'; import { useAuth } from '../../contexts/AuthContext'; +import { logger } from '../../utils/logger'; export default function ProfilePage() { const { user, updateUser } = useAuth(); @@ -86,12 +87,15 @@ export default function ProfilePage() { creator_tags: formData.creator_tags.join(',') }; + logger.debug('ProfilePage', '保存个人资料', { userId: user?.id }); + // 模拟API调用 await new Promise(resolve => setTimeout(resolve, 1000)); updateUser(updatedData); setIsEditing(false); + // ✅ 保留关键操作提示 toast({ title: "个人资料更新成功", status: "success", @@ -99,6 +103,9 @@ export default function ProfilePage() { isClosable: true, }); } catch (error) { + logger.error('ProfilePage', 'handleSaveProfile', error, { userId: user?.id }); + + // ✅ 保留错误提示 toast({ title: "更新失败", description: error.message, @@ -114,10 +121,14 @@ export default function ProfilePage() { const handleAvatarUpload = (event) => { const file = event.target.files[0]; if (file) { + logger.debug('ProfilePage', '上传头像', { fileName: file.name, fileSize: file.size }); + // 这里应该上传文件到服务器 const reader = new FileReader(); reader.onload = (e) => { updateUser({ avatar_url: e.target.result }); + + // ✅ 保留关键操作提示 toast({ title: "头像更新成功", status: "success", diff --git a/src/views/Settings/SettingsPage.js b/src/views/Settings/SettingsPage.js index a3405520..736465fe 100644 --- a/src/views/Settings/SettingsPage.js +++ b/src/views/Settings/SettingsPage.js @@ -57,6 +57,7 @@ import { } from '@chakra-ui/icons'; import { FaWeixin, FaMobile, FaEnvelope } from 'react-icons/fa'; import { useAuth } from '../../contexts/AuthContext'; +import { logger } from '../../utils/logger'; export default function SettingsPage() { const { user, updateUser, logout } = useAuth(); @@ -117,24 +118,28 @@ export default function SettingsPage() { // 获取密码状态 const fetchPasswordStatus = async () => { 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"; - + + logger.api.request('GET', '/api/account/password-status', null); + const response = await fetch(`${API_BASE_URL}/api/account/password-status`, { method: 'GET', credentials: 'include' }); - + if (response.ok) { const data = await response.json(); + logger.api.response('GET', '/api/account/password-status', response.status, data); + if (data.success) { - console.log('密码状态数据:', data.data); // 调试信息 + logger.debug('SettingsPage', '密码状态获取成功', data.data); setPasswordStatus(data.data); } } } catch (error) { - console.error('获取密码状态失败:', error); + logger.error('SettingsPage', 'fetchPasswordStatus', error); } finally { setPasswordStatusLoading(false); } @@ -249,34 +254,41 @@ export default function SettingsPage() { setIsLoading(true); try { 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', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ phone: phoneForm.phone }) }); const data = await res.json(); + logger.api.response('POST', url, res.status, data); + if (!res.ok) throw new Error(data.error || '发送失败'); } else { + const url = '/api/account/email/send-bind-code'; + logger.api.request('POST', url, { email: emailForm.email.substring(0, 3) + '***@***' }); + // 使用绑定邮箱的验证码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', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ email: emailForm.email }) }); const data = await res.json(); + logger.api.response('POST', url, res.status, data); + if (!res.ok) throw new Error(data.error || '发送失败'); } - toast({ - title: "验证码已发送", - description: `请查收${type === 'phone' ? '短信' : '邮件'}`, - status: "success", - duration: 3000, - isClosable: true, - }); + // ❌ 移除验证码发送成功toast + logger.info('SettingsPage', `${type === 'phone' ? '短信' : '邮件'}验证码已发送`); } catch (error) { + logger.error('SettingsPage', 'sendVerificationCode', error, { type }); + toast({ title: "发送失败", description: error.message, @@ -381,18 +393,18 @@ export default function SettingsPage() { const saveNotificationSettings = async () => { setIsLoading(true); try { + logger.debug('SettingsPage', '保存通知设置', notifications); + // 这里应该调用后端API保存设置 await new Promise(resolve => setTimeout(resolve, 1000)); updateUser(notifications); - toast({ - title: "通知设置已保存", - status: "success", - duration: 3000, - isClosable: true, - }); + // ❌ 移除设置保存成功toast + logger.info('SettingsPage', '通知设置已保存'); } catch (error) { + logger.error('SettingsPage', 'saveNotificationSettings', error); + toast({ title: "保存失败", description: error.message, @@ -409,6 +421,8 @@ export default function SettingsPage() { const savePrivacySettings = async () => { setIsLoading(true); try { + logger.debug('SettingsPage', '保存隐私设置', { privacy, blockedKeywords }); + // 这里应该调用后端API保存设置 await new Promise(resolve => setTimeout(resolve, 1000)); @@ -417,13 +431,11 @@ export default function SettingsPage() { blocked_keywords: blockedKeywords }); - toast({ - title: "隐私设置已保存", - status: "success", - duration: 3000, - isClosable: true, - }); + // ❌ 移除设置保存成功toast + logger.info('SettingsPage', '隐私设置已保存'); } catch (error) { + logger.error('SettingsPage', 'savePrivacySettings', error); + toast({ title: "保存失败", description: error.message,