Commit Graph

472 Commits

Author SHA1 Message Date
zdl
462933f4af feat: 统一事件详情和滚动列表的重要性颜色样式
优化:
- 事件详情页面的重要性标签从固定橙色改为动态红色渐变
- 背景色使用 importance.bgColor (red.50)
- 文字和边框颜色使用 importance.badgeBg (red.800/600/500/400)
- 添加 2px 边框以保持视觉一致性
- 与滚动事件列表的重要性角标样式保持统一

修改文件:
- src/views/Community/components/DynamicNewsDetail/EventHeaderInfo.js

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 15:59:12 +08:00
zdl
26dcfd061c feat: 优化 EventScrollList 分页控制器位置和样式
本次提交包含以下优化:

 分页控制器位置调整
- 从底部移至顶部右对齐
- 使用相对定位 (Flex justify="flex-end")
- 移除 CardBody 顶部 padding (pt={0})
- 确保分页控制器紧贴顶部,无任何间距

 箭头样式优化
- 调整箭头大小和颜色
- 使用毛玻璃效果背景
- 改善视觉层次和交互体验

修改文件:
- src/views/Community/components/DynamicNewsCard.js (CardBody pt={0})
- src/views/Community/components/DynamicNewsCard/EventScrollList.js (分页位置和箭头样式)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 15:56:19 +08:00
zdl
7e32dda2df feat本次提交包含的优化
 StockChangeIndicators 组件优化

  - 调整 padding 使布局更紧凑
  - 修复窄卡片中的折行问题
  - 自动根据内容调整宽度

   重要性等级视觉优化

  - 统一使用红色系(S→A→B→C:从深红到浅红)
  - 添加 badgeBg 字段支持新的角标样式

   DynamicNewsEventCard 卡片改版

  - 左上角矩形角标显示重要性(镂空边框样式)
  - 悬浮显示所有等级说明
  - 标题限制两行显示

   Mock 数据完整性

  - 添加缺失的 related_week_chg 字段
  - 确保三个涨跌幅指标数据完整
2025-11-03 15:38:30 +08:00
zdl
9274323151 fix: 完全移除 EventScrollList 顶部间距
问题:
- EventScrollList 顶部间距 (pt={2}, 8px) 仍然过大
- 用户期望事件列表紧贴搜索框,无顶部间距

修改:
- pt={2} 改为 pt={0}
- 顶部间距从 8px 完全移除为 0px
- 保持底部 pb={4} (16px) 和左右 px={2} (8px) 不变

视觉效果:
- EventScrollList 紧贴 CardHeader,更加紧凑
- 其他方向间距保持不变

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:41:05 +08:00
zdl
cedfd3978d fix: 减少 EventScrollList 顶部间距
问题:
- EventScrollList 的 Flex 容器设置了 py={4}(上下各 16px padding)
- 导致顶部间距过大,视觉不够紧凑

修改:
- py={4} 改为 pt={2} pb={4}
- 顶部间距从 16px 减少到 8px
- 保持底部 16px 间距,为滚动条留出足够空间

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:32:28 +08:00
zdl
89fe0cd10b fix: 修改 EventScrollList 左右箭头为翻页功能
问题:
- 左边箭头位置 (left: -4) 超出容器,看不到
- 右边箭头点击只是滚动 400px,而不是切换页面
- 用户期望左右箭头用于翻页,而不是横向滚动

修改内容:
1. 删除滚动相关函数和状态
   - 删除 scrollLeft()、scrollRight() 函数
   - 删除 handleScroll() 监听函数
   - 删除 showLeftArrow、showRightArrow state
   - 删除 useEffect 重置滚动位置逻辑
   - 移除 useState、useEffect 导入

2. 修改箭头功能从"滚动"改为"翻页"
   - 左箭头: onClick={scrollLeft} → onClick={() => onPageChange(currentPage - 1)}
   - 右箭头: onClick={scrollRight} → onClick={() => onPageChange(currentPage + 1)}

3. 修改箭头显隐逻辑为基于页码
   - 左箭头: showLeftArrow → currentPage > 1
   - 右箭头: showRightArrow → currentPage < totalPages

4. 优化箭头位置和样式
   - 位置: left/right: "-4" → "2" (在容器内部边缘)
   - 图标尺寸: boxSize={6} → boxSize={8}
   - 按钮尺寸: size="md" → size="lg"
   - 阴影: shadow="md" → shadow="lg"
   - 明确背景色: bg="blue.500"
   - 增强 hover 效果: 放大 scale(1.1) + 加深颜色
   - 更新说明文字: "向左/右滚动" → "上一页/下一页"

