update pay ui
This commit is contained in:
173
src/views/Company/hooks/useCompanyData.ts
Normal file
173
src/views/Company/hooks/useCompanyData.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Company 页面数据加载 Hook
|
||||
* - 使用 axios 请求
|
||||
* - 懒加载策略
|
||||
* - 自动取消请求
|
||||
*/
|
||||
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useToast } from '@chakra-ui/react';
|
||||
import axios from '@utils/axiosConfig';
|
||||
import { logger } from '@utils/logger';
|
||||
import { useAuth } from '@contexts/AuthContext';
|
||||
import type {
|
||||
StockInfo,
|
||||
WatchlistItem,
|
||||
UseCompanyDataReturn,
|
||||
ApiResponse,
|
||||
} from '../types';
|
||||
|
||||
interface UseCompanyDataOptions {
|
||||
stockCode: string;
|
||||
/** 是否自动加载股票信息 */
|
||||
autoLoadStockInfo?: boolean;
|
||||
/** 是否自动加载自选股状态 */
|
||||
autoLoadWatchlist?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Company 页面数据管理 Hook
|
||||
*/
|
||||
export const useCompanyData = ({
|
||||
stockCode,
|
||||
autoLoadStockInfo = true,
|
||||
autoLoadWatchlist = true,
|
||||
}: UseCompanyDataOptions): UseCompanyDataReturn => {
|
||||
// 状态
|
||||
const [stockInfo, setStockInfo] = useState<StockInfo | null>(null);
|
||||
const [stockInfoLoading, setStockInfoLoading] = useState(false);
|
||||
const [isInWatchlist, setIsInWatchlist] = useState(false);
|
||||
const [watchlistLoading, setWatchlistLoading] = useState(false);
|
||||
|
||||
// Hooks
|
||||
const toast = useToast();
|
||||
const { isAuthenticated } = useAuth();
|
||||
|
||||
// AbortController 用于取消请求
|
||||
const abortControllerRef = useRef<AbortController | null>(null);
|
||||
|
||||
/**
|
||||
* 加载股票基本信息
|
||||
*/
|
||||
const loadStockInfo = useCallback(async () => {
|
||||
if (!stockCode || stockCode.length !== 6) return;
|
||||
|
||||
// 取消之前的请求
|
||||
abortControllerRef.current?.abort();
|
||||
abortControllerRef.current = new AbortController();
|
||||
|
||||
setStockInfoLoading(true);
|
||||
|
||||
try {
|
||||
const { data } = await axios.get<ApiResponse<StockInfo>>(
|
||||
`/api/financial/stock-info/${stockCode}`,
|
||||
{ signal: abortControllerRef.current.signal }
|
||||
);
|
||||
|
||||
if (data.success && data.data) {
|
||||
setStockInfo(data.data);
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (error.name === 'CanceledError') return;
|
||||
logger.error('useCompanyData', 'loadStockInfo', error, { stockCode });
|
||||
} finally {
|
||||
setStockInfoLoading(false);
|
||||
}
|
||||
}, [stockCode]);
|
||||
|
||||
/**
|
||||
* 加载自选股状态
|
||||
*/
|
||||
const loadWatchlistStatus = useCallback(async () => {
|
||||
if (!isAuthenticated) {
|
||||
setIsInWatchlist(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { data } = await axios.get<ApiResponse<WatchlistItem[]>>(
|
||||
'/api/account/watchlist'
|
||||
);
|
||||
|
||||
if (data.success && Array.isArray(data.data)) {
|
||||
const codes = new Set(data.data.map((item) => item.stock_code));
|
||||
setIsInWatchlist(codes.has(stockCode));
|
||||
}
|
||||
} catch (error: any) {
|
||||
logger.error('useCompanyData', 'loadWatchlistStatus', error);
|
||||
setIsInWatchlist(false);
|
||||
}
|
||||
}, [stockCode, isAuthenticated]);
|
||||
|
||||
/**
|
||||
* 切换自选股状态
|
||||
*/
|
||||
const toggleWatchlist = useCallback(async () => {
|
||||
if (!stockCode) {
|
||||
toast({ title: '无效的股票代码', status: 'error', duration: 2000 });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAuthenticated) {
|
||||
toast({ title: '请先登录后再加入自选', status: 'warning', duration: 2000 });
|
||||
return;
|
||||
}
|
||||
|
||||
setWatchlistLoading(true);
|
||||
|
||||
try {
|
||||
if (isInWatchlist) {
|
||||
// 移除自选
|
||||
await axios.delete(`/api/account/watchlist/${stockCode}`);
|
||||
setIsInWatchlist(false);
|
||||
toast({ title: '已从自选移除', status: 'info', duration: 1500 });
|
||||
} else {
|
||||
// 添加自选
|
||||
await axios.post('/api/account/watchlist', { stock_code: stockCode });
|
||||
setIsInWatchlist(true);
|
||||
toast({ title: '已加入自选', status: 'success', duration: 1500 });
|
||||
}
|
||||
} catch (error: any) {
|
||||
logger.error('useCompanyData', 'toggleWatchlist', error, { stockCode });
|
||||
toast({ title: '操作失败,请稍后重试', status: 'error', duration: 2000 });
|
||||
} finally {
|
||||
setWatchlistLoading(false);
|
||||
}
|
||||
}, [stockCode, isAuthenticated, isInWatchlist, toast]);
|
||||
|
||||
/**
|
||||
* 刷新股票信息
|
||||
*/
|
||||
const refreshStockInfo = useCallback(async () => {
|
||||
await loadStockInfo();
|
||||
}, [loadStockInfo]);
|
||||
|
||||
// 自动加载股票信息
|
||||
useEffect(() => {
|
||||
if (autoLoadStockInfo) {
|
||||
loadStockInfo();
|
||||
}
|
||||
|
||||
return () => {
|
||||
abortControllerRef.current?.abort();
|
||||
};
|
||||
}, [autoLoadStockInfo, loadStockInfo]);
|
||||
|
||||
// 自动加载自选股状态
|
||||
useEffect(() => {
|
||||
if (autoLoadWatchlist) {
|
||||
loadWatchlistStatus();
|
||||
}
|
||||
}, [autoLoadWatchlist, loadWatchlistStatus]);
|
||||
|
||||
return {
|
||||
stockInfo,
|
||||
stockInfoLoading,
|
||||
isInWatchlist,
|
||||
watchlistLoading,
|
||||
toggleWatchlist,
|
||||
refreshStockInfo,
|
||||
};
|
||||
};
|
||||
|
||||
export default useCompanyData;
|
||||
Reference in New Issue
Block a user