feat: 添加消息推送能力,添加新闻催化分析页的合规提示

This commit is contained in:
zdl
2025-10-21 10:59:52 +08:00
parent 6c96299b8f
commit 5a3a3ad42b
15 changed files with 1800 additions and 125 deletions

View File

@@ -0,0 +1,254 @@
// src/services/mockSocketService.js
/**
* Mock Socket 服务 - 用于开发环境模拟实时推送
* 模拟交易提醒、系统通知等实时消息推送
*/
import { logger } from '../utils/logger';
// 模拟交易提醒数据
const mockTradeAlerts = [
{
type: 'trade_alert',
severity: 'success',
title: '买入成功',
message: '您的订单已成功执行:买入 贵州茅台(600519) 100股成交价 ¥1,850.00',
timestamp: Date.now(),
autoClose: 8000,
},
{
type: 'trade_alert',
severity: 'warning',
title: '价格预警',
message: '您关注的股票 比亚迪(002594) 当前价格 ¥245.50,已触达预设价格',
timestamp: Date.now(),
autoClose: 10000,
},
{
type: 'trade_alert',
severity: 'info',
title: '持仓提醒',
message: '您持有的 宁德时代(300750) 今日涨幅达 5.2%,当前盈利 +¥12,350',
timestamp: Date.now(),
autoClose: 8000,
},
{
type: 'trade_alert',
severity: 'error',
title: '委托失败',
message: '卖出订单失败:五粮液(000858) 当前处于停牌状态,无法交易',
timestamp: Date.now(),
autoClose: 12000,
},
{
type: 'system_notification',
severity: 'info',
title: '系统公告',
message: '市场将于15:00收盘请注意及时调整持仓',
timestamp: Date.now(),
autoClose: 10000,
},
{
type: 'trade_alert',
severity: 'success',
title: '分红到账',
message: '您持有的 中国平安(601318) 分红已到账,金额 ¥560.00',
timestamp: Date.now(),
autoClose: 8000,
},
];
class MockSocketService {
constructor() {
this.connected = false;
this.listeners = new Map();
this.intervals = [];
this.messageQueue = [];
}
/**
* 连接到 mock socket
*/
connect() {
if (this.connected) {
logger.warn('mockSocketService', 'Already connected');
return;
}
logger.info('mockSocketService', 'Connecting to mock socket service...');
// 模拟连接延迟
setTimeout(() => {
this.connected = true;
logger.info('mockSocketService', 'Mock socket connected successfully');
// 触发连接成功事件
this.emit('connect', { timestamp: Date.now() });
// 在连接后3秒发送欢迎消息
setTimeout(() => {
this.emit('trade_notification', {
type: 'system_notification',
severity: 'info',
title: '连接成功',
message: '实时消息推送服务已启动 (Mock 模式)',
timestamp: Date.now(),
autoClose: 5000,
});
}, 3000);
}, 1000);
}
/**
* 断开连接
*/
disconnect() {
if (!this.connected) {
return;
}
logger.info('mockSocketService', 'Disconnecting from mock socket service...');
// 清除所有定时器
this.intervals.forEach(interval => clearInterval(interval));
this.intervals = [];
this.connected = false;
this.emit('disconnect', { timestamp: Date.now() });
}
/**
* 监听事件
* @param {string} event - 事件名称
* @param {Function} callback - 回调函数
*/
on(event, callback) {
if (!this.listeners.has(event)) {
this.listeners.set(event, []);
}
this.listeners.get(event).push(callback);
logger.info('mockSocketService', `Event listener added: ${event}`);
}
/**
* 移除事件监听
* @param {string} event - 事件名称
* @param {Function} callback - 回调函数
*/
off(event, callback) {
if (!this.listeners.has(event)) {
return;
}
const callbacks = this.listeners.get(event);
const index = callbacks.indexOf(callback);
if (index !== -1) {
callbacks.splice(index, 1);
logger.info('mockSocketService', `Event listener removed: ${event}`);
}
// 如果没有监听器了,删除该事件
if (callbacks.length === 0) {
this.listeners.delete(event);
}
}
/**
* 触发事件
* @param {string} event - 事件名称
* @param {*} data - 事件数据
*/
emit(event, data) {
if (!this.listeners.has(event)) {
return;
}
const callbacks = this.listeners.get(event);
callbacks.forEach(callback => {
try {
callback(data);
} catch (error) {
logger.error('mockSocketService', 'emit', error, { event, data });
}
});
}
/**
* 启动模拟消息推送
* @param {number} interval - 推送间隔(毫秒)
* @param {number} burstCount - 每次推送的消息数量1-3条
*/
startMockPush(interval = 15000, burstCount = 1) {
if (!this.connected) {
logger.warn('mockSocketService', 'Cannot start mock push: not connected');
return;
}
logger.info('mockSocketService', `Starting mock push: interval=${interval}ms, burst=${burstCount}`);
const pushInterval = setInterval(() => {
// 随机选择 1-burstCount 条消息
const count = Math.floor(Math.random() * burstCount) + 1;
for (let i = 0; i < count; i++) {
// 从模拟数据中随机选择一条
const randomIndex = Math.floor(Math.random() * mockTradeAlerts.length);
const alert = {
...mockTradeAlerts[randomIndex],
timestamp: Date.now(),
id: `mock_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
};
// 延迟发送(模拟层叠效果)
setTimeout(() => {
this.emit('trade_notification', alert);
logger.info('mockSocketService', 'Mock notification sent', alert);
}, i * 500); // 每条消息间隔500ms
}
}, interval);
this.intervals.push(pushInterval);
}
/**
* 停止模拟推送
*/
stopMockPush() {
this.intervals.forEach(interval => clearInterval(interval));
this.intervals = [];
logger.info('mockSocketService', 'Mock push stopped');
}
/**
* 手动触发一条测试消息
* @param {object} customData - 自定义消息数据(可选)
*/
sendTestNotification(customData = null) {
const notification = customData || {
type: 'trade_alert',
severity: 'info',
title: '测试消息',
message: '这是一条手动触发的测试消息',
timestamp: Date.now(),
autoClose: 5000,
id: `test_${Date.now()}`,
};
this.emit('trade_notification', notification);
logger.info('mockSocketService', 'Test notification sent', notification);
}
/**
* 获取连接状态
*/
isConnected() {
return this.connected;
}
}
// 导出单例
export const mockSocketService = new MockSocketService();
export default mockSocketService;