预期效果:
- 左箭头点击后加载上一页数据
- 右箭头点击后加载下一页数据
- 第1页时左箭头隐藏,最后一页时右箭头隐藏
- 箭头位置清晰可见,视觉效果突出

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:29:44 +08:00
zdl
d027071e98 feat: 优化社区页面滚动和分页交互体验…)
⎿  [feature_2025/1028_event 5dedbb3] feat: 优化社区页面滚动和分页交互体验
      6 files changed, 1355 insertions(+), 49 deletions(-)
      create mode 100644 docs/test-cases/Community351241265351235242346265213350257225347224250344276213.md
2025-11-03 14:24:41 +08:00
zdl
e31e4118a0 fix: 修改相关概念组件以匹配真实API数据结构
修改内容:
- SimpleConceptCard.js: 改用 concept.concept 和 concept.score 字段
- DetailedConceptCard.js: 改用 concept.concept、concept.score 和 concept.price_info.avg_change_pct
- RelatedConceptsSection/index.js: 导航时使用 concept.concept 字段
- events.js mock数据: 更新keywords生成函数,使用concept/score/price_info结构

数据结构变更:
- name → concept (概念名称)
- relevance (0-100) → score (0-1)
- avg_change_pct → price_info.avg_change_pct (嵌套结构)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:18:17 +08:00
zdl
5611c06991 refactor: 移除 RelatedConcepts 组件中的 API_BASE_URL 配置
移除硬编码的 API 基础地址配置,改为直接使用 API 路径:
- 删除 API_BASE_URL 常量定义
- 修改 fetch 请求直接使用 '/concept-api/search'
- 依赖项目的环境配置文件进行代理配置

优点:
- 代码更简洁,不需要环境判断
- 统一使用项目级别的代理配置
- 便于维护和部署

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 13:55:32 +08:00
zdl
784202025c feat: 增强历史事件对比卡片交互,支持点击跳转事件详情
功能新增:
- 点击事件卡片跳转到事件详情页(/event-detail/:eventId)
- 点击事件标题跳转到事件详情页(带下划线 hover 效果)
- "相关股票"按钮独立触发弹窗,不影响卡片跳转

组件修改:
- HistoricalEvents.js:
  * 导入 useNavigate hook 用于路由跳转
  * 添加 handleCardClick 函数处理跳转逻辑
  * 事件卡片添加 cursor="pointer" 和 onClick 事件
  * 优化卡片 hover 效果(阴影、边框色、上浮动画)
  * 标题添加独立的点击事件和下划线 hover 效果
  * "相关股票"按钮添加 stopPropagation 阻止事件冒泡

交互优化:
- 卡片 hover: boxShadow 从 md → lg,边框从 blue.300 → blue.400
- 卡片 hover: 添加 translateY(-2px) 上浮效果
- 标题 hover: 添加下划线提示可点击
- 光标样式: 卡片和标题都显示 pointer

事件冒泡控制:
- 标题点击: stopPropagation 后再触发跳转(保持一致性)
- 相关股票按钮: stopPropagation 防止触发卡片跳转
- 确保各个点击区域互不干扰

用户体验提升:
- 多种点击方式提供便利性(整个卡片、标题)
- 更明显的视觉反馈(hover 效果、光标变化)
- 精确的交互控制,避免误触发

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 13:08:07 +08:00
zdl
daf7372bab feat: 修复相关概念卡片跳转逻辑,支持跳转至概念中心
功能优化:
- 相关概念卡片点击跳转至概念中心(/concepts)并自动搜索该概念
- 概念相关股票支持点击跳转至公司详情页

组件修改:
- RelatedConceptsSection/index.js:
  * 修复 handleConceptClick 函数跳转路径
  * 从错误的 /concept/:name 改为正确的 /concepts?q=:name
  * 使用 encodeURIComponent 确保中文概念名称正确编码

- RelatedConceptsSection/ConceptStockItem.js:
  * 新增 handleStockClick 点击处理函数
  * 点击股票跳转至公司详情页(valuefrontier.cn/company)
  * 添加 hover 效果和过渡动画
  * 使用 stopPropagation 防止事件冒泡到概念卡片

