perf(Company): 优化渲染性能和 API 请求

- StockQuoteCard: 添加 memo 包装减少重渲染
- Company/index: componentProps 使用 useMemo 缓存
- useCompanyEvents: 页面浏览事件只触发一次,避免重复追踪
- useCompanyData: 自选股状态改用单股票查询接口,减少数据传输
- CompanyHeader: inputCode 状态下移到 SearchActions,减少父组件重渲染
- CompanyHeader: 移除重复环境光效果,由全局 AmbientGlow 统一处理

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-12-19 10:14:07 +08:00
parent c979e775a5
commit 51721ce9bf
5 changed files with 96 additions and 94 deletions

View File

@@ -76,26 +76,42 @@ export const useCompanyData = ({
}, [stockCode]);
/**
* 加载自选股状态
* 加载自选股状态(优化:只检查单个股票,避免加载整个列表)
*/
const loadWatchlistStatus = useCallback(async () => {
if (!isAuthenticated) {
if (!isAuthenticated || !stockCode) {
setIsInWatchlist(false);
return;
}
try {
const { data } = await axios.get<ApiResponse<WatchlistItem[]>>(
'/api/account/watchlist'
const { data } = await axios.get<ApiResponse<{ is_in_watchlist: boolean }>>(
`/api/account/watchlist/check/${stockCode}`
);
if (data.success && Array.isArray(data.data)) {
const codes = new Set(data.data.map((item) => item.stock_code));
setIsInWatchlist(codes.has(stockCode));
if (data.success && data.data) {
setIsInWatchlist(data.data.is_in_watchlist);
} else {
setIsInWatchlist(false);
}
} catch (error: any) {
logger.error('useCompanyData', 'loadWatchlistStatus', error);
setIsInWatchlist(false);
// 接口不存在时降级到原方案
if (error.response?.status === 404) {
try {
const { data: listData } = await axios.get<ApiResponse<WatchlistItem[]>>(
'/api/account/watchlist'
);
if (listData.success && Array.isArray(listData.data)) {
const codes = new Set(listData.data.map((item) => item.stock_code));
setIsInWatchlist(codes.has(stockCode));
}
} catch {
setIsInWatchlist(false);
}
} else {
logger.error('useCompanyData', 'loadWatchlistStatus', error);
setIsInWatchlist(false);
}
}
}, [stockCode, isAuthenticated]);