useStockSocketClient.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import { useEffect, useState, useCallback } from 'react';
  2. import { io, Socket } from 'socket.io-client';
  3. import { useAuth } from '../../mobile/hooks.tsx';
  4. interface StockPriceUpdate {
  5. symbol: string;
  6. price: number;
  7. timestamp: Date;
  8. }
  9. interface ProfitSummary {
  10. dailyStats: {
  11. close: number;
  12. };
  13. }
  14. interface StockSocketClient {
  15. connect(): void;
  16. disconnect(): void;
  17. subscribe(symbol: string): void;
  18. unsubscribe(symbol: string): void;
  19. currentPrice: number | null;
  20. lastUpdate: Date | null;
  21. error: Error | null;
  22. isConnected: boolean;
  23. }
  24. export function useStockSocket(): StockSocketClient {
  25. const { token } = useAuth();
  26. const [socket, setSocket] = useState<Socket | null>(null);
  27. const [currentPrice, setCurrentPrice] = useState<number | null>(null);
  28. const [lastUpdate, setLastUpdate] = useState<Date | null>(null);
  29. const [error, setError] = useState<Error | null>(null);
  30. const [isConnected, setIsConnected] = useState(false);
  31. const [currentDate, setCurrentDate] = useState<Date | null>(null);
  32. const [profitSummary, setProfitSummary] = useState<ProfitSummary | null>(null);
  33. // 初始化socket连接
  34. useEffect(() => {
  35. if (!token) return;
  36. const newSocket = io('/', {
  37. path: '/socket.io',
  38. transports: ['websocket'],
  39. query: { token },
  40. reconnection: true,
  41. reconnectionAttempts: 5,
  42. reconnectionDelay: 1000,
  43. });
  44. newSocket.on('connect', () => {
  45. console.log('Stock socket connected');
  46. setIsConnected(true);
  47. });
  48. newSocket.on('disconnect', () => {
  49. console.log('Stock socket disconnected');
  50. setIsConnected(false);
  51. });
  52. newSocket.on('error', (err) => {
  53. console.error('Stock socket error:', err);
  54. setError(err);
  55. });
  56. // 监听股票价格更新
  57. newSocket.on('stock:priceUpdate', (data: StockPriceUpdate) => {
  58. setCurrentPrice(data.price);
  59. setLastUpdate(new Date(data.timestamp));
  60. });
  61. // 监听当前日期更新
  62. newSocket.on('stock:currentDate', (date: string) => {
  63. setCurrentDate(new Date(date));
  64. });
  65. // 监听收益摘要更新
  66. newSocket.on('stock:profitSummary', (summary: ProfitSummary) => {
  67. setProfitSummary(summary);
  68. });
  69. setSocket(newSocket);
  70. return () => {
  71. newSocket.disconnect();
  72. };
  73. }, [token]);
  74. const connect = useCallback(() => {
  75. if (socket && !socket.connected) {
  76. socket.connect();
  77. }
  78. }, [socket]);
  79. const disconnect = useCallback(() => {
  80. if (socket && socket.connected) {
  81. socket.disconnect();
  82. }
  83. }, [socket]);
  84. const subscribe = useCallback((symbol: string) => {
  85. if (socket) {
  86. socket.emit('stock:subscribe', { symbol });
  87. }
  88. }, [socket]);
  89. const unsubscribe = useCallback((symbol: string) => {
  90. if (socket) {
  91. socket.emit('stock:unsubscribe', { symbol });
  92. }
  93. }, [socket]);
  94. return {
  95. connect,
  96. disconnect,
  97. subscribe,
  98. unsubscribe,
  99. currentPrice,
  100. lastUpdate,
  101. error,
  102. isConnected,
  103. };
  104. }