跳转行为:
- 简单概念卡片(横向)→ 点击跳转到概念中心搜索结果页
- 详细概念卡片(展开后)→ 点击跳转到概念中心搜索结果页
- 概念相关股票 → 点击跳转到公司详情页(新标签页)

URL示例:
- 点击"人工智能"概念 → /concepts?q=人工智能
- 点击股票"000001.SZ" → valuefrontier.cn/company?scode=000001

用户体验提升:
- 概念卡片跳转逻辑符合用户预期
- 股票点击可查看公司详情,提供更多信息
- 事件冒泡控制正确,避免误触发

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 12:58:21 +08:00
zdl
7291777488 feat: 优化股票卡片交互体验
StockListItem 组件优化:
- 整个卡片可点击,点击后跳转到股票详情页(新标签页)
- 添加 cursor="pointer" 鼠标悬停提示
- 分时图/K线图区域点击时阻止事件冒泡,仅打开弹窗
- "查看"按钮、自选股按钮、展开/收起按钮点击时阻止冒泡

StockChartModal 组件修复:
- 修复 relation_desc 对象渲染错误
- 添加 getRelationDesc() 函数兼容对象和字符串格式
- 正确提取 {data: [...]} 结构中的文本内容

交互改进:
- 用户可点击卡片任意空白区域快速跳转
- 图表、按钮保持独立交互功能
- 提升用户操作便利性和体验流畅度

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 12:54:26 +08:00
zdl
92d6751529 feat: 在 DynamicNewsCard 头部集成搜索和筛选功能
功能新增:
- 将 UnifiedSearchBox 组件集成到 DynamicNewsCard 的 CardHeader 中
- 实现 DynamicNewsCard 和 EventTimelineCard 共享筛选状态
- 用户可在动态新闻区域直接进行搜索和筛选操作

组件修改:
- DynamicNewsCard.js:
  * 导入 UnifiedSearchBox 组件
  * 添加 filters, popularKeywords, onSearch, onSearchFocus 等 props
  * 在 CardHeader 内部渲染搜索框(标题下方,mt={4})
- Community/index.js:
  * 向 DynamicNewsCard 传递筛选状态和回调函数
  * filters 和 popularKeywords 数据传递
  * updateFilters 和 scrollToTimeline 回调传递

布局结构:
CardHeader
├─ 第一行:标题、徽章、更新时间
└─ 第二行:UnifiedSearchBox(搜索框 + 热门概念 + 筛选器)

状态管理:
- 使用共享的 filters 状态(来自 useEventFilters hook)
- 搜索操作通过 updateFilters 回调同步到父组件
- 两个组件的筛选条件保持一致

用户体验提升:
- 用户无需滚动到页面底部即可进行搜索
- 动态新闻区域功能更完整和独立
- 搜索结果在两个组件间同步显示

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 12:49:58 +08:00
zdl
95134d526d feat(HistoricalEvents): 优化历史事件列表 UI 和相关股票弹窗
主要改进:
1. 历史事件列表改为卡片式网格布局
   - 移除时间轴样式(垂直线 + 节点图标)
   - 使用 SimpleGrid 响应式布局(1列/2列/3列)
   - 卡片显示:事件名称、日期、相关度、重要性、描述
   - 点击"相关股票"按钮打开 Modal 弹窗

2. 历史事件对比默认展开
   - DynamicNewsDetailPanel: isHistoricalOpen 初始值改为 true
   - 用户打开事件详情面板时,历史事件对比区域默认展开

3. 相关股票弹窗改为卡片式布局
   - StocksList 组件从 Table 表格改为 SimpleGrid 卡片
   - 显示 6 个字段:代码、名称、板块、相关度、涨幅、关联原因
   - 关联原因支持展开/收起(startingHeight: 40px)
   - 响应式网格布局(base: 1列, md: 2列, lg: 3列)

4. 修复字段映射兼容性
   - 添加 getEventDate() 兼容多种日期字段
   - 添加 getEventContent() 兼容多种内容字段
   - 支持字段:event_date/created_at/date、content/description/summary
   - 添加 Debug 日志输出实际数据结构

5. 修复弹窗关闭问题
   - 添加 handleCloseModal() 同时清空两个状态
   - 使用条件渲染 {stocksModalOpen && <Modal>}
   - 关闭时完全卸载 Modal 组件,避免状态残留

