Merge branch 'feature_bugfix/251201_vf_h5_ui' into feature_bugfix/251201_py_h5_ui
* feature_bugfix/251201_vf_h5_ui: refactor: Community 目录结构重组 + 修复导入路径 + 添加 Mock 数据 feat: 添加mock数据
This commit is contained in:
@@ -121,7 +121,7 @@ const CitationMark = ({ citationId, citation }) => {
|
||||
title={`引用来源 [${citationId}]`}
|
||||
trigger={triggerType}
|
||||
placement="top"
|
||||
overlayInnerStyle={{ maxWidth: 340, padding: '8px' }}
|
||||
styles={{ body: { maxWidth: 340, padding: '8px' } }}
|
||||
open={popoverVisible}
|
||||
onOpenChange={setPopoverVisible}
|
||||
zIndex={2000}
|
||||
|
||||
@@ -146,7 +146,7 @@ const CitedContent = ({
|
||||
</div>
|
||||
|
||||
{/* 响应式样式 */}
|
||||
<style jsx>{`
|
||||
<style>{`
|
||||
@media (max-width: 768px) {
|
||||
.ai-badge-responsive {
|
||||
font-size: 10px !important;
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import { ViewIcon } from '@chakra-ui/icons';
|
||||
import EventFollowButton from '@views/Community/components/EventCard/EventFollowButton';
|
||||
import { EventFollowButton } from '@views/Community/components/EventCard/atoms';
|
||||
|
||||
/**
|
||||
* 精简信息栏组件
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
import { ViewIcon } from '@chakra-ui/icons';
|
||||
import dayjs from 'dayjs';
|
||||
import StockChangeIndicators from '../StockChangeIndicators';
|
||||
import EventFollowButton from '@views/Community/components/EventCard/EventFollowButton';
|
||||
import { EventFollowButton } from '@views/Community/components/EventCard/atoms';
|
||||
|
||||
/**
|
||||
* 事件头部信息区组件
|
||||
|
||||
@@ -111,18 +111,24 @@ export const generateMarketData = (stockCode) => {
|
||||
}
|
||||
},
|
||||
|
||||
// 涨停分析
|
||||
// 涨停分析 - 返回数组格式,每个元素对应一个交易日
|
||||
riseAnalysisData: {
|
||||
success: true,
|
||||
data: {
|
||||
is_limit_up: false,
|
||||
limit_up_price: basePrice * 1.10,
|
||||
current_price: basePrice,
|
||||
distance_to_limit: 8.92, // %
|
||||
consecutive_days: 0,
|
||||
reason: '',
|
||||
concept_tags: ['银行', '深圳国资', 'MSCI', '沪深300']
|
||||
}
|
||||
data: Array(30).fill(null).map((_, i) => {
|
||||
const tradeDate = new Date(Date.now() - (29 - i) * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
|
||||
const isLimitUp = Math.random() < 0.05; // 5%概率涨停
|
||||
return {
|
||||
trade_date: tradeDate,
|
||||
is_limit_up: isLimitUp,
|
||||
limit_up_price: (basePrice * 1.10).toFixed(2),
|
||||
current_price: (basePrice + (Math.random() - 0.5) * 0.5).toFixed(2),
|
||||
distance_to_limit: (Math.random() * 10).toFixed(2), // %
|
||||
consecutive_days: isLimitUp ? Math.floor(Math.random() * 3) + 1 : 0,
|
||||
reason: isLimitUp ? '业绩超预期' : '',
|
||||
concept_tags: ['银行', '深圳国资', 'MSCI', '沪深300'],
|
||||
analysis: isLimitUp ? '股价触及涨停板,资金流入明显' : '股价正常波动,交投活跃'
|
||||
};
|
||||
})
|
||||
},
|
||||
|
||||
// 最新分时数据
|
||||
|
||||
@@ -212,4 +212,64 @@ export const companyHandlers = [
|
||||
data: data.forecastReport || null
|
||||
});
|
||||
}),
|
||||
|
||||
// 14. 价值链关联公司
|
||||
http.get('/api/company/value-chain/related-companies', async ({ request }) => {
|
||||
await delay(300);
|
||||
|
||||
const url = new URL(request.url);
|
||||
const nodeName = url.searchParams.get('node_name') || '';
|
||||
|
||||
console.log('[Mock] 获取价值链关联公司:', nodeName);
|
||||
|
||||
// 生成模拟的关联公司数据
|
||||
const relatedCompanies = [
|
||||
{
|
||||
stock_code: '601318',
|
||||
stock_name: '中国平安',
|
||||
industry: '保险',
|
||||
relation: '同业竞争',
|
||||
market_cap: 9200,
|
||||
change_pct: 1.25
|
||||
},
|
||||
{
|
||||
stock_code: '600036',
|
||||
stock_name: '招商银行',
|
||||
industry: '银行',
|
||||
relation: '核心供应商',
|
||||
market_cap: 8500,
|
||||
change_pct: 0.85
|
||||
},
|
||||
{
|
||||
stock_code: '601166',
|
||||
stock_name: '兴业银行',
|
||||
industry: '银行',
|
||||
relation: '同业竞争',
|
||||
market_cap: 4200,
|
||||
change_pct: -0.32
|
||||
},
|
||||
{
|
||||
stock_code: '601398',
|
||||
stock_name: '工商银行',
|
||||
industry: '银行',
|
||||
relation: '同业竞争',
|
||||
market_cap: 15000,
|
||||
change_pct: 0.15
|
||||
},
|
||||
{
|
||||
stock_code: '601288',
|
||||
stock_name: '农业银行',
|
||||
industry: '银行',
|
||||
relation: '同业竞争',
|
||||
market_cap: 12000,
|
||||
change_pct: -0.08
|
||||
}
|
||||
];
|
||||
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
data: relatedCompanies,
|
||||
node_name: nodeName
|
||||
});
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -297,6 +297,45 @@ export const eventHandlers = [
|
||||
}
|
||||
}),
|
||||
|
||||
// 获取事件超预期得分
|
||||
http.get('/api/events/:eventId/expectation-score', async ({ params }) => {
|
||||
await delay(200);
|
||||
|
||||
const { eventId } = params;
|
||||
|
||||
console.log('[Mock] 获取事件超预期得分, eventId:', eventId);
|
||||
|
||||
try {
|
||||
// 生成模拟的超预期得分数据
|
||||
const score = parseFloat((Math.random() * 100).toFixed(1));
|
||||
const avgChange = parseFloat((Math.random() * 10 - 2).toFixed(2));
|
||||
const maxChange = parseFloat((Math.random() * 15).toFixed(2));
|
||||
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
data: {
|
||||
event_id: parseInt(eventId),
|
||||
expectation_score: score,
|
||||
avg_change: avgChange,
|
||||
max_change: maxChange,
|
||||
stock_count: Math.floor(Math.random() * 20) + 5,
|
||||
updated_at: new Date().toISOString(),
|
||||
},
|
||||
message: '获取成功'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Mock] 获取事件超预期得分失败:', error);
|
||||
return HttpResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: '获取事件超预期得分失败',
|
||||
data: null
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}),
|
||||
|
||||
// 获取事件相关股票
|
||||
http.get('/api/events/:eventId/stocks', async ({ params }) => {
|
||||
await delay(300);
|
||||
|
||||
@@ -8,6 +8,53 @@ import { generateMarketData } from '../data/market';
|
||||
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
export const marketHandlers = [
|
||||
// 0. 指数实时行情数据
|
||||
http.get('/api/index/:indexCode/realtime', async ({ params }) => {
|
||||
await delay(100);
|
||||
const { indexCode } = params;
|
||||
|
||||
console.log('[Mock] 获取指数实时行情, indexCode:', indexCode);
|
||||
|
||||
// 指数基础数据
|
||||
const indexData = {
|
||||
'000001': { name: '上证指数', basePrice: 3200, baseVolume: 3500 },
|
||||
'399001': { name: '深证成指', basePrice: 10500, baseVolume: 4200 },
|
||||
'399006': { name: '创业板指', basePrice: 2100, baseVolume: 1800 },
|
||||
'000300': { name: '沪深300', basePrice: 3800, baseVolume: 2800 },
|
||||
'000016': { name: '上证50', basePrice: 2600, baseVolume: 1200 },
|
||||
'000905': { name: '中证500', basePrice: 5800, baseVolume: 1500 },
|
||||
};
|
||||
|
||||
const baseData = indexData[indexCode] || { name: `指数${indexCode}`, basePrice: 3000, baseVolume: 2000 };
|
||||
|
||||
// 生成随机波动
|
||||
const changePercent = parseFloat((Math.random() * 4 - 2).toFixed(2)); // -2% ~ +2%
|
||||
const price = parseFloat((baseData.basePrice * (1 + changePercent / 100)).toFixed(2));
|
||||
const change = parseFloat((price - baseData.basePrice).toFixed(2));
|
||||
const volume = parseFloat((baseData.baseVolume * (0.8 + Math.random() * 0.4)).toFixed(2)); // 80%-120% of base
|
||||
const amount = parseFloat((volume * price / 10000).toFixed(2)); // 亿元
|
||||
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
data: {
|
||||
index_code: indexCode,
|
||||
index_name: baseData.name,
|
||||
current_price: price,
|
||||
change: change,
|
||||
change_percent: changePercent,
|
||||
open_price: parseFloat((baseData.basePrice * (1 + (Math.random() * 0.01 - 0.005))).toFixed(2)),
|
||||
high_price: parseFloat((price * (1 + Math.random() * 0.01)).toFixed(2)),
|
||||
low_price: parseFloat((price * (1 - Math.random() * 0.01)).toFixed(2)),
|
||||
prev_close: baseData.basePrice,
|
||||
volume: volume, // 亿手
|
||||
amount: amount, // 亿元
|
||||
update_time: new Date().toISOString(),
|
||||
market_status: 'trading', // trading, closed, pre-market, after-hours
|
||||
},
|
||||
message: '获取成功'
|
||||
});
|
||||
}),
|
||||
|
||||
// 1. 成交数据
|
||||
http.get('/api/market/trade/:stockCode', async ({ params, request }) => {
|
||||
await delay(200);
|
||||
|
||||
184
src/views/Community/README.md
Normal file
184
src/views/Community/README.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Community 模块说明
|
||||
|
||||
本目录包含社区页面的所有组件,按功能模块进行组织。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
src/views/Community/
|
||||
├── index.js # 页面入口
|
||||
├── components/ # 组件目录
|
||||
│ ├── SearchFilters/ # 搜索筛选模块
|
||||
│ │ ├── CompactSearchBox.js
|
||||
│ │ ├── CompactSearchBox.css
|
||||
│ │ ├── TradingTimeFilter.js
|
||||
│ │ └── index.js
|
||||
│ ├── EventCard/ # 事件卡片模块
|
||||
│ │ ├── atoms/ # 原子组件
|
||||
│ │ └── index.js
|
||||
│ ├── HotEvents/ # 热点事件模块
|
||||
│ │ ├── HotEvents.js
|
||||
│ │ ├── HotEvents.css
|
||||
│ │ ├── HotEventsSection.js
|
||||
│ │ └── index.js
|
||||
│ ├── DynamicNews/ # 动态新闻模块
|
||||
│ │ ├── layouts/
|
||||
│ │ ├── hooks/
|
||||
│ │ └── index.js
|
||||
│ ├── EventDetailModal/ # 事件详情弹窗模块
|
||||
│ │ ├── EventDetailModal.tsx
|
||||
│ │ ├── EventDetailModal.less
|
||||
│ │ └── index.ts
|
||||
│ └── HeroPanel.js # 英雄面板(独立组件)
|
||||
└── hooks/ # 页面级 Hooks
|
||||
├── useEventData.js
|
||||
├── useEventFilters.js
|
||||
└── useCommunityEvents.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. SearchFilters 模块(搜索筛选)
|
||||
|
||||
路径:`components/SearchFilters/`
|
||||
|
||||
| 文件 | 行数 | 功能 |
|
||||
|------|------|------|
|
||||
| `CompactSearchBox.js` | 612 | 紧凑搜索框,集成关键词搜索、概念/行业筛选 |
|
||||
| `TradingTimeFilter.js` | 491 | 交易时间筛选器,被 CompactSearchBox 引用 |
|
||||
|
||||
**使用方式**:
|
||||
```javascript
|
||||
import { CompactSearchBox } from './components/SearchFilters';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. EventCard 模块(事件卡片)
|
||||
|
||||
路径:`components/EventCard/`
|
||||
|
||||
### 主卡片组件
|
||||
|
||||
| 文件 | 功能 |
|
||||
|------|------|
|
||||
| `CompactEventCard.js` | 紧凑事件卡片(列表模式) |
|
||||
| `DetailedEventCard.js` | 详细事件卡片(展开模式) |
|
||||
| `DynamicNewsEventCard.js` | 动态新闻事件卡片 |
|
||||
| `HorizontalDynamicNewsEventCard.js` | 水平布局新闻卡片 |
|
||||
|
||||
### 原子组件(atoms/)
|
||||
|
||||
| 文件 | 功能 |
|
||||
|------|------|
|
||||
| `EventHeader.js` | 事件标题头部 |
|
||||
| `EventDescription.js` | 事件描述文本 |
|
||||
| `EventStats.js` | 事件统计数据 |
|
||||
| `EventPriceDisplay.js` | 股价显示 |
|
||||
| `EventTimeline.js` | 事件时间线 |
|
||||
| `EventFollowButton.js` | 关注按钮 |
|
||||
| `EventImportanceBadge.js` | 重要性徽章 |
|
||||
| `ImportanceBadge.js` | 通用重要性徽章 |
|
||||
| `ImportanceStamp.js` | 重要性印章 |
|
||||
| `KeywordsCarousel.js` | 关键词轮播 |
|
||||
|
||||
**使用方式**:
|
||||
```javascript
|
||||
// 使用主卡片组件
|
||||
import EventCard from './components/EventCard';
|
||||
|
||||
// 使用原子组件
|
||||
import { EventHeader, EventTimeline } from './components/EventCard/atoms';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. HotEvents 模块(热点事件)
|
||||
|
||||
路径:`components/HotEvents/`
|
||||
|
||||
| 文件 | 功能 |
|
||||
|------|------|
|
||||
| `HotEvents.js` | 热点事件列表渲染 |
|
||||
| `HotEventsSection.js` | 热点事件区块容器 |
|
||||
|
||||
**使用方式**:
|
||||
```javascript
|
||||
import { HotEventsSection } from './components/HotEvents';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. DynamicNews 模块(动态新闻)
|
||||
|
||||
路径:`components/DynamicNews/`
|
||||
|
||||
### 主组件
|
||||
|
||||
| 文件 | 功能 |
|
||||
|------|------|
|
||||
| `DynamicNewsCard.js` | 主列表容器(695行) |
|
||||
| `EventScrollList.js` | 事件滚动列表 |
|
||||
| `EventDetailScrollPanel.js` | 事件详情滚动面板 |
|
||||
| `ModeToggleButtons.js` | 模式切换按钮 |
|
||||
| `PaginationControl.js` | 分页控制器 |
|
||||
| `constants.js` | 常量配置 |
|
||||
|
||||
### 布局组件(layouts/)
|
||||
|
||||
| 文件 | 功能 |
|
||||
|------|------|
|
||||
| `VerticalModeLayout.js` | 垂直布局模式 |
|
||||
| `VirtualizedFourRowGrid.js` | 虚拟滚动四行网格(性能优化) |
|
||||
|
||||
### Hooks(hooks/)
|
||||
|
||||
| 文件 | 功能 |
|
||||
|------|------|
|
||||
| `usePagination.js` | 分页逻辑 Hook |
|
||||
|
||||
**使用方式**:
|
||||
```javascript
|
||||
import { DynamicNewsCard } from './components/DynamicNews';
|
||||
import { usePagination } from './components/DynamicNews/hooks';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. EventDetailModal 模块(事件详情弹窗)
|
||||
|
||||
路径:`components/EventDetailModal/`
|
||||
|
||||
| 文件 | 功能 |
|
||||
|------|------|
|
||||
| `EventDetailModal.tsx` | 事件详情弹窗(TypeScript) |
|
||||
| `EventDetailModal.less` | 弹窗样式 |
|
||||
|
||||
**使用方式**:
|
||||
```javascript
|
||||
import EventDetailModal from './components/EventDetailModal';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 独立组件
|
||||
|
||||
路径:`components/`
|
||||
|
||||
| 文件 | 行数 | 功能 |
|
||||
|------|------|------|
|
||||
| `HeroPanel.js` | 972 | 首页英雄面板(指数K线 + 概念词云) |
|
||||
|
||||
**说明**:
|
||||
- `HeroPanel.js` 使用懒加载,包含 ECharts (~600KB)
|
||||
|
||||
---
|
||||
|
||||
## 更新日志
|
||||
|
||||
- **2024-12-09**: 目录结构重组
|
||||
- 创建 `SearchFilters/` 模块(含 CSS)
|
||||
- 创建 `EventCard/atoms/` 原子组件目录
|
||||
- 创建 `HotEvents/` 模块(含 CSS)
|
||||
- 重组 `DynamicNews/` 模块(含 layouts/ 和 hooks/)
|
||||
- 创建 `EventDetailModal/` 模块
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/DynamicNewsCard.js
|
||||
// src/views/Community/components/DynamicNews/DynamicNewsCard.js
|
||||
// 横向滚动事件卡片组件(实时要闻·动态追踪)
|
||||
|
||||
import React, { forwardRef, useState, useEffect, useMemo, useCallback, useRef, useImperativeHandle } from 'react';
|
||||
@@ -30,23 +30,23 @@ import {
|
||||
Icon,
|
||||
} from '@chakra-ui/react';
|
||||
import { TimeIcon, BellIcon } from '@chakra-ui/icons';
|
||||
import { useNotification } from '../../../contexts/NotificationContext';
|
||||
import EventScrollList from './DynamicNewsCard/EventScrollList';
|
||||
import ModeToggleButtons from './DynamicNewsCard/ModeToggleButtons';
|
||||
import PaginationControl from './DynamicNewsCard/PaginationControl';
|
||||
import { useNotification } from '@contexts/NotificationContext';
|
||||
import EventScrollList from './EventScrollList';
|
||||
import ModeToggleButtons from './ModeToggleButtons';
|
||||
import PaginationControl from './PaginationControl';
|
||||
import DynamicNewsDetailPanel from '@components/EventDetailPanel';
|
||||
import CompactSearchBox from './CompactSearchBox';
|
||||
import CompactSearchBox from '../SearchFilters/CompactSearchBox';
|
||||
import {
|
||||
fetchDynamicNews,
|
||||
toggleEventFollow,
|
||||
selectEventFollowStatus,
|
||||
selectVerticalEventsWithLoading,
|
||||
selectFourRowEventsWithLoading
|
||||
} from '../../../store/slices/communityDataSlice';
|
||||
import { usePagination } from './DynamicNewsCard/hooks/usePagination';
|
||||
import { PAGINATION_CONFIG, DISPLAY_MODES, REFRESH_DEBOUNCE_DELAY } from './DynamicNewsCard/constants';
|
||||
import { PROFESSIONAL_COLORS } from '../../../constants/professionalTheme';
|
||||
import { debounce } from '../../../utils/debounce';
|
||||
} from '@store/slices/communityDataSlice';
|
||||
import { usePagination } from './hooks/usePagination';
|
||||
import { PAGINATION_CONFIG, DISPLAY_MODES, REFRESH_DEBOUNCE_DELAY } from './constants';
|
||||
import { PROFESSIONAL_COLORS } from '@constants/professionalTheme';
|
||||
import { debounce } from '@utils/debounce';
|
||||
import { useDevice } from '@hooks/useDevice';
|
||||
|
||||
// 🔍 调试:渲染计数器
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/DynamicNewsCard/EventDetailScrollPanel.js
|
||||
// src/views/Community/components/DynamicNews/EventDetailScrollPanel.js
|
||||
// 事件详情滚动面板组件
|
||||
|
||||
import React from 'react';
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/DynamicNewsCard/EventScrollList.js
|
||||
// src/views/Community/components/DynamicNews/EventScrollList.js
|
||||
// 横向滚动事件列表组件
|
||||
|
||||
import React, { useRef, useCallback } from 'react';
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
Box,
|
||||
useColorModeValue
|
||||
} from '@chakra-ui/react';
|
||||
import VirtualizedFourRowGrid from './VirtualizedFourRowGrid';
|
||||
import VerticalModeLayout from './VerticalModeLayout';
|
||||
import VirtualizedFourRowGrid from './layouts/VirtualizedFourRowGrid';
|
||||
import VerticalModeLayout from './layouts/VerticalModeLayout';
|
||||
|
||||
/**
|
||||
* 事件列表组件 - 支持纵向和平铺两种展示模式
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/DynamicNewsCard/ModeToggleButtons.js
|
||||
// src/views/Community/components/DynamicNews/ModeToggleButtons.js
|
||||
// 事件列表模式切换按钮组
|
||||
|
||||
import React from 'react';
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/DynamicNewsCard/PaginationControl.js
|
||||
// src/views/Community/components/DynamicNews/PaginationControl.js
|
||||
// 分页控制器组件
|
||||
|
||||
import React, { useState } from 'react';
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/DynamicNewsCard/constants.js
|
||||
// src/views/Community/components/DynamicNews/constants.js
|
||||
// 动态新闻卡片组件 - 常量配置
|
||||
|
||||
// ========== 分页配置常量 ==========
|
||||
@@ -0,0 +1,4 @@
|
||||
// src/views/Community/components/DynamicNews/hooks/index.js
|
||||
// Hooks
|
||||
|
||||
export { usePagination } from './usePagination';
|
||||
@@ -1,9 +1,9 @@
|
||||
// src/views/Community/components/DynamicNewsCard/hooks/usePagination.js
|
||||
// src/views/Community/components/DynamicNews/hooks/usePagination.js
|
||||
// 分页逻辑自定义 Hook
|
||||
|
||||
import { useState, useMemo, useCallback, useRef } from 'react';
|
||||
import { fetchDynamicNews, updatePaginationPage } from '../../../../../store/slices/communityDataSlice';
|
||||
import { logger } from '../../../../../utils/logger';
|
||||
import { fetchDynamicNews, updatePaginationPage } from '@store/slices/communityDataSlice';
|
||||
import { logger } from '@utils/logger';
|
||||
import {
|
||||
PAGINATION_CONFIG,
|
||||
DISPLAY_MODES,
|
||||
21
src/views/Community/components/DynamicNews/index.js
Normal file
21
src/views/Community/components/DynamicNews/index.js
Normal file
@@ -0,0 +1,21 @@
|
||||
// src/views/Community/components/DynamicNews/index.js
|
||||
// 动态新闻模块
|
||||
|
||||
// 主组件
|
||||
export { default as DynamicNewsCard } from './DynamicNewsCard';
|
||||
|
||||
// 布局组件
|
||||
export { default as VerticalModeLayout } from './layouts/VerticalModeLayout';
|
||||
export { default as VirtualizedFourRowGrid } from './layouts/VirtualizedFourRowGrid';
|
||||
|
||||
// 子组件
|
||||
export { default as EventScrollList } from './EventScrollList';
|
||||
export { default as EventDetailScrollPanel } from './EventDetailScrollPanel';
|
||||
export { default as ModeToggleButtons } from './ModeToggleButtons';
|
||||
export { default as PaginationControl } from './PaginationControl';
|
||||
|
||||
// Hooks
|
||||
export { usePagination } from './hooks/usePagination';
|
||||
|
||||
// 常量
|
||||
export * from './constants';
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/DynamicNewsCard/VerticalModeLayout.js
|
||||
// src/views/Community/components/DynamicNews/layouts/VerticalModeLayout.js
|
||||
// 纵向分栏模式布局组件
|
||||
|
||||
import React, { useState } from 'react';
|
||||
@@ -12,10 +12,10 @@ import {
|
||||
useDisclosure
|
||||
} from '@chakra-ui/react';
|
||||
import { InfoIcon } from '@chakra-ui/icons';
|
||||
import HorizontalDynamicNewsEventCard from '../EventCard/HorizontalDynamicNewsEventCard';
|
||||
import EventDetailScrollPanel from './EventDetailScrollPanel';
|
||||
import EventDetailModal from '../EventDetailModal';
|
||||
import PaginationControl from './PaginationControl';
|
||||
import HorizontalDynamicNewsEventCard from '../../EventCard/HorizontalDynamicNewsEventCard';
|
||||
import EventDetailScrollPanel from '../EventDetailScrollPanel';
|
||||
import EventDetailModal from '../../EventDetailModal';
|
||||
import PaginationControl from '../PaginationControl';
|
||||
|
||||
/**
|
||||
* 纵向分栏模式布局
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/DynamicNewsCard/VirtualizedFourRowGrid.js
|
||||
// src/views/Community/components/DynamicNews/layouts/VirtualizedFourRowGrid.js
|
||||
// 虚拟化网格组件(支持多列布局 + 纵向滚动 + 无限滚动)
|
||||
|
||||
import React, { useRef, useMemo, useEffect, forwardRef, useImperativeHandle } from 'react';
|
||||
@@ -6,7 +6,7 @@ import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import { Box, Grid, Spinner, Text, VStack, Center, HStack, IconButton, useBreakpointValue } from '@chakra-ui/react';
|
||||
import { RepeatIcon } from '@chakra-ui/icons';
|
||||
import { useColorModeValue } from '@chakra-ui/react';
|
||||
import DynamicNewsEventCard from '../EventCard/DynamicNewsEventCard';
|
||||
import DynamicNewsEventCard from '../../EventCard/DynamicNewsEventCard';
|
||||
|
||||
/**
|
||||
* 虚拟化网格组件(支持多列布局 + 无限滚动)
|
||||
@@ -0,0 +1,5 @@
|
||||
// src/views/Community/components/DynamicNews/layouts/index.js
|
||||
// 布局组件
|
||||
|
||||
export { default as VerticalModeLayout } from './VerticalModeLayout';
|
||||
export { default as VirtualizedFourRowGrid } from './VirtualizedFourRowGrid';
|
||||
@@ -12,13 +12,15 @@ import {
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import dayjs from 'dayjs';
|
||||
import { getImportanceConfig } from '../../../../constants/importanceLevels';
|
||||
import { getImportanceConfig } from '@constants/importanceLevels';
|
||||
|
||||
// 导入子组件
|
||||
import EventTimeline from './EventTimeline';
|
||||
import EventHeader from './EventHeader';
|
||||
import EventStats from './EventStats';
|
||||
import EventFollowButton from './EventFollowButton';
|
||||
import {
|
||||
EventTimeline,
|
||||
EventHeader,
|
||||
EventStats,
|
||||
EventFollowButton,
|
||||
} from './atoms';
|
||||
|
||||
/**
|
||||
* 紧凑模式事件卡片组件
|
||||
|
||||
@@ -10,15 +10,17 @@ import {
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import dayjs from 'dayjs';
|
||||
import { getImportanceConfig } from '../../../../constants/importanceLevels';
|
||||
import { getImportanceConfig } from '@constants/importanceLevels';
|
||||
|
||||
// 导入子组件
|
||||
import EventTimeline from './EventTimeline';
|
||||
import EventHeader from './EventHeader';
|
||||
import EventStats from './EventStats';
|
||||
import EventFollowButton from './EventFollowButton';
|
||||
import EventPriceDisplay from './EventPriceDisplay';
|
||||
import EventDescription from './EventDescription';
|
||||
import {
|
||||
EventTimeline,
|
||||
EventHeader,
|
||||
EventStats,
|
||||
EventFollowButton,
|
||||
EventPriceDisplay,
|
||||
EventDescription,
|
||||
} from './atoms';
|
||||
|
||||
/**
|
||||
* 详细模式事件卡片组件
|
||||
|
||||
@@ -12,12 +12,12 @@ import {
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import dayjs from 'dayjs';
|
||||
import { getImportanceConfig } from '../../../../constants/importanceLevels';
|
||||
import { getChangeColor } from '../../../../utils/colorUtils';
|
||||
import { getImportanceConfig } from '@constants/importanceLevels';
|
||||
import { getChangeColor } from '@utils/colorUtils';
|
||||
|
||||
// 导入子组件
|
||||
import EventFollowButton from './EventFollowButton';
|
||||
import StockChangeIndicators from '../../../../components/StockChangeIndicators';
|
||||
import { EventFollowButton } from './atoms';
|
||||
import StockChangeIndicators from '@components/StockChangeIndicators';
|
||||
|
||||
/**
|
||||
* 动态新闻事件卡片组件(极简版)
|
||||
|
||||
@@ -13,17 +13,19 @@ import {
|
||||
useColorModeValue,
|
||||
useBreakpointValue,
|
||||
} from '@chakra-ui/react';
|
||||
import { getImportanceConfig } from '../../../../constants/importanceLevels';
|
||||
import { PROFESSIONAL_COLORS } from '../../../../constants/professionalTheme';
|
||||
import { getImportanceConfig } from '@constants/importanceLevels';
|
||||
import { PROFESSIONAL_COLORS } from '@constants/professionalTheme';
|
||||
import { useDevice } from '@hooks/useDevice';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
// 导入子组件
|
||||
import ImportanceStamp from './ImportanceStamp';
|
||||
import EventTimeline from './EventTimeline';
|
||||
import EventFollowButton from './EventFollowButton';
|
||||
import StockChangeIndicators from '../../../../components/StockChangeIndicators';
|
||||
import KeywordsCarousel from './KeywordsCarousel';
|
||||
import {
|
||||
ImportanceStamp,
|
||||
EventTimeline,
|
||||
EventFollowButton,
|
||||
KeywordsCarousel,
|
||||
} from './atoms';
|
||||
import StockChangeIndicators from '@components/StockChangeIndicators';
|
||||
|
||||
/**
|
||||
* 横向布局的动态新闻事件卡片组件
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/EventCard/EventFollowButton.js
|
||||
// src/views/Community/components/EventCard/atoms/EventFollowButton.js
|
||||
import React from 'react';
|
||||
import { IconButton, Box } from '@chakra-ui/react';
|
||||
import { AiFillStar, AiOutlineStar } from 'react-icons/ai';
|
||||
@@ -1,8 +1,8 @@
|
||||
// src/views/Community/components/EventCard/EventImportanceBadge.js
|
||||
// src/views/Community/components/EventCard/atoms/EventImportanceBadge.js
|
||||
import React from 'react';
|
||||
import { Badge, Tooltip, VStack, HStack, Text, Divider, Circle } from '@chakra-ui/react';
|
||||
import { InfoIcon } from '@chakra-ui/icons';
|
||||
import { getImportanceConfig, getAllImportanceLevels } from '../../../../constants/importanceLevels';
|
||||
import { getImportanceConfig, getAllImportanceLevels } from '@constants/importanceLevels';
|
||||
|
||||
/**
|
||||
* 事件重要性等级标签组件
|
||||
@@ -1,7 +1,7 @@
|
||||
// src/views/Community/components/EventCard/EventPriceDisplay.js
|
||||
// src/views/Community/components/EventCard/atoms/EventPriceDisplay.js
|
||||
import React, { useState } from 'react';
|
||||
import { HStack, Box, Text, Tooltip, Progress } from '@chakra-ui/react';
|
||||
import { PriceArrow } from '../../../../utils/priceFormatters';
|
||||
import { PriceArrow } from '@utils/priceFormatters';
|
||||
|
||||
/**
|
||||
* 事件价格变动显示组件
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/EventCard/ImportanceBadge.js
|
||||
// src/views/Community/components/EventCard/atoms/ImportanceBadge.js
|
||||
// 重要性标签通用组件
|
||||
|
||||
import React from 'react';
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
PopoverArrow,
|
||||
Portal,
|
||||
} from '@chakra-ui/react';
|
||||
import { getImportanceConfig, getAllImportanceLevels } from '../../../../constants/importanceLevels';
|
||||
import { getImportanceConfig, getAllImportanceLevels } from '@constants/importanceLevels';
|
||||
|
||||
/**
|
||||
* 重要性标签组件(实心样式)
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/EventCard/ImportanceStamp.js
|
||||
// src/views/Community/components/EventCard/atoms/ImportanceStamp.js
|
||||
// 重要性印章组件
|
||||
|
||||
import React from 'react';
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
Text,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import { getImportanceConfig } from '../../../../constants/importanceLevels';
|
||||
import { getImportanceConfig } from '@constants/importanceLevels';
|
||||
|
||||
/**
|
||||
* 重要性印章组件(模拟盖章效果)
|
||||
@@ -1,8 +1,8 @@
|
||||
// src/views/Community/components/EventCard/KeywordsCarousel.js
|
||||
// src/views/Community/components/EventCard/atoms/KeywordsCarousel.js
|
||||
// Keywords标签组件(点击切换)
|
||||
import React, { useState } from 'react';
|
||||
import { Box, Text, Tooltip } from '@chakra-ui/react';
|
||||
import { PROFESSIONAL_COLORS } from '../../../../constants/professionalTheme';
|
||||
import { PROFESSIONAL_COLORS } from '@constants/professionalTheme';
|
||||
|
||||
/**
|
||||
* Keywords标签组件(点击切换下一个)
|
||||
13
src/views/Community/components/EventCard/atoms/index.js
Normal file
13
src/views/Community/components/EventCard/atoms/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// src/views/Community/components/EventCard/atoms/index.js
|
||||
// 事件卡片原子组件
|
||||
|
||||
export { default as EventDescription } from './EventDescription';
|
||||
export { default as EventFollowButton } from './EventFollowButton';
|
||||
export { default as EventHeader } from './EventHeader';
|
||||
export { default as EventImportanceBadge } from './EventImportanceBadge';
|
||||
export { default as EventPriceDisplay } from './EventPriceDisplay';
|
||||
export { default as EventStats } from './EventStats';
|
||||
export { default as EventTimeline } from './EventTimeline';
|
||||
export { default as ImportanceBadge } from './ImportanceBadge';
|
||||
export { default as ImportanceStamp } from './ImportanceStamp';
|
||||
export { default as KeywordsCarousel } from './KeywordsCarousel';
|
||||
4
src/views/Community/components/EventDetailModal/index.ts
Normal file
4
src/views/Community/components/EventDetailModal/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
// src/views/Community/components/EventDetailModal/index.ts
|
||||
// 事件详情弹窗模块
|
||||
|
||||
export { default } from './EventDetailModal';
|
||||
@@ -27,8 +27,8 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import { AlertCircle, Clock, TrendingUp, Info, RefreshCw } from 'lucide-react';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import { logger } from '../../../utils/logger';
|
||||
import { useIndexQuote } from '../../../hooks/useIndexQuote';
|
||||
import { logger } from '@utils/logger';
|
||||
import { useIndexQuote } from '@hooks/useIndexQuote';
|
||||
|
||||
// 定义动画
|
||||
const animations = `
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// src/views/Community/components/HotEvents.js
|
||||
// src/views/Community/components/HotEvents/HotEvents.js
|
||||
import React, { useState } from 'react';
|
||||
import { Card, Badge, Tag, Empty, Carousel, Tooltip } from 'antd';
|
||||
import { ArrowUpOutlined, ArrowDownOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||
import { useDisclosure, useBreakpointValue } from '@chakra-ui/react';
|
||||
import EventDetailModal from './EventDetailModal';
|
||||
import EventDetailModal from '../EventDetailModal';
|
||||
import dayjs from 'dayjs';
|
||||
import './HotEvents.css';
|
||||
import defaultEventImage from '../../../assets/img/default-event.jpg';
|
||||
import defaultEventImage from '@assets/img/default-event.jpg';
|
||||
|
||||
// 自定义箭头组件
|
||||
const CustomArrow = ({ className, style, onClick, direction }) => {
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/HotEventsSection.js
|
||||
// src/views/Community/components/HotEvents/HotEventsSection.js
|
||||
// 热点事件区域组件
|
||||
|
||||
import React, { useState } from 'react';
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
useColorModeValue
|
||||
} from '@chakra-ui/react';
|
||||
import HotEvents from './HotEvents';
|
||||
import { PROFESSIONAL_COLORS } from '../../../constants/professionalTheme';
|
||||
import { PROFESSIONAL_COLORS } from '@constants/professionalTheme';
|
||||
|
||||
/**
|
||||
* 热点事件区域组件
|
||||
5
src/views/Community/components/HotEvents/index.js
Normal file
5
src/views/Community/components/HotEvents/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// src/views/Community/components/HotEvents/index.js
|
||||
// 热点事件模块
|
||||
|
||||
export { default as HotEvents } from './HotEvents';
|
||||
export { default as HotEventsSection } from './HotEventsSection';
|
||||
@@ -1,4 +1,4 @@
|
||||
// src/views/Community/components/CompactSearchBox.js
|
||||
// src/views/Community/components/SearchFilters/CompactSearchBox.js
|
||||
// 紧凑版搜索和筛选组件 - 优化布局
|
||||
|
||||
import React, { useState, useMemo, useEffect, useCallback, useRef } from 'react';
|
||||
5
src/views/Community/components/SearchFilters/index.js
Normal file
5
src/views/Community/components/SearchFilters/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// src/views/Community/components/SearchFilters/index.js
|
||||
// 搜索筛选组件模块
|
||||
|
||||
export { default as CompactSearchBox } from './CompactSearchBox';
|
||||
export { default as TradingTimeFilter } from './TradingTimeFilter';
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
// 导入组件
|
||||
import DynamicNewsCard from './components/DynamicNewsCard';
|
||||
import HotEventsSection from './components/HotEventsSection';
|
||||
import DynamicNewsCard from './components/DynamicNews/DynamicNewsCard';
|
||||
import HotEventsSection from './components/HotEvents/HotEventsSection';
|
||||
// ⚡ HeroPanel 懒加载:包含 ECharts (~600KB),首屏不需要立即渲染
|
||||
const HeroPanel = lazy(() => import('./components/HeroPanel'));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user