Initial commit

This commit is contained in:
2025-10-11 11:55:25 +08:00
parent 467dad8449
commit 8107dee8d3
2879 changed files with 610575 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
// 调试文件 - 检查 eventService 的方法
import { eventService } from '../services/eventService';
export const debugEventService = () => {
console.log('=== eventService 调试信息 ===');
console.log('eventService 对象:', eventService);
console.log('eventService 类型:', typeof eventService);
console.log('eventService 的所有键:', Object.keys(eventService));
// 检查特定的方法
const methods = [
'getPosts',
'createPost',
'deletePost',
'likePost',
'getPostComments',
'addPostComment',
'deleteComment',
'likeComment'
];
console.log('\n方法检查:');
methods.forEach(method => {
console.log(`${method}:`,
eventService[method] ? '✓ 存在' : '✗ 不存在',
eventService[method] ? `(类型: ${typeof eventService[method]})` : ''
);
});
// 检查是否有其他相似的方法名
console.log('\n所有方法列表:');
Object.keys(eventService).forEach(key => {
if (typeof eventService[key] === 'function') {
console.log(`- ${key}`);
}
});
return eventService;
};

25
src/utils/eventBus.js Normal file
View File

@@ -0,0 +1,25 @@
// 简单的事件总线,用于组件间通信
class EventBus {
constructor() {
this.events = {};
}
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
off(event, callback) {
if (!this.events[event]) return;
this.events[event] = this.events[event].filter(cb => cb !== callback);
}
emit(event, data) {
if (!this.events[event]) return;
this.events[event].forEach(callback => callback(data));
}
}
export default new EventBus();

75
src/utils/textUtils.js Normal file
View File

@@ -0,0 +1,75 @@
/**
* 文本处理工具函数
*/
/**
* 处理包含<br>标签的文本转换为适合在React中显示的格式
* @param {string} text - 包含<br>标签的文本
* @param {string} mode - 处理模式:'html' 使用dangerouslySetInnerHTML, 'text' 转换为纯文本换行, 'remove' 直接去掉br标签
* @returns {string} 处理后的文本
*/
export const formatTextWithBr = (text, mode = 'text') => {
if (!text) return '';
switch (mode) {
case 'html':
// 用于dangerouslySetInnerHTML保持换行效果
return text
.replace(/<br\s*\/?>(\s*)/g, '\n') // 将br标签转换为换行符
.replace(/\n{2,}/g, '\n') // 去掉多余的换行符
.replace(/\n/g, '<br/>'); // 重新转换为br标签
case 'text':
// 用于普通Text组件配合whiteSpace="pre-line"使用
return text
.replace(/<br\s*\/?>(\s*)/g, '\n') // 将br标签转换为换行符
.replace(/\n{2,}/g, '\n') // 去掉多余的换行符
.trim();
case 'remove':
// 直接去掉br标签用空格替代
return text
.replace(/<br\s*\/?>(\s*)/g, ' ') // 将br标签替换为空格
.replace(/\s{2,}/g, ' ') // 去掉多余的空格
.trim();
default:
return text;
}
};
/**
* 为文本添加样式化的换行处理
* @param {string} text - 原始文本
* @returns {object} 包含处理后文本和样式的对象
*/
export const getFormattedTextProps = (text) => {
if (!text) return { children: '', props: {} };
const formattedText = formatTextWithBr(text, 'text');
return {
children: formattedText,
props: {
whiteSpace: 'pre-line',
lineHeight: '1.6',
wordBreak: 'break-word'
}
};
};
/**
* 为工具提示(Tooltip)优化的文本格式化
* @param {string} text - 原始文本
* @param {number} maxLength - 最大长度,超出部分用...省略
* @returns {string} 处理后的文本
*/
export const formatTooltipText = (text, maxLength = 200) => {
if (!text) return '';
const cleaned = formatTextWithBr(text, 'text');
if (cleaned.length <= maxLength) return cleaned;
return cleaned.substring(0, maxLength) + '...';
};

View File