技术细节:
- 移除未使用的导入(Table, Thead, Tbody, Tr, Th, Td 等)
- 新增工具函数:formatChange, getChangeColor, getCorrelationColor
- 卡片 hover 效果:boxShadow + borderColor 变化
- 涨跌幅颜色:红色(上涨)/ 绿色(下跌)
- 相关度颜色梯度:>=80% 红色, >=60% 橙色, <60% 绿色

代码统计:
- HistoricalEvents.js: -402 行, +344 行(净减少 58 行)
- 移除时间轴复杂逻辑,简化组件结构
- 提升代码可维护性和可读性

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 12:41:02 +08:00
zdl
cc2777ae20 feat: 实现实时要闻服务端分页功能
功能新增:
- 实时要闻组件支持服务端分页,每次切换页码重新请求数据
- 分页控制器组件,支持数字页码、上下翻页、快速跳转
- Mock 数据量从 100 条增加到 200 条,支持分页测试

技术实现:

1. Redux 状态管理(communityDataSlice.js)
   - fetchDynamicNews 接收分页参数 { page, per_page }
   - 返回数据结构调整为 { events, pagination }
   - initialState 新增 dynamicNewsPagination 字段
   - Reducer 分别存储 events 和 pagination 信息
   - Selector 返回完整的 pagination 数据

2. 组件层(index.js → DynamicNewsCard → EventScrollList)
   - Community/index.js: 获取并传递 pagination 信息
   - DynamicNewsCard.js: 管理分页状态,触发服务端请求
   - EventScrollList.js: 接收服务端 totalPages,渲染当前页数据
   - 页码切换时自动选中第一个事件

3. 分页控制器(PaginationControl.js)
   - 精简版设计:移除首页/末页按钮
   - 上一页/下一页按钮,边界状态自动禁用
   - 智能页码列表(最多5个,使用省略号)
   - 输入框跳转功能,支持回车键
   - Toast 提示非法输入
   - 全部使用 xs 尺寸,紧凑布局

4. Mock 数据(events.js)
   - 总事件数从 100 增加到 200 条
   - 支持服务端分页测试(40 页 × 5 条/页)

分页流程:
1. 初始加载:请求 page=1, per_page=5
2. 切换页码:dispatch(fetchDynamicNews({ page: 2, per_page: 5 }))
3. 后端返回:{ events: [5条], pagination: { page, total, total_pages } }
4. 前端更新:显示新页面数据,更新分页控制器状态

UI 优化:
- 紧凑的分页控制器布局
- 移除冗余元素(首页/末页/总页数提示)
- xs 尺寸按钮,减少视觉负担
- 保留核心功能(翻页、页码、跳转)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 12:38:25 +08:00
zdl
39a2ccd53b refactor(stockSlice): 移除 LocalStorage 缓存层,简化为两级缓存架构 2025-11-03 11:58:39 +08:00
zdl
6160edf060 feat(DynamicNewsDetailPanel): 升级为实时数据,移除模拟数据生成 2025-11-03 11:57:04 +08:00
zdl
bdea4209b2 feat: 添加 EventScrollList.js 组件 2025-11-03 11:42:04 +08:00
zdl
6cde2175db feat: 实现实时要闻事件卡片点击高亮效果
功能新增:
- 点击事件卡片后显示高亮状态
- 当前选中的卡片有明显的视觉反馈

视觉效果:
- 选中状态:蓝色浅背景 (blue.50) + 蓝色粗边框 (2px, blue.500) + 大阴影 (lg)
- 未选中状态:原样式(白色/灰色交替背景 + 细边框 + 小阴影)
- 过渡动画:0.3s 平滑过渡
- 悬停效果:选中卡片悬停时边框变为 blue.600,阴影增强为 xl

技术实现:
1. DynamicNewsCard.js:
   - 传递 isSelected prop 给 DynamicNewsEventCard
   - 判断逻辑:isSelected={selectedEvent?.id === event.id}

2. DynamicNewsEventCard.js:
   - 添加 isSelected 参数(默认 false)
   - 根据 isSelected 动态调整 Card 样式:
     - 背景色:选中 blue.50 / 未选中 原样式
     - 边框:选中 2px blue.500 / 未选中 1px 原颜色
     - 阴影:选中 lg / 未选中 sm

用户体验提升:
- 清晰显示当前查看的事件
- 与下方详情面板形成呼应
- 视觉反馈明确,交互友好

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 11:28:03 +08:00
zdl
f432d72151 fix: 移除 DynamicNewsCard 点击事件时的弹窗触发
问题描述:
- 点击新闻卡片时,既更新了详情组件,又触发了不需要的弹窗
- 用户只希望更新下方的详情面板,不需要弹窗

