feat: 添加消息推送能力

This commit is contained in:
zdl
2025-10-21 15:48:38 +08:00
parent 955e0db740
commit 38499ce650
8 changed files with 2485 additions and 417 deletions

View File

@@ -0,0 +1,181 @@
// src/constants/notificationTypes.js
/**
* 金融资讯通知系统 - 类型定义和常量
*/
import { MdCampaign, MdTrendingUp, MdTrendingDown, MdArticle, MdAssessment } from 'react-icons/md';
// 通知类型
export const NOTIFICATION_TYPES = {
ANNOUNCEMENT: 'announcement', // 公告通知
STOCK_ALERT: 'stock_alert', // 股票动向
EVENT_ALERT: 'event_alert', // 事件动向
ANALYSIS_REPORT: 'analysis_report', // 分析报告
};
// 优先级
export const PRIORITY_LEVELS = {
URGENT: 'urgent', // 紧急
IMPORTANT: 'important', // 重要
NORMAL: 'normal', // 普通
};
// 通知状态(用于预测通知)
export const NOTIFICATION_STATUS = {
PREDICTION: 'prediction', // 预测状态(详情未就绪)
READY: 'ready', // 详情已就绪
};
// 通知系统配置
export const NOTIFICATION_CONFIG = {
// 显示策略
maxVisible: 3, // 最多显示3条通知
maxHistory: 15, // 历史保留15条折叠区
// 自动关闭时长(毫秒)- 按优先级区分
autoCloseDuration: {
[PRIORITY_LEVELS.URGENT]: 0, // 紧急:不自动关闭
[PRIORITY_LEVELS.IMPORTANT]: 30000, // 重要30秒
[PRIORITY_LEVELS.NORMAL]: 15000, // 普通15秒
},
// 推送频率配置(测试模式)
mockPush: {
interval: 60000, // 60秒推送一次
minBatch: 1, // 最少1条
maxBatch: 2, // 最多2条
},
// 折叠配置
collapse: {
threshold: 3, // 超过3条开始折叠
textTemplate: '还有 {count} 条通知', // 折叠提示文案
},
};
// 优先级标签配置
export const PRIORITY_CONFIGS = {
[PRIORITY_LEVELS.URGENT]: {
label: '紧急',
colorScheme: 'red',
show: true,
},
[PRIORITY_LEVELS.IMPORTANT]: {
label: '重要',
colorScheme: 'orange',
show: true,
},
[PRIORITY_LEVELS.NORMAL]: {
label: '',
colorScheme: 'gray',
show: false, // 普通优先级不显示标签
},
};
// 通知类型样式配置
export const NOTIFICATION_TYPE_CONFIGS = {
[NOTIFICATION_TYPES.ANNOUNCEMENT]: {
name: '公告通知',
icon: MdCampaign,
colorScheme: 'blue',
bg: 'blue.50',
borderColor: 'blue.400',
iconColor: 'blue.500',
hoverBg: 'blue.100',
},
[NOTIFICATION_TYPES.STOCK_ALERT]: {
name: '股票动向',
// 图标根据涨跌动态设置
getIcon: (priceChange) => {
if (!priceChange) return MdTrendingUp;
return priceChange.startsWith('+') ? MdTrendingUp : MdTrendingDown;
},
// 颜色根据涨跌动态设置
getColorScheme: (priceChange) => {
if (!priceChange) return 'red';
return priceChange.startsWith('+') ? 'red' : 'green';
},
getBg: (priceChange) => {
const scheme = NOTIFICATION_TYPE_CONFIGS[NOTIFICATION_TYPES.STOCK_ALERT].getColorScheme(priceChange);
return `${scheme}.50`;
},
getBorderColor: (priceChange) => {
const scheme = NOTIFICATION_TYPE_CONFIGS[NOTIFICATION_TYPES.STOCK_ALERT].getColorScheme(priceChange);
return `${scheme}.400`;
},
getIconColor: (priceChange) => {
const scheme = NOTIFICATION_TYPE_CONFIGS[NOTIFICATION_TYPES.STOCK_ALERT].getColorScheme(priceChange);
return `${scheme}.500`;
},
getHoverBg: (priceChange) => {
const scheme = NOTIFICATION_TYPE_CONFIGS[NOTIFICATION_TYPES.STOCK_ALERT].getColorScheme(priceChange);
return `${scheme}.100`;
},
},
[NOTIFICATION_TYPES.EVENT_ALERT]: {
name: '事件动向',
icon: MdArticle,
colorScheme: 'orange',
bg: 'orange.50',
borderColor: 'orange.400',
iconColor: 'orange.500',
hoverBg: 'orange.100',
},
[NOTIFICATION_TYPES.ANALYSIS_REPORT]: {
name: '分析报告',
icon: MdAssessment,
colorScheme: 'purple',
bg: 'purple.50',
borderColor: 'purple.400',
iconColor: 'purple.500',
hoverBg: 'purple.100',
},
};
// 时间格式化辅助函数
export const formatNotificationTime = (timestamp) => {
const date = new Date(timestamp);
const now = new Date();
const diff = now - date;
// 小于1分钟
if (diff < 60000) {
return '刚刚';
}
// 小于1小时
if (diff < 3600000) {
return `${Math.floor(diff / 60000)}分钟前`;
}
// 小于24小时
if (diff < 86400000) {
return `${Math.floor(diff / 3600000)}小时前`;
}
// 今天
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const dateDay = new Date(date.getFullYear(), date.getMonth(), date.getDate());
if (dateDay.getTime() === today.getTime()) {
return `今天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
}
// 昨天
const yesterday = new Date(today);
yesterday.setDate(yesterday.getDate() - 1);
if (dateDay.getTime() === yesterday.getTime()) {
return `昨天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
}
// 其他
return `${date.getMonth() + 1}-${date.getDate()} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
};
export default {
NOTIFICATION_TYPES,
PRIORITY_LEVELS,
NOTIFICATION_STATUS,
PRIORITY_CONFIGS,
NOTIFICATION_TYPE_CONFIGS,
formatNotificationTime,
};