@@ -0,0 +1,214 @@
// src/utils/tradingDayUtils.js
// 交易日计算工具函数
/**
* 中国股市交易日工具类
* 包含节假日判断和交易日计算
*/
class TradingDayUtils {
constructor() {
// 2024-2025年的法定节假日需要定期更新
this.holidays = new Set([
// 2024年节假日
'2024-01-01', // 元旦
'2024-02-09', '2024-02-10', '2024-02-11', '2024-02-12', '2024-02-13',
'2024-02-14', '2024-02-15', '2024-02-16', '2024-02-17', // 春节
'2024-04-04', '2024-04-05', '2024-04-06', // 清明节
'2024-05-01', '2024-05-02', '2024-05-03', '2024-05-04', '2024-05-05', // 劳动节
'2024-06-08', '2024-06-09', '2024-06-10', // 端午节
'2024-09-15', '2024-09-16', '2024-09-17', // 中秋节
'2024-10-01', '2024-10-02', '2024-10-03', '2024-10-04',
'2024-10-05', '2024-10-06', '2024-10-07', // 国庆节
// 2025年节假日预估需要根据官方公告更新
'2025-01-01', // 元旦
'2025-01-28', '2025-01-29', '2025-01-30', '2025-01-31',
'2025-02-01', '2025-02-02', '2025-02-03', '2025-02-04', // 春节
'2025-04-04', '2025-04-05', '2025-04-06', // 清明节
'2025-05-01', '2025-05-02', '2025-05-03', // 劳动节
'2025-05-31', '2025-06-01', '2025-06-02', // 端午节
'2025-10-01', '2025-10-02', '2025-10-03', '2025-10-04',
'2025-10-05', '2025-10-06', '2025-10-07', '2025-10-08', // 国庆节+中秋节
]);
// A股交易时间
this.marketOpenTime = { hour: 9, minute: 30 };
this.marketCloseTime = { hour: 15, minute: 0 };
}
/**
* 判断是否为周末
* @param {Date} date
* @returns {boolean}
*/
isWeekend(date) {
const day = date.getDay();
return day === 0 || day === 6; // 0是周日6是周六
}
/**
* 判断是否为节假日
* @param {Date} date
* @returns {boolean}
*/
isHoliday(date) {
const dateStr = this.formatDate(date);
return this.holidays.has(dateStr);
}
/**
* 判断是否为交易日
* @param {Date} date
* @returns {boolean}
*/
isTradingDay(date) {
return !this.isWeekend(date) && !this.isHoliday(date);
}
/**
* 格式化日期为 YYYY-MM-DD
* @param {Date} date
* @returns {string}
*/
formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
/**
* 判断时间是否在交易时间内
* @param {Date} datetime
* @returns {boolean}
*/
isInTradingHours(datetime) {
const hours = datetime.getHours();
const minutes = datetime.getMinutes();
// 上午交易时间9:30-11:30
const morningStart = hours > 9 || (hours === 9 && minutes >= 30);
const morningEnd = hours < 11 || (hours === 11 && minutes <= 30);
// 下午交易时间13:00-15:00
const afternoonStart = hours >= 13;
const afternoonEnd = hours < 15;
return (morningStart && morningEnd) || (afternoonStart && afternoonEnd);
}
/**
* 判断事件是否发生在交易时间后
* @param {Date} datetime
* @returns {boolean}
*/
isAfterTradingHours(datetime) {
const hours = datetime.getHours();
const minutes = datetime.getMinutes();
return hours > 15 || (hours === 15 && minutes > 0);
}
/**
* 获取下一个交易日
* @param {Date} date
* @returns {Date}
*/
getNextTradingDay(date) {
const nextDay = new Date(date);
nextDay.setDate(nextDay.getDate() + 1);
while (!this.isTradingDay(nextDay)) {
nextDay.setDate(nextDay.getDate() + 1);
}
return nextDay;
}
/**
* 获取上一个交易日
* @param {Date} date
* @returns {Date}
*/
getPreviousTradingDay(date) {
const prevDay = new Date(date);
prevDay.setDate(prevDay.getDate() - 1);
while (!this.isTradingDay(prevDay)) {
prevDay.setDate(prevDay.getDate() - 1);
}
return prevDay;
}
/**
* 根据事件时间获取对应的交易日
* 规则:
* 1. 如果是交易日的交易时间内,返回当天
* 2. 如果是交易日的15:00后返回下一个交易日
* 3. 如果是非交易日(周末或节假日),返回下一个交易日
*
* @param {Date|string} eventDateTime 事件时间
* @returns {string} 交易日期 YYYY-MM-DD
*/
getEffectiveTradingDay(eventDateTime) {
const datetime = typeof eventDateTime === 'string' ? new Date(eventDateTime) : eventDateTime;
// 如果是非交易日,直接返回下一个交易日
if (!this.isTradingDay(datetime)) {
return this.formatDate(this.getNextTradingDay(datetime));
}
// 如果是交易日
// 检查是否在15:00之后
if (this.isAfterTradingHours(datetime)) {
// 15:00后返回下一个交易日
return this.formatDate(this.getNextTradingDay(datetime));
}
// 交易日的15:00前返回当天
return this.formatDate(datetime);
}
/**
* 批量加载交易日数据如果有CSV文件
* @param {string} csvContent CSV内容
*/
loadTradingDaysFromCSV(csvContent) {
const lines = csvContent.trim().split('\n');
const tradingDays = new Set();
// 跳过标题行
for (let i = 1; i < lines.length; i++) {
const date = lines[i].trim();
if (date) {
// 转换日期格式 2010/1/4 -> 2010-01-04
const parts = date.split('/');
if (parts.length === 3) {
const year = parts[0];
const month = parts[1].padStart(2, '0');
const day = parts[2].padStart(2, '0');
tradingDays.add(`${year}-${month}-${day}`);
}
}
}
this.tradingDaysSet = tradingDays;
}
/**
* 使用CSV数据判断是否为交易日如果已加载
* @param {Date} date
* @returns {boolean}
*/
isTradingDayByCSV(date) {
if (this.tradingDaysSet) {
return this.tradingDaysSet.has(this.formatDate(date));
}
// 如果没有CSV数据回退到默认判断
return this.isTradingDay(date);
}
}
// 导出单例
export const tradingDayUtils = new TradingDayUtils();
export default tradingDayUtils;