解决方案:
- 移除 onEventClick 和 onTitleClick 中对父组件回调的调用
- 保留 setSelectedEvent 更新逻辑
- 详情面板仍然正常更新显示

修改位置:
- src/views/Community/components/DynamicNewsCard.js 第226-235行

交互效果:
- 点击新闻卡片 → 只更新下方的 DynamicNewsDetailPanel
- 不再触发任何额外的弹窗
- 保持内联详情面板显示方式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 11:19:10 +08:00
zdl
befa68cc51 feat: 接入真实数据 2025-11-03 10:06:48 +08:00
zdl
7ae4bc418f feat: 提取交易日期 2025-11-02 16:41:55 +08:00
zdl
0110dc2fdc feat: 添加滚动组件 2025-11-02 16:41:21 +08:00
zdl
e7e2b3bb11 feat: 提交迷你分时图组件 2025-11-02 16:38:44 +08:00
zdl
e22a39c5cd feat: 提交历史事件对比组件 2025-11-02 16:37:46 +08:00
zdl
3b8b749eb1 feat: 添加相关股票模块 2025-11-01 12:19:47 +08:00
zdl
571d5e68bc feat:删除不必要组件 2025-10-31 20:12:05 +08:00
zdl
933932b86d feat:添加mock数据 2025-10-31 20:11:50 +08:00
zdl
fc251ede05 feat: 添加相关概念组件 2025-10-31 20:08:53 +08:00
zdl
57c4c3c959 feat: 添加可折叠模块标题组件 2025-10-31 18:15:39 +08:00
zdl
e1e82555bf feat: 事件滑动面板添加 详情面板 2025-10-31 18:14:05 +08:00
zdl
b44a0ccd39 feat: 添加事件描述组件 2025-10-31 17:50:23 +08:00
zdl
2d936ca1c7 feat: UI调整 2025-10-31 16:29:11 +08:00
zdl
14db374820 style: 优化事件详情和涨跌幅指标的视觉效果
EventHeaderInfo 组件优化:
- "重要性:高"背景色改为浅杏黄色(yellow.100 → orange.50)
- 文字颜色改为深杏色(yellow.700 → orange.800)
- 视觉效果更柔和优雅,不刺眼

StockChangeIndicators 组件优化:
- 改用多颜色梯度(5级分级)
- 上涨:红色系(red.900/700/500)→ 橙色系(orange.600/400)
- 下跌:绿色系(green.900/700/500)→ 青色系(teal.600/400)
- 背景色和边框色跟随数字颜色
- 移除调试 console.log

视觉改进:
- 颜色分级更细腻,从3级增加到5级
- 引入橙色和青色让小幅和大幅波动有明显色系区别
- 5.7% 显示为深红色,1.7% 显示为橙色,视觉区分明显

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 16:00:37 +08:00
zdl
db472620f3 feat: 添加事件详情头部 2025-10-31 15:33:22 +08:00
zdl
37d98203a3 fix: 优化概念中心时间轴弹窗关闭行为,使用条件渲染
问题描述:
- 点击关闭按钮后,弹窗未完全关闭
- 可能存在 DOM 残留或状态问题

优化方案:
- 使用条件渲染替代 isOpen 属性控制
- 当状态为 false 时,Modal 组件完全从 DOM 中卸载
- 确保每次打开都是全新的状态

修改内容:
1. 主时间轴 Modal:添加 {isOpen && <Modal>...</Modal>} 条件渲染
2. 研报详情 Modal:添加 {isReportModalOpen && <Modal>...</Modal>} 条件渲染
3. 新闻详情 Modal:添加 {isNewsModalOpen && <Modal>...</Modal>} 条件渲染

优化效果:
- 弹窗关闭后组件完全卸载,避免残留
- 减少不必要的 DOM 节点,提升性能
- 每次打开都是全新的组件实例

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 15:05:15 +08:00
zdl
2420ff45a4 feat:暂时注释掉市场复盘 2025-10-31 15:01:53 +08:00
zdl
adaebbf800 fix: 修复概念中心历史时间轴"查看详情"按钮无响应问题
问题描述:
- 在历史时间轴弹窗中,点击新闻或研报的"查看详情"按钮无响应
- 导致用户无法查看新闻/研报的详细内容

