feat: 1. 基础设施(2个文件)
- ✅ src/utils/logger.js - 统一日志工具 - API 请求/响应/错误日志 - 组件错误/警告/调试日志 - 开发环境详细分组,生产环境仅错误 - ✅ src/utils/axiosConfig.js - axios 全局拦截器 - 自动记录所有请求/响应 - 统一 baseURL 和 credentials 配置\ 2. 核心文件重构(8个文件)\ AuthFormContent.js | ✅ 保留登录/注册成功 toast❌ 移除验证码发送 toast✅ 添加 .trim()✅ 所有 API 添加 logger | ✅ 完成 | | Center.js | ❌ 移除所有 toast✅ 移除 toast 依赖✅ 添加错误 logger | ✅ 完成 | | Community/index.js | ❌ 移除所有 toast 和导入✅ 移除 toast 依赖✅ 添加错误 logger | ✅ 完成 | | authService.js | ✅ 统一 apiRequest 函数✅ 所有请求自动记录❌ 移除 console.error | ✅ 完成 | | eventService.js | ✅ 重构 apiRequest✅ 所有方法添加 logger❌ 移除 console.log/error | ✅ 完成 | | stockService | ✅ 所有方法添加 logger❌ 移除 console 输出 | ✅ 完成 | | indexService | ✅ 添加 logger❌ 移除 console 输出 | ✅ 完成 | | AuthContext.js | ✅ 保留注册/登出成功 toast❌ 移除验证码发送 toast✅ 所有方法添加 logger | ✅ 完成 |\ 3. Mock 数据完善(\ Mock 数据完善(1个文件) - ✅ src/mocks/handlers/account.js - 个人中心 Mock - ✅ 自选股列表 (GET /api/account/watchlist) - ✅ 实时行情 (GET /api/account/watchlist/realtime) - ✅ 添加自选股 (POST /api/account/watchlist/add) - ✅ 删除自选股 (DELETE /api/account/watchlist/:id) - ✅ 关注的事件 (GET /api/account/events/following) - ✅ 事件评论 (GET /api/account/events/comments) - ✅ 当前订阅 (GET /api/subscription/current)\ 4. API 文档(1个文件) - ✅ API_ENDPOINTS.md - 完整 API 接口文档 - 认证相关: 4个接口 - 个人中心: 12个接口 - 事件相关: 12个接口 - 总计: 28+个接口\ 5。Toast 策略执行: - ✅ 保留: 3种(登录成功、注册成功、登出成功) - ❌ 移除: 15+处(验证码、数据加载等) Logger 替换: - ✅ console.log → logger.debug/logger.info - ✅ console.error → logger.error\- console.warn → logger.warn Mock 数据: 已有: auth.js, event.js, users.js, events.js 新增: account.js(7个新接口) 6.用户体验改进 静默优化:不再弹出验证码发送成功提示(静默处理)不再弹出数据加载失败提示(console 记录) 仅在关键操作显示 toast(登录/注册/登出) 开发体验: Console 中有清晰的分组日志(🌐 🔴 ⚠️ 等图标), 所有 API 请求/响应自动记录,错误日志包含完整上下文和堆栈,Mock 服务完善 测试场景: 登录/注册 - 仅显示成功 toast,验证码静默发送 个人中心 - 加载自选股、实时行情、关注事件 社区页面 - 加载事件列表、Console 查看 9. 添加日志:API Request / ✅ API Response / ❌ API Error
This commit is contained in:
@@ -1,30 +1,36 @@
|
||||
// src/services/eventService.js
|
||||
|
||||
const apiRequest = async (url, options = {}) => {
|
||||
try {
|
||||
console.log(`Making API request to: ${url}`);
|
||||
import { logger } from '../utils/logger';
|
||||
|
||||
const apiRequest = async (url, options = {}) => {
|
||||
const method = options.method || 'GET';
|
||||
const requestData = options.body ? JSON.parse(options.body) : null;
|
||||
|
||||
logger.api.request(method, url, requestData);
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
...options,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers,
|
||||
},
|
||||
credentials: 'include', // 包含 cookies,以便后端识别登录状态
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`API request failed: ${response.status} - ${errorText}`);
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
const error = new Error(`HTTP error! status: ${response.status}`);
|
||||
logger.api.error(method, url, error, { errorText, ...requestData });
|
||||
throw error;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log(`API response from ${url}:`, data);
|
||||
logger.api.response(method, url, response.status, data);
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error(`API request failed for ${url}:`, error);
|
||||
logger.api.error(method, url, error, requestData);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -160,7 +166,7 @@ export const eventService = {
|
||||
try {
|
||||
return await apiRequest(`/api/events/${eventId}/posts?sort=${sortType}&page=${page}&per_page=${perPage}`);
|
||||
} catch (error) {
|
||||
console.error('获取帖子失败:', error);
|
||||
logger.error('eventService', 'getPosts', error, { eventId, sortType, page });
|
||||
return { success: false, data: [], pagination: {} };
|
||||
}
|
||||
},
|
||||
@@ -172,7 +178,7 @@ export const eventService = {
|
||||
body: JSON.stringify(postData)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('创建帖子失败:', error);
|
||||
logger.error('eventService', 'createPost', error, { eventId });
|
||||
return { success: false, message: '创建帖子失败' };
|
||||
}
|
||||
},
|
||||
@@ -183,7 +189,7 @@ export const eventService = {
|
||||
method: 'DELETE'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('删除帖子失败:', error);
|
||||
logger.error('eventService', 'deletePost', error, { postId });
|
||||
return { success: false, message: '删除帖子失败' };
|
||||
}
|
||||
},
|
||||
@@ -194,7 +200,7 @@ export const eventService = {
|
||||
method: 'POST'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('点赞失败:', error);
|
||||
logger.error('eventService', 'likePost', error, { postId });
|
||||
return { success: false, message: '点赞失败' };
|
||||
}
|
||||
},
|
||||
@@ -204,7 +210,7 @@ export const eventService = {
|
||||
try {
|
||||
return await apiRequest(`/api/posts/${postId}/comments?sort=${sortType}`);
|
||||
} catch (error) {
|
||||
console.error('获取评论失败:', error);
|
||||
logger.error('eventService', 'getPostComments', error, { postId, sortType });
|
||||
return { success: false, data: [] };
|
||||
}
|
||||
},
|
||||
@@ -216,7 +222,7 @@ export const eventService = {
|
||||
body: JSON.stringify(commentData)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('添加评论失败:', error);
|
||||
logger.error('eventService', 'addPostComment', error, { postId });
|
||||
return { success: false, message: '添加评论失败' };
|
||||
}
|
||||
},
|
||||
@@ -227,7 +233,7 @@ export const eventService = {
|
||||
method: 'DELETE'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('删除评论失败:', error);
|
||||
logger.error('eventService', 'deleteComment', error, { commentId });
|
||||
return { success: false, message: '删除评论失败' };
|
||||
}
|
||||
},
|
||||
@@ -238,33 +244,31 @@ export const eventService = {
|
||||
method: 'POST'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('点赞失败:', error);
|
||||
logger.error('eventService', 'likeComment', error, { commentId });
|
||||
return { success: false, message: '点赞失败' };
|
||||
}
|
||||
},
|
||||
|
||||
// 兼容旧版本的评论API
|
||||
getComments: async (eventId, sortType = 'latest') => {
|
||||
console.warn('getComments 已废弃,请使用 getPosts');
|
||||
// 直接调用 getPosts 的实现,避免循环引用
|
||||
logger.warn('eventService', 'getComments 已废弃,请使用 getPosts');
|
||||
try {
|
||||
return await apiRequest(`/api/events/${eventId}/posts?sort=${sortType}&page=1&per_page=20`);
|
||||
} catch (error) {
|
||||
console.error('获取帖子失败:', error);
|
||||
logger.error('eventService', 'getComments', error, { eventId, sortType });
|
||||
return { success: false, data: [], pagination: {} };
|
||||
}
|
||||
},
|
||||
|
||||
addComment: async (eventId, commentData) => {
|
||||
console.warn('addComment 已废弃,请使用 createPost');
|
||||
// 直接调用 createPost 的实现,避免循环引用
|
||||
logger.warn('eventService', 'addComment 已废弃,请使用 createPost');
|
||||
try {
|
||||
return await apiRequest(`/api/events/${eventId}/posts`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(commentData)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('创建帖子失败:', error);
|
||||
logger.error('eventService', 'addComment', error, { eventId });
|
||||
return { success: false, message: '创建帖子失败' };
|
||||
}
|
||||
},
|
||||
@@ -281,26 +285,26 @@ export const stockService = {
|
||||
requestBody.event_time = eventTime;
|
||||
}
|
||||
|
||||
console.log(`获取股票报价,请求体:`, requestBody);
|
||||
logger.debug('stockService', '获取股票报价', requestBody);
|
||||
|
||||
const response = await apiRequest(`/api/stock/quotes`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
console.log('股票报价原始响应:', response);
|
||||
console.log('response.success:', response.success);
|
||||
console.log('response.data:', response.data);
|
||||
logger.debug('stockService', '股票报价响应', {
|
||||
success: response.success,
|
||||
dataKeys: response.data ? Object.keys(response.data) : []
|
||||
});
|
||||
|
||||
if (response.success && response.data) {
|
||||
console.log('返回股票报价数据:', response.data);
|
||||
return response.data;
|
||||
} else {
|
||||
console.warn('股票报价响应格式异常:', response);
|
||||
logger.warn('stockService', '股票报价响应格式异常', response);
|
||||
return {};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取股票报价失败:', error);
|
||||
logger.error('stockService', 'getQuotes', error, { codes, eventTime });
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -317,18 +321,18 @@ export const stockService = {
|
||||
}
|
||||
|
||||
const url = `/api/stock/${stockCode}/kline?${params.toString()}`;
|
||||
console.log(`获取K线数据: ${url}`);
|
||||
logger.debug('stockService', '获取K线数据', { stockCode, chartType, eventTime });
|
||||
|
||||
const response = await apiRequest(url);
|
||||
|
||||
if (response.error) {
|
||||
console.warn('K线数据响应包含错误:', response.error);
|
||||
logger.warn('stockService', 'K线数据响应包含错误', response.error);
|
||||
return response;
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('获取K线数据失败:', error);
|
||||
logger.error('stockService', 'getKlineData', error, { stockCode, chartType });
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -343,21 +347,10 @@ export const stockService = {
|
||||
node_level: nodeInfo.level
|
||||
});
|
||||
|
||||
const response = await fetch(`/api/events/${eventId}/sankey-node-detail?${params}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
const url = `/api/events/${eventId}/sankey-node-detail?${params}`;
|
||||
return await apiRequest(url);
|
||||
} catch (error) {
|
||||
console.error('Error fetching sankey node detail:', error);
|
||||
logger.error('stockService', 'getSankeyNodeDetail', error, { eventId, nodeInfo });
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
@@ -382,11 +375,11 @@ export const indexService = {
|
||||
}
|
||||
|
||||
const url = `/api/index/${indexCode}/kline?${params.toString()}`;
|
||||
console.log(`获取指数K线数据: ${url}`);
|
||||
logger.debug('indexService', '获取指数K线数据', { indexCode, chartType, eventTime });
|
||||
const response = await apiRequest(url);
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('获取指数K线数据失败:', error);
|
||||
logger.error('indexService', 'getKlineData', error, { indexCode, chartType });
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user