问题根因:
- 在 onClick 事件处理函数中使用了未定义的变量 `date`
- 应该使用循环中的 `item.date` 变量
- 未定义的变量导致追踪函数报错,阻止了后续代码执行
- Modal 无法正常打开

修复内容:
- 第750行:trackNewsClicked(event, date) → trackNewsClicked(event, item.date)
- 第763行:trackReportClicked(event, date) → trackReportClicked(event, item.date)

影响范围:
- 概念中心历史时间轴功能
- 新闻和研报详情查看功能

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 14:51:53 +08:00
zdl
9fd9fcb731 feat: 添加事件详情面板 2025-10-31 14:38:43 +08:00
zdl
c372832f1f feat: 新增实时要闻·动态追踪与市场复盘功能,优化导航体验
新增功能:
- 实时要闻·动态追踪横向滚动卡片(DynamicNewsCard)
- 动态新闻事件卡片组件(DynamicNewsEventCard)
- 市场复盘卡片组件(MarketReviewCard)
- 股票涨跌幅指标组件(StockChangeIndicators)
- 交易时间工具函数(tradingTimeUtils)
- Mock API 支持动态新闻数据生成

UI 优化:
- EventFollowButton 改用 react-icons 星星图标,实现真正的空心/实心效果
- 关注按钮添加半透明白色背景(whiteAlpha.500),悬停效果更明显
- 事件卡片标题添加右侧留白,防止关注按钮遮挡文字

性能优化:
- 禁用 Router v7_startTransition 特性,解决路由切换延迟 2 秒问题
- 调整导航菜单点击顺序(先跳转后关闭),提升响应速度

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 14:11:03 +08:00
zdl
5d8ad5e442 feat: bugfix 2025-10-31 10:33:53 +08:00
zdl
f05daa3a78 fix(TradingSimulation): 修复 React Hooks 调用顺序错误
提取 JSX 中直接调用的 useColorModeValue 到组件顶部,避免 Hooks 顺序不一致。

修改内容:
- 在第 95 行添加 contentTextColor 常量
- 替换第 350 行 Heading 中的内联 Hook 调用
- 替换第 361 行 Text 中的内联 Hook 调用

修复警告:React has detected a change in the order of Hooks called by TradingSimulation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 19:08:24 +08:00
zdl
2461ce81c9 fix: 修复导航菜单 hover 触发实现方式
修复之前提交(47f84c5)中使用的无效 trigger="hover" 属性。
Chakra UI Menu 组件不支持 trigger 属性,改用正确的实现方式:

**实现方式:**
- 使用 useDisclosure Hook 管理菜单开关状态
- 为 MenuButton 和 MenuList 添加 onMouseEnter/onMouseLeave 事件
- 这样可以确保鼠标从按钮移到菜单列表时保持打开状态

**修改的组件:**
- DesktopNav.js: 为4个菜单添加独立的 useDisclosure Hook
- MoreMenu.js: 平板版"更多"菜单
- PersonalCenterMenu.js: 个人中心菜单

**技术要点:**
- MenuButton 和 MenuList 都需要 hover 事件处理
- 每个菜单使用独立的 useDisclosure 实例
- 符合 Chakra UI 官方推荐的 hover 菜单实现方式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 19:06:21 +08:00
zdl
85d505cd53 fix: 修复 InvestmentCalendar Ant Design 5.x API 废弃警告
## 问题
控制台出现 4 个 Ant Design API 废弃警告:
```
[antd: Calendar] `dateCellRender` is deprecated. Please use `cellRender` instead.
[antd: Modal] `visible` is deprecated. Please use `open` instead.
[antd: Modal] `bodyStyle` is deprecated. Please use `styles.body` instead.
[antd: Drawer] `visible` is deprecated. Please use `open` instead.
```

## 修复内容

### 1. Calendar API (Line 137, 687)
**旧 API**:
```javascript
const dateCellRender = (value) => {
  const dateStr = value.format('YYYY-MM-DD');
  // ...
};
<Calendar dateCellRender={dateCellRender} />
```

**新 API (Ant Design 5.x)**:
```javascript
const cellRender = (current, info) => {
  // 只处理日期单元格,月份单元格返回默认
  if (info.type !== 'date') return info.originNode;

  const dateStr = current.format('YYYY-MM-DD');
  // ...
};
<Calendar cellRender={cellRender} />
```

### 2. Modal API (Line 701, 766)
`visible` → `open`
```javascript
// 旧 API
<Modal visible={modalVisible} />

// 新 API
<Modal open={modalVisible} />
```

### 3. Modal Styles API (Line 705)
`bodyStyle` → `styles.body`
```javascript
// 旧 API
<Modal bodyStyle={{ padding: '24px' }} />

// 新 API
<Modal styles={{ body: { padding: '24px' } }} />
```

### 4. Drawer API (Line 740)
`visible` → `open`
```javascript
// 旧 API
<Drawer visible={detailDrawerVisible} />

// 新 API
<Drawer open={detailDrawerVisible} />
```

## 影响
-  消除 4 个 Ant Design API 废弃警告
-  兼容 Ant Design 5.x
-  功能不受影响

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 19:04:30 +08:00
zdl
1886c54e0f fix: 修复 StockOverview prevStats 未定义错误
## 问题
控制台报错:
```
ReferenceError: prevStats is not defined
    at fetchMarketStats (index.js:247:1)
```

## 根本原因
`fetchMarketStats` 函数中引用了不存在的变量 `prevStats`:
```javascript
//  错误代码
const newStats = {
  ...data.summary,
  rising_count: prevStats?.rising_count,
  falling_count: prevStats?.falling_count,
  date: data.trade_date
};
```

这里的 `prevStats` 变量从未定义或声明。

## 解决方案
使用状态变量 `marketStats` 来获取之前的值:
```javascript
//  正确代码
const newStats = {
  ...data.summary,
  rising_count: marketStats?.rising_count,
  falling_count: marketStats?.falling_count,
  date: data.trade_date
};
```

## 影响
-  修复市场统计数据加载错误
-  正确保留上涨/下跌家数
-  消除控制台 ReferenceError

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 18:59:49 +08:00
zdl
6829f687ee fix: 修复 MSW EventEmitter 内存泄漏警告
## 问题
控制台警告:
```
MaxListenersExceededWarning: Possible EventEmitter memory leak detected.
11 response:mocked listeners added. Use emitter.setMaxListeners() to increase limit
```

## 根本原因

类似 PostHog 的问题:

1. **React StrictMode 双重渲染** - 开发环境组件渲染两次
2. **热重载** - 代码更改时频繁重新加载模块
3. **缺少启动锁** - `startMockServiceWorker()` 被多次调用
4. **事件监听器累积** - 每次启动添加新 listener,旧的未清理

## 解决方案

### 方案A: 防止重复启动
添加启动状态锁:
```javascript
let isStarting = false;
let isStarted = false;

export async function startMockServiceWorker() {
  // 防止重复启动
  if (isStarting || isStarted) {
    console.log('[MSW] 已启动,跳过重复调用');
    return;
  }

  isStarting = true;

  try {
    await worker.start({...});
    isStarted = true;  // 成功后标记
  } finally {
    isStarting = false;  // 无论成功失败都重置
  }
}
```

### 方案B: 完善 stop 逻辑
确保正确清理:
```javascript
export function stopMockServiceWorker() {
  if (!isStarted) return;  // 避免重复停止

  worker.stop();
  isStarted = false;  // 重置状态
  console.log('[MSW] Mock Service Worker 已停止');
}
```

## 影响
-  修复 EventEmitter 内存泄漏警告
-  防止热重载时重复启动 MSW
-  正确清理事件监听器
-  提升开发体验

## 验证
重启开发服务器后:
-  不再有 MaxListenersExceededWarning
-  MSW 只启动一次
-  热重载正常工作
-  Mock 功能正常

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 18:56:12 +08:00
zdl
47f84c5eff feat: 导航菜单改为 hover 触发
为所有导航菜单组件添加 trigger="hover" 属性,使菜单在鼠标悬停时自动展开,提升用户体验。

修改的组件:
- DesktopNav.js: 4 个主导航菜单(高频跟踪、行情复盘、AGENT社群、联系我们)
- MoreMenu.js: 平板版"更多"下拉菜单
- PersonalCenterMenu.js: 个人中心下拉菜单

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 18:49:14 +08:00
zdl
a0d1790469 fix: 修复 PostHog AbortError 和重复初始化问题
## 问题
控制台报错:
```
[PostHog.js] AbortError: The user aborted a request.
```

## 根本原因

### 1. 热重载导致重复初始化
- 开发环境频繁热重载
- App.js 每次重载都调用 initPostHog()
- 之前的网络请求被新请求中断 → AbortError

### 2. 缺少初始化状态管理
- 没有防止重复初始化的锁
- 每次组件更新都可能触发新的初始化

## 解决方案

### 方案A: 防止重复初始化
添加初始化状态锁:
```javascript
let isInitializing = false;
let isInitialized = false;

export const initPostHog = () => {
  // 防止重复初始化
  if (isInitializing || isInitialized) {
    console.log('📊 PostHog 已初始化,跳过重复调用');
    return;
  }

  isInitializing = true;

  try {
    posthog.init(apiKey, {...});
    isInitialized = true;  // 成功后标记为已初始化
  } finally {
    isInitializing = false;  // 无论成功失败都重置标志
  }
};
```

### 方案B: 捕获并忽略 AbortError
在 catch 块中特殊处理:
```javascript
} catch (error) {
  // 忽略 AbortError(通常由热重载引起)
  if (error.name === 'AbortError') {
    console.log('⚠️ PostHog 初始化请求被中断(热重载)');
    return;  // 静默处理,不报错
  }
  console.error(' PostHog initialization failed:', error);
}
```

## 影响
-  修复 AbortError 警告
-  防止热重载时重复初始化
-  提升开发体验
-  不影响生产环境

## 验证
重启开发服务器后:
-  不再有 AbortError
-  PostHog 只初始化一次
-  热重载正常工作

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 18:49:03 +08:00
zdl
0364b3a927 fix(NotificationContainer): 修复 React Hooks 调用顺序错误
**问题描述**
React 检测到 NotificationItem 组件中 Hooks 调用顺序不一致:

```
Warning: React has detected a change in the order of Hooks called by null.
Previous render: 24. useCallback
Next render:     25. useContext
```

**根本原因**
在第 433 行,`useColorModeValue` Hook 在条件对象展开中被调用:

```javascript
{...(isNewest && {
    borderTopColor: useColorModeValue(...),  //  违反 Hooks 规则
})}
```

当 `isNewest` 值变化时:
- `isNewest = false` → Hook 不调用
- `isNewest = true` → Hook 调用
- 导致不同渲染的 Hooks 数量不一致

**React Hooks 规则**
> Hooks 必须在组件顶层调用,不能在条件语句、循环或嵌套函数中调用

**修复内容**

1. **将 Hook 移到组件顶层** (第 349-353 行)
```javascript
// 最新通知的 borderTopColor(避免在条件语句中调用 Hook)
const newestBorderTopColor = useColorModeValue(
    `${typeConfig.colorScheme}.100`,
    `${typeConfig.colorScheme}.700`
);
```

2. **添加到 colors 对象** (第 365 行)
```javascript
const colors = useMemo(() => ({
    // ... 其他颜色
    newestBorderTop: newestBorderTopColor,
}), [/* dependencies */]);
```

3. **在 JSX 中使用预计算的值** (第 439 行)
```diff
  {...(isNewest && {
-     borderTopColor: useColorModeValue(...),
+     borderTopColor: colors.newestBorderTop,
  })}
```

**修复验证**
-  所有 Hooks 在每次渲染都以相同顺序调用
-  消除 React Hooks 警告
-  功能保持不变(视觉效果一致)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 18:43:19 +08:00
zdl
5236976307 fix(EventList): 删除重复的 Toast 通知,统一使用右下角通知卡片
**问题描述**
新事件推送时显示两种通知:
1.  左侧顶部绿色 Toast(重复多次)
2.  右下角通知卡片(NotificationContainer)

用户反馈:只需要右下角通知卡片,不需要 Toast 提示

**修复内容**

删除 EventList.js 中的 Chakra UI Toast 通知代码(13 行):

```diff
- console.log('[EventList DEBUG] 准备显示 Toast 通知');
- // 显示 Toast 通知 - 更明显的配置
- const toastId = toast({
-     title: '🔔 新事件发布',
-     description: event.title,
-     status: 'success',
-     duration: 8000,
-     isClosable: true,
-     position: 'top',
-     variant: 'solid',
- });
- console.log('[EventList DEBUG] ✓ Toast 通知已调用,ID:', toastId);
```

**保留的通知能力**
-  右下角通知卡片(NotificationContainer)
-  浏览器原生通知(需用户授权)
-  事件列表实时更新
-  PostHog 埋点追踪

**验证**
刷新页面后,新事件推送时:
-  不再显示左侧 Toast
-  只显示右下角通知卡片

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 18:39:47 +08:00