Merge branch 'feature_bugfix/251201_py_h5_ui' of https://git.valuefrontier.cn/vf/vf_react into feature_bugfix/251201_py_h5_ui
This commit is contained in:
@@ -31,6 +31,8 @@ export interface TradeDatePickerProps {
|
|||||||
showIcon?: boolean;
|
showIcon?: boolean;
|
||||||
/** 是否使用深色模式(强制覆盖 Chakra 颜色模式) */
|
/** 是否使用深色模式(强制覆盖 Chakra 颜色模式) */
|
||||||
isDarkMode?: boolean;
|
isDarkMode?: boolean;
|
||||||
|
/** 是否显示最新交易日期提示,默认 true */
|
||||||
|
showLatestTradeDateTip?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,6 +52,7 @@ const TradeDatePicker: React.FC<TradeDatePickerProps> = ({
|
|||||||
inputWidth = { base: '100%', lg: '200px' },
|
inputWidth = { base: '100%', lg: '200px' },
|
||||||
showIcon = true,
|
showIcon = true,
|
||||||
isDarkMode = false,
|
isDarkMode = false,
|
||||||
|
showLatestTradeDateTip = true,
|
||||||
}) => {
|
}) => {
|
||||||
// 颜色主题 - 支持 isDarkMode 强制覆盖
|
// 颜色主题 - 支持 isDarkMode 强制覆盖
|
||||||
const defaultLabelColor = useColorModeValue('purple.700', 'purple.300');
|
const defaultLabelColor = useColorModeValue('purple.700', 'purple.300');
|
||||||
@@ -142,21 +145,21 @@ const TradeDatePicker: React.FC<TradeDatePickerProps> = ({
|
|||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 最新交易日期提示 */}
|
{/* 最新交易日期提示 - 靠右显示,样式更低调避免误认为按钮 */}
|
||||||
{latestTradeDate && (
|
{showLatestTradeDateTip && latestTradeDate && (
|
||||||
<Tooltip label="数据库中最新的交易日期">
|
<Tooltip label="数据库中最新的交易日期">
|
||||||
<HStack
|
<HStack
|
||||||
spacing={2}
|
spacing={1.5}
|
||||||
bg={tipBg}
|
ml="auto"
|
||||||
px={3}
|
px={2}
|
||||||
py={1.5}
|
py={1}
|
||||||
borderRadius="full"
|
opacity={0.7}
|
||||||
border="1px solid"
|
_hover={{ opacity: 1 }}
|
||||||
borderColor={tipBorderColor}
|
transition="opacity 0.2s"
|
||||||
>
|
>
|
||||||
<Icon as={InfoIcon} color={tipIconColor} boxSize={3} />
|
<Icon as={InfoIcon} color={tipIconColor} boxSize={3} />
|
||||||
<Text fontSize="sm" color={tipTextColor} fontWeight="medium">
|
<Text fontSize="xs" color={tipTextColor}>
|
||||||
最新: {latestTradeDate.toLocaleDateString('zh-CN')}
|
数据更新至 {latestTradeDate.toLocaleDateString('zh-CN')}
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
@@ -336,17 +336,34 @@ export const conceptHandlers = [
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 获取最新交易日期
|
// 获取最新交易日期 - 硬编码 URL(开发环境)
|
||||||
http.get('http://111.198.58.126:16801/price/latest', async () => {
|
http.get('http://111.198.58.126:16801/price/latest', async () => {
|
||||||
await delay(200);
|
await delay(200);
|
||||||
|
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const dateStr = today.toISOString().split('T')[0].replace(/-/g, '');
|
// 使用 YYYY-MM-DD 格式,确保 new Date() 可以正确解析
|
||||||
|
const dateStr = today.toISOString().split('T')[0];
|
||||||
|
|
||||||
console.log('[Mock Concept] 获取最新交易日期:', dateStr);
|
console.log('[Mock Concept] 获取最新交易日期:', dateStr);
|
||||||
|
|
||||||
return HttpResponse.json({
|
return HttpResponse.json({
|
||||||
latest_date: dateStr,
|
latest_trade_date: dateStr,
|
||||||
|
timestamp: today.toISOString()
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
// 获取最新交易日期 - 相对路径(MSW 环境)
|
||||||
|
http.get('/concept-api/price/latest', async () => {
|
||||||
|
await delay(200);
|
||||||
|
|
||||||
|
const today = new Date();
|
||||||
|
// 使用 YYYY-MM-DD 格式,确保 new Date() 可以正确解析
|
||||||
|
const dateStr = today.toISOString().split('T')[0];
|
||||||
|
|
||||||
|
console.log('[Mock Concept] 获取最新交易日期 (概念API):', dateStr);
|
||||||
|
|
||||||
|
return HttpResponse.json({
|
||||||
|
latest_trade_date: dateStr,
|
||||||
timestamp: today.toISOString()
|
timestamp: today.toISOString()
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
@@ -393,6 +410,48 @@ export const conceptHandlers = [
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// 搜索概念(MSW 代理路径)
|
||||||
|
http.post('/concept-api/search', async ({ request }) => {
|
||||||
|
await delay(300);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const body = await request.json();
|
||||||
|
const { query = '', size = 20, page = 1, sort_by = 'change_pct' } = body;
|
||||||
|
|
||||||
|
console.log('[Mock Concept] 搜索概念 (concept-api):', { query, size, page, sort_by });
|
||||||
|
|
||||||
|
let results = generatePopularConcepts(size);
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
results = results.filter(item =>
|
||||||
|
item.concept.toLowerCase().includes(query.toLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort_by === 'change_pct') {
|
||||||
|
results.sort((a, b) => b.price_info.avg_change_pct - a.price_info.avg_change_pct);
|
||||||
|
} else if (sort_by === 'stock_count') {
|
||||||
|
results.sort((a, b) => b.stock_count - a.stock_count);
|
||||||
|
} else if (sort_by === 'hot_score') {
|
||||||
|
results.sort((a, b) => b.hot_score - a.hot_score);
|
||||||
|
}
|
||||||
|
|
||||||
|
return HttpResponse.json({
|
||||||
|
results,
|
||||||
|
total: results.length,
|
||||||
|
page,
|
||||||
|
size,
|
||||||
|
message: '搜索成功'
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[Mock Concept] 搜索失败 (concept-api):', error);
|
||||||
|
return HttpResponse.json(
|
||||||
|
{ results: [], total: 0, error: '搜索失败' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
// 获取统计数据(直接访问外部 API)
|
// 获取统计数据(直接访问外部 API)
|
||||||
http.get('http://111.198.58.126:16801/statistics', async ({ request }) => {
|
http.get('http://111.198.58.126:16801/statistics', async ({ request }) => {
|
||||||
await delay(300);
|
await delay(300);
|
||||||
@@ -592,13 +651,13 @@ export const conceptHandlers = [
|
|||||||
|
|
||||||
// ============ 层级结构 API ============
|
// ============ 层级结构 API ============
|
||||||
|
|
||||||
// 获取完整层级结构
|
// 获取完整层级结构(硬编码 URL - 开发环境)
|
||||||
http.get('/concept-api/hierarchy', async () => {
|
http.get('http://111.198.58.126:16801/hierarchy', async () => {
|
||||||
await delay(300);
|
await delay(300);
|
||||||
|
|
||||||
console.log('[Mock Concept] 获取层级结构');
|
console.log('[Mock Concept] 获取层级结构 (硬编码URL)');
|
||||||
|
|
||||||
// 模拟层级结构数据
|
// 模拟完整的层级结构数据
|
||||||
const hierarchy = [
|
const hierarchy = [
|
||||||
{
|
{
|
||||||
id: 'lv1_1',
|
id: 'lv1_1',
|
||||||
@@ -610,24 +669,24 @@ export const conceptHandlers = [
|
|||||||
name: 'AI基础设施',
|
name: 'AI基础设施',
|
||||||
concept_count: 52,
|
concept_count: 52,
|
||||||
children: [
|
children: [
|
||||||
{ id: 'lv3_1_1_1', name: 'AI算力硬件', concept_count: 16, concepts: ['AI芯片', 'GPU概念股', '服务器', 'AI一体机'] },
|
{ id: 'lv3_1_1_1', name: 'AI算力硬件', concept_count: 16, concepts: ['AI芯片', 'GPU概念股', '服务器', 'AI一体机', '算力租赁', 'NPU', '智能计算中心', '超算中心'] },
|
||||||
{ id: 'lv3_1_1_2', name: 'AI关键组件', concept_count: 24, concepts: ['HBM', 'PCB', '光通信', '存储芯片'] },
|
{ id: 'lv3_1_1_2', name: 'AI关键组件', concept_count: 24, concepts: ['HBM', 'PCB', '光通信', '存储芯片', 'CPO', '光模块', '铜连接', '高速背板'] },
|
||||||
{ id: 'lv3_1_1_3', name: 'AI配套设施', concept_count: 12, concepts: ['数据中心', '液冷', '电力设备'] }
|
{ id: 'lv3_1_1_3', name: 'AI配套设施', concept_count: 12, concepts: ['数据中心', '液冷', '电力设备', 'UPS', 'IDC服务', '边缘计算', 'AI电源'] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lv2_1_2',
|
id: 'lv2_1_2',
|
||||||
name: 'AI模型与软件',
|
name: 'AI模型与软件',
|
||||||
concept_count: 13,
|
concept_count: 18,
|
||||||
concepts: ['DeepSeek', 'KIMI', 'SORA概念', '国产大模型']
|
concepts: ['DeepSeek', 'KIMI', 'SORA概念', '国产大模型', 'ChatGPT', 'Claude', '文心一言', '通义千问', 'Gemini概念', 'AI推理']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lv2_1_3',
|
id: 'lv2_1_3',
|
||||||
name: 'AI应用',
|
name: 'AI应用',
|
||||||
concept_count: 17,
|
concept_count: 28,
|
||||||
children: [
|
children: [
|
||||||
{ id: 'lv3_1_3_1', name: '智能体与陪伴', concept_count: 11, concepts: ['AI伴侣', 'AI智能体', 'AI陪伴'] },
|
{ id: 'lv3_1_3_1', name: '智能体与陪伴', concept_count: 11, concepts: ['AI伴侣', 'AI智能体', 'AI陪伴', 'AI助手', '数字人', 'AI语音', 'AI社交'] },
|
||||||
{ id: 'lv3_1_3_2', name: '行业应用', concept_count: 6, concepts: ['AI编程', '低代码'] }
|
{ id: 'lv3_1_3_2', name: '行业应用', concept_count: 17, concepts: ['AI编程', '低代码', 'AI教育', 'AI医疗', 'AI金融', 'AI制造', 'AI安防', 'AI营销', 'AI设计'] }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -635,71 +694,320 @@ export const conceptHandlers = [
|
|||||||
{
|
{
|
||||||
id: 'lv1_2',
|
id: 'lv1_2',
|
||||||
name: '半导体',
|
name: '半导体',
|
||||||
concept_count: 45,
|
concept_count: 65,
|
||||||
children: [
|
children: [
|
||||||
{ id: 'lv2_2_1', name: '半导体设备', concept_count: 10, concepts: ['光刻机', 'EDA', '半导体设备'] },
|
{ id: 'lv2_2_1', name: '半导体设备', concept_count: 18, concepts: ['光刻机', '刻蚀设备', '薄膜沉积', '离子注入', 'CMP设备', '清洗设备'] },
|
||||||
{ id: 'lv2_2_2', name: '半导体材料', concept_count: 8, concepts: ['光刻胶', '半导体材料', '石英砂'] },
|
{ id: 'lv2_2_2', name: '半导体材料', concept_count: 15, concepts: ['光刻胶', '半导体材料', '石英砂', '硅片', '电子特气', '靶材', 'CMP抛光液'] },
|
||||||
{ id: 'lv2_2_3', name: '芯片设计与制造', concept_count: 10, concepts: ['第三代半导体', '碳化硅', '功率半导体'] },
|
{ id: 'lv2_2_3', name: '芯片设计与制造', concept_count: 22, concepts: ['CPU', 'GPU', 'FPGA', 'ASIC', 'MCU', 'DSP', 'NPU芯片', '功率半导体', '碳化硅'] },
|
||||||
{ id: 'lv2_2_4', name: '先进封装', concept_count: 5, concepts: ['玻璃基板', '半导体封测'] }
|
{ id: 'lv2_2_4', name: '先进封装', concept_count: 10, concepts: ['玻璃基板', '半导体封测', 'Chiplet', 'CoWoS', 'SiP', '3D封装'] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lv1_3',
|
id: 'lv1_3',
|
||||||
name: '机器人',
|
name: '机器人',
|
||||||
concept_count: 42,
|
concept_count: 52,
|
||||||
children: [
|
children: [
|
||||||
{ id: 'lv2_3_1', name: '人形机器人整机', concept_count: 20, concepts: ['特斯拉机器人', '人形机器人', '智元机器人'] },
|
{ id: 'lv2_3_1', name: '人形机器人整机', concept_count: 20, concepts: ['特斯拉机器人', '人形机器人', '智元机器人', '优必选', '小米机器人', '华为机器人'] },
|
||||||
{ id: 'lv2_3_2', name: '机器人核心零部件', concept_count: 12, concepts: ['滚柱丝杆', '电子皮肤', '轴向磁通电机'] },
|
{ id: 'lv2_3_2', name: '机器人核心零部件', concept_count: 20, concepts: ['滚柱丝杆', '电子皮肤', '轴向磁通电机', '谐波减速器', '行星减速器', '伺服电机', '六维力传感器', '灵巧手'] },
|
||||||
{ id: 'lv2_3_3', name: '其他类型机器人', concept_count: 10, concepts: ['工业机器人', '机器狗', '外骨骼机器人'] }
|
{ id: 'lv2_3_3', name: '其他类型机器人', concept_count: 12, concepts: ['工业机器人', '机器狗', '外骨骼机器人', '协作机器人', '手术机器人', '服务机器人'] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lv1_4',
|
id: 'lv1_4',
|
||||||
name: '消费电子',
|
name: '消费电子',
|
||||||
concept_count: 38,
|
concept_count: 48,
|
||||||
children: [
|
children: [
|
||||||
{ id: 'lv2_4_1', name: '智能终端', concept_count: 8, concepts: ['AI PC', 'AI手机'] },
|
{ id: 'lv2_4_1', name: '智能终端', concept_count: 12, concepts: ['AI PC', 'AI手机', '折叠屏', '卫星通信手机', '智能手表', '智能耳机'] },
|
||||||
{ id: 'lv2_4_2', name: 'XR与空间计算', concept_count: 14, concepts: ['AR眼镜', 'MR', '智能眼镜'] },
|
{ id: 'lv2_4_2', name: 'XR与空间计算', concept_count: 18, concepts: ['AR眼镜', 'MR', '智能眼镜', 'VR头显', 'Apple Vision Pro概念', 'Meta Quest概念'] },
|
||||||
{ id: 'lv2_4_3', name: '华为产业链', concept_count: 16, concepts: ['华为Mate70', '鸿蒙', '华为昇腾'] }
|
{ id: 'lv2_4_3', name: '华为产业链', concept_count: 18, concepts: ['华为Mate70', '鸿蒙', '华为昇腾', '华为汽车', '华为海思', '华为云', '麒麟芯片'] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lv1_5',
|
id: 'lv1_5',
|
||||||
name: '智能驾驶与汽车',
|
name: '智能驾驶与汽车',
|
||||||
concept_count: 35,
|
concept_count: 45,
|
||||||
children: [
|
children: [
|
||||||
{ id: 'lv2_5_1', name: '自动驾驶解决方案', concept_count: 12, concepts: ['Robotaxi', '无人驾驶', '特斯拉FSD'] },
|
{ id: 'lv2_5_1', name: '自动驾驶解决方案', concept_count: 18, concepts: ['Robotaxi', '无人驾驶', '特斯拉FSD', 'L4自动驾驶', '萝卜快跑', '百度Apollo'] },
|
||||||
{ id: 'lv2_5_2', name: '智能汽车产业链', concept_count: 15, concepts: ['比亚迪产业链', '小米汽车产业链'] },
|
{ id: 'lv2_5_2', name: '智能汽车产业链', concept_count: 18, concepts: ['比亚迪产业链', '小米汽车产业链', '特斯拉产业链', '新能源汽车', '智能座舱', '汽车电子'] },
|
||||||
{ id: 'lv2_5_3', name: '车路协同', concept_count: 8, concepts: ['车路云一体化', '车路协同'] }
|
{ id: 'lv2_5_3', name: '车路协同', concept_count: 9, concepts: ['车路云一体化', '车路协同', 'V2X', '智能交通', '高精地图', '车联网'] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lv1_6',
|
id: 'lv1_6',
|
||||||
name: '新能源与电力',
|
name: '新能源与电力',
|
||||||
concept_count: 52,
|
concept_count: 62,
|
||||||
children: [
|
children: [
|
||||||
{ id: 'lv2_6_1', name: '新型电池技术', concept_count: 18, concepts: ['固态电池', '钠离子电池', '硅基负极'] },
|
{ id: 'lv2_6_1', name: '新型电池技术', concept_count: 22, concepts: ['固态电池', '钠离子电池', '锂电池', '磷酸铁锂', '三元锂电池', '硅基负极', '电解液'] },
|
||||||
{ id: 'lv2_6_2', name: '电力设备与电网', concept_count: 20, concepts: ['电力', '变压器出海', '燃料电池'] },
|
{ id: 'lv2_6_2', name: '电力设备与电网', concept_count: 24, concepts: ['电力', '变压器出海', '特高压', '智能电网', '储能', '充电桩', '虚拟电厂'] },
|
||||||
{ id: 'lv2_6_3', name: '清洁能源', concept_count: 14, concepts: ['光伏', '核电', '可控核聚变'] }
|
{ id: 'lv2_6_3', name: '清洁能源', concept_count: 16, concepts: ['光伏', '核电', '可控核聚变', '风电', '海上风电', '氢能源', '绿电', '碳中和'] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lv1_7',
|
id: 'lv1_7',
|
||||||
name: '空天经济',
|
name: '空天经济',
|
||||||
concept_count: 28,
|
concept_count: 38,
|
||||||
children: [
|
children: [
|
||||||
{ id: 'lv2_7_1', name: '低空经济', concept_count: 14, concepts: ['低空经济', 'eVTOL', '飞行汽车'] },
|
{ id: 'lv2_7_1', name: '低空经济', concept_count: 20, concepts: ['低空经济', 'eVTOL', '飞行汽车', '无人机', '电动垂直起降', '载人飞行器', '物流无人机'] },
|
||||||
{ id: 'lv2_7_2', name: '商业航天', concept_count: 14, concepts: ['卫星互联网', '商业航天', '北斗导航'] }
|
{ id: 'lv2_7_2', name: '商业航天', concept_count: 18, concepts: ['卫星互联网', '商业航天', '北斗导航', '星链概念', '火箭发射', '卫星制造', '遥感卫星'] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'lv1_8',
|
id: 'lv1_8',
|
||||||
name: '国防军工',
|
name: '国防军工',
|
||||||
|
concept_count: 35,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv2_8_1', name: '无人作战与信息化', concept_count: 14, concepts: ['AI军工', '无人机蜂群', '军工信息化', '无人作战', '军用无人机', '电子战'] },
|
||||||
|
{ id: 'lv2_8_2', name: '海军装备', concept_count: 12, concepts: ['国产航母', '电磁弹射', '舰艇', '潜艇', '海军武器', '舰载机'] },
|
||||||
|
{ id: 'lv2_8_3', name: '军贸出海', concept_count: 9, concepts: ['军贸', '巴黎航展', '武器出口', '国际军贸', '军工出海'] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return HttpResponse.json({
|
||||||
|
hierarchy,
|
||||||
|
total_lv1: hierarchy.length,
|
||||||
|
total_concepts: hierarchy.reduce((acc, h) => acc + h.concept_count, 0)
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
// 获取完整层级结构(更丰富的 mock 数据)
|
||||||
|
http.get('/concept-api/hierarchy', async () => {
|
||||||
|
await delay(300);
|
||||||
|
|
||||||
|
console.log('[Mock Concept] 获取层级结构');
|
||||||
|
|
||||||
|
// 模拟完整的层级结构数据
|
||||||
|
const hierarchy = [
|
||||||
|
{
|
||||||
|
id: 'lv1_1',
|
||||||
|
name: '人工智能',
|
||||||
|
concept_count: 98,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 'lv2_1_1',
|
||||||
|
name: 'AI基础设施',
|
||||||
|
concept_count: 52,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv3_1_1_1', name: 'AI算力硬件', concept_count: 16, concepts: ['AI芯片', 'GPU概念股', '服务器', 'AI一体机', '算力租赁', 'NPU', '智能计算中心', '超算中心'] },
|
||||||
|
{ id: 'lv3_1_1_2', name: 'AI关键组件', concept_count: 24, concepts: ['HBM', 'PCB', '光通信', '存储芯片', 'CPO', '光模块', '铜连接', '高速背板'] },
|
||||||
|
{ id: 'lv3_1_1_3', name: 'AI配套设施', concept_count: 12, concepts: ['数据中心', '液冷', '电力设备', 'UPS', 'IDC服务', '边缘计算', 'AI电源'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv2_1_2',
|
||||||
|
name: 'AI模型与软件',
|
||||||
|
concept_count: 18,
|
||||||
|
concepts: ['DeepSeek', 'KIMI', 'SORA概念', '国产大模型', 'ChatGPT', 'Claude', '文心一言', '通义千问', 'Gemini概念', 'AI推理']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv2_1_3',
|
||||||
|
name: 'AI应用',
|
||||||
|
concept_count: 28,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv3_1_3_1', name: '智能体与陪伴', concept_count: 11, concepts: ['AI伴侣', 'AI智能体', 'AI陪伴', 'AI助手', '数字人', 'AI语音', 'AI社交'] },
|
||||||
|
{ id: 'lv3_1_3_2', name: '行业应用', concept_count: 17, concepts: ['AI编程', '低代码', 'AI教育', 'AI医疗', 'AI金融', 'AI制造', 'AI安防', 'AI营销', 'AI设计'] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_2',
|
||||||
|
name: '半导体',
|
||||||
|
concept_count: 65,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 'lv2_2_1',
|
||||||
|
name: '半导体设备',
|
||||||
|
concept_count: 18,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv3_2_1_1', name: '前道设备', concept_count: 10, concepts: ['光刻机', '刻蚀设备', '薄膜沉积', '离子注入', 'CMP设备', '清洗设备'] },
|
||||||
|
{ id: 'lv3_2_1_2', name: '后道设备', concept_count: 8, concepts: ['划片机', '键合设备', '测试设备', '封装设备', 'AOI检测'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv2_2_2',
|
||||||
|
name: '半导体材料',
|
||||||
|
concept_count: 15,
|
||||||
|
concepts: ['光刻胶', '半导体材料', '石英砂', '硅片', '电子特气', '靶材', 'CMP抛光液', '湿电子化学品', '掩模版']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv2_2_3',
|
||||||
|
name: '芯片设计与制造',
|
||||||
|
concept_count: 22,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv3_2_3_1', name: '数字芯片', concept_count: 12, concepts: ['CPU', 'GPU', 'FPGA', 'ASIC', 'MCU', 'DSP', 'NPU芯片'] },
|
||||||
|
{ id: 'lv3_2_3_2', name: '模拟芯片', concept_count: 10, concepts: ['电源管理芯片', '驱动芯片', '传感器芯片', '射频芯片', '功率半导体', '碳化硅', '氮化镓'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ id: 'lv2_2_4', name: '先进封装', concept_count: 10, concepts: ['玻璃基板', '半导体封测', 'Chiplet', 'CoWoS', 'SiP', '3D封装', '扇出封装'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_3',
|
||||||
|
name: '机器人',
|
||||||
|
concept_count: 52,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 'lv2_3_1',
|
||||||
|
name: '人形机器人整机',
|
||||||
|
concept_count: 20,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv3_3_1_1', name: '整机厂商', concept_count: 12, concepts: ['特斯拉机器人', '人形机器人', '智元机器人', '优必选', '小米机器人', '华为机器人', '波士顿动力概念'] },
|
||||||
|
{ id: 'lv3_3_1_2', name: '解决方案', concept_count: 8, concepts: ['具身智能', '机器人操作系统', '多模态AI', '机器人仿真'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv2_3_2',
|
||||||
|
name: '机器人核心零部件',
|
||||||
|
concept_count: 20,
|
||||||
|
concepts: ['滚柱丝杆', '电子皮肤', '轴向磁通电机', '谐波减速器', '行星减速器', '伺服电机', '编码器', '力矩传感器', '六维力传感器', '灵巧手', '机器人关节']
|
||||||
|
},
|
||||||
|
{ id: 'lv2_3_3', name: '其他类型机器人', concept_count: 12, concepts: ['工业机器人', '机器狗', '外骨骼机器人', '协作机器人', '手术机器人', '服务机器人', '物流机器人', '农业机器人'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_4',
|
||||||
|
name: '消费电子',
|
||||||
|
concept_count: 48,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv2_4_1', name: '智能终端', concept_count: 12, concepts: ['AI PC', 'AI手机', '折叠屏', '卫星通信手机', '智能手表', '智能耳机', '智能音箱', '平板电脑'] },
|
||||||
|
{
|
||||||
|
id: 'lv2_4_2',
|
||||||
|
name: 'XR与空间计算',
|
||||||
|
concept_count: 18,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv3_4_2_1', name: 'XR硬件', concept_count: 10, concepts: ['AR眼镜', 'MR', '智能眼镜', 'VR头显', 'Apple Vision Pro概念', 'Meta Quest概念'] },
|
||||||
|
{ id: 'lv3_4_2_2', name: 'XR软件与内容', concept_count: 8, concepts: ['XR内容', '空间计算', '3D引擎', 'XR社交', 'XR游戏'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ id: 'lv2_4_3', name: '华为产业链', concept_count: 18, concepts: ['华为Mate70', '鸿蒙', '华为昇腾', '华为汽车', '华为海思', '华为云', '华为手机', '华为概念', '麒麟芯片'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_5',
|
||||||
|
name: '智能驾驶与汽车',
|
||||||
|
concept_count: 45,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 'lv2_5_1',
|
||||||
|
name: '自动驾驶解决方案',
|
||||||
|
concept_count: 18,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv3_5_1_1', name: '整体方案', concept_count: 10, concepts: ['Robotaxi', '无人驾驶', '特斯拉FSD', 'L4自动驾驶', '萝卜快跑', '百度Apollo'] },
|
||||||
|
{ id: 'lv3_5_1_2', name: '核心部件', concept_count: 8, concepts: ['自动驾驶芯片', '激光雷达', '毫米波雷达', '车载摄像头', '域控制器'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ id: 'lv2_5_2', name: '智能汽车产业链', concept_count: 18, concepts: ['比亚迪产业链', '小米汽车产业链', '特斯拉产业链', '理想产业链', '蔚来产业链', '小鹏产业链', '新能源汽车', '智能座舱', '汽车电子'] },
|
||||||
|
{ id: 'lv2_5_3', name: '车路协同', concept_count: 9, concepts: ['车路云一体化', '车路协同', 'V2X', '智能交通', '高精地图', '车联网'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_6',
|
||||||
|
name: '新能源与电力',
|
||||||
|
concept_count: 62,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 'lv2_6_1',
|
||||||
|
name: '新型电池技术',
|
||||||
|
concept_count: 22,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv3_6_1_1', name: '电池类型', concept_count: 12, concepts: ['固态电池', '钠离子电池', '锂电池', '磷酸铁锂', '三元锂电池', '刀片电池', '4680电池'] },
|
||||||
|
{ id: 'lv3_6_1_2', name: '电池材料', concept_count: 10, concepts: ['硅基负极', '正极材料', '负极材料', '电解液', '隔膜', '锂矿', '钠矿'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ id: 'lv2_6_2', name: '电力设备与电网', concept_count: 24, concepts: ['电力', '变压器出海', '燃料电池', '特高压', '智能电网', '配电网', '虚拟电厂', '储能', '抽水蓄能', '电力物联网', '充电桩'] },
|
||||||
|
{ id: 'lv2_6_3', name: '清洁能源', concept_count: 16, concepts: ['光伏', '核电', '可控核聚变', '风电', '海上风电', '氢能源', '绿电', '碳中和', 'CCER'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_7',
|
||||||
|
name: '空天经济',
|
||||||
|
concept_count: 38,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 'lv2_7_1',
|
||||||
|
name: '低空经济',
|
||||||
|
concept_count: 20,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv3_7_1_1', name: '飞行器', concept_count: 12, concepts: ['低空经济', 'eVTOL', '飞行汽车', '无人机', '电动垂直起降', '载人飞行器', '物流无人机'] },
|
||||||
|
{ id: 'lv3_7_1_2', name: '配套设施', concept_count: 8, concepts: ['低空空域', '通用航空', '无人机反制', '低空雷达', '飞行管控'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ id: 'lv2_7_2', name: '商业航天', concept_count: 18, concepts: ['卫星互联网', '商业航天', '北斗导航', '星链概念', '火箭发射', '卫星制造', '遥感卫星', '通信卫星', '空间站', '太空旅游'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_8',
|
||||||
|
name: '国防军工',
|
||||||
|
concept_count: 35,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv2_8_1', name: '无人作战与信息化', concept_count: 14, concepts: ['AI军工', '无人机蜂群', '军工信息化', '无人作战', '军用无人机', '军用机器人', '电子战', '军用芯片'] },
|
||||||
|
{ id: 'lv2_8_2', name: '海军装备', concept_count: 12, concepts: ['国产航母', '电磁弹射', '舰艇', '潜艇', '海军武器', '舰载机', '军船', '海洋装备'] },
|
||||||
|
{ id: 'lv2_8_3', name: '军贸出海', concept_count: 9, concepts: ['军贸', '巴黎航展', '武器出口', '国际军贸', '军工出海', '航展概念'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_9',
|
||||||
|
name: '政策与主题',
|
||||||
|
concept_count: 42,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv2_9_1', name: '国家战略', concept_count: 22, concepts: ['一带一路', '国产替代', '自主可控', '信创', '数字经济', '数据要素', '东数西算', '新基建', '乡村振兴', '共同富裕', '双循环'] },
|
||||||
|
{ id: 'lv2_9_2', name: '区域发展', concept_count: 20, concepts: ['粤港澳大湾区', '长三角一体化', '京津冀协同', '成渝经济圈', '海南自贸港', '雄安新区', '西部大开发', '中部崛起'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_10',
|
||||||
|
name: '周期与材料',
|
||||||
|
concept_count: 35,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv2_10_1', name: '有色金属', concept_count: 18, concepts: ['黄金', '白银', '铜', '铝', '稀土', '锂', '钴', '镍', '锡', '锌', '小金属'] },
|
||||||
|
{ id: 'lv2_10_2', name: '化工材料', concept_count: 17, concepts: ['氟化工', '磷化工', '钛白粉', '碳纤维', '石墨烯', '复合材料', '新材料', '高分子材料'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_11',
|
||||||
|
name: '大消费',
|
||||||
|
concept_count: 45,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv2_11_1', name: '食品饮料', concept_count: 22, concepts: ['白酒', '啤酒', '乳业', '预制菜', '零食', '调味品', '饮料', '食品加工', '餐饮', '咖啡茶饮'] },
|
||||||
|
{ id: 'lv2_11_2', name: '消费服务', concept_count: 23, concepts: ['免税', '旅游', '酒店', '航空', '电商', '直播带货', '新零售', '社区团购', '跨境电商', '本地生活'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_12',
|
||||||
|
name: '数字经济与金融科技',
|
||||||
|
concept_count: 38,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv2_12_1', name: '金融科技', concept_count: 20, concepts: ['数字货币', '数字人民币', '区块链', 'Web3', '金融IT', '征信', '保险科技', '券商金融科技'] },
|
||||||
|
{ id: 'lv2_12_2', name: '数字化转型', concept_count: 18, concepts: ['云计算', '大数据', '物联网', '5G', '6G', '数字孪生', '元宇宙', '工业互联网', 'SaaS'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_13',
|
||||||
|
name: '医药健康',
|
||||||
|
concept_count: 55,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv2_13_1', name: '创新药', concept_count: 25, concepts: ['创新药', 'CXO', 'ADC', '减肥药', 'GLP-1', 'CAR-T', '细胞治疗', '基因治疗', 'mRNA', 'PROTAC'] },
|
||||||
|
{ id: 'lv2_13_2', name: '医疗器械', concept_count: 18, concepts: ['医疗器械', '高值耗材', '医疗影像', '手术机器人', '康复器械', 'IVD', '医美设备', '眼科器械'] },
|
||||||
|
{ id: 'lv2_13_3', name: '中医药', concept_count: 12, concepts: ['中药', '中药创新药', '中医诊疗', '中药配方颗粒', '道地药材'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_14',
|
||||||
|
name: '前沿科技',
|
||||||
|
concept_count: 28,
|
||||||
|
children: [
|
||||||
|
{ id: 'lv2_14_1', name: '量子科技', concept_count: 14, concepts: ['量子计算', '量子通信', '量子芯片', '量子加密', '量子传感', '量子软件'] },
|
||||||
|
{ id: 'lv2_14_2', name: '脑机接口', concept_count: 14, concepts: ['脑机接口', 'Neuralink概念', '神经科技', '脑科学', '人脑芯片', '神经调控'] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'lv1_15',
|
||||||
|
name: '全球宏观与贸易',
|
||||||
concept_count: 25,
|
concept_count: 25,
|
||||||
children: [
|
children: [
|
||||||
{ id: 'lv2_8_1', name: '无人作战与信息化', concept_count: 10, concepts: ['AI军工', '无人机蜂群', '军工信息化'] },
|
{ id: 'lv2_15_1', name: '国际贸易', concept_count: 15, concepts: ['跨境电商', '出口', '贸易摩擦', '人民币国际化', '中美贸易', '中欧贸易', '东盟贸易'] },
|
||||||
{ id: 'lv2_8_2', name: '海军装备', concept_count: 8, concepts: ['国产航母', '电磁弹射'] },
|
{ id: 'lv2_15_2', name: '宏观主题', concept_count: 10, concepts: ['美联储加息', '美债', '汇率', '通胀', '衰退预期', '地缘政治'] }
|
||||||
{ id: 'lv2_8_3', name: '军贸出海', concept_count: 7, concepts: ['军贸', '巴黎航展'] }
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -737,7 +1045,98 @@ export const conceptHandlers = [
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 获取层级涨跌幅数据(实时价格)
|
// 获取层级涨跌幅数据(硬编码 URL - 开发环境)
|
||||||
|
http.get('http://111.198.58.126:16801/hierarchy/price', async ({ request }) => {
|
||||||
|
await delay(200);
|
||||||
|
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const tradeDate = url.searchParams.get('trade_date');
|
||||||
|
|
||||||
|
console.log('[Mock Concept] 获取层级涨跌幅数据 (硬编码URL):', { tradeDate });
|
||||||
|
|
||||||
|
// 模拟 lv1 层级涨跌幅数据
|
||||||
|
const lv1_concepts = [
|
||||||
|
{ concept_name: '人工智能', avg_change_pct: 3.56, stock_count: 245 },
|
||||||
|
{ concept_name: '半导体', avg_change_pct: 2.12, stock_count: 156 },
|
||||||
|
{ concept_name: '机器人', avg_change_pct: 4.28, stock_count: 128 },
|
||||||
|
{ concept_name: '消费电子', avg_change_pct: 1.45, stock_count: 98 },
|
||||||
|
{ concept_name: '智能驾驶与汽车', avg_change_pct: 2.89, stock_count: 112 },
|
||||||
|
{ concept_name: '新能源与电力', avg_change_pct: -0.56, stock_count: 186 },
|
||||||
|
{ concept_name: '空天经济', avg_change_pct: 3.12, stock_count: 76 },
|
||||||
|
{ concept_name: '国防军工', avg_change_pct: 1.78, stock_count: 89 }
|
||||||
|
];
|
||||||
|
|
||||||
|
// 模拟 lv2 层级涨跌幅数据
|
||||||
|
const lv2_concepts = [
|
||||||
|
{ concept_name: 'AI基础设施', avg_change_pct: 4.12, stock_count: 85 },
|
||||||
|
{ concept_name: 'AI模型与软件', avg_change_pct: 5.67, stock_count: 42 },
|
||||||
|
{ concept_name: 'AI应用', avg_change_pct: 2.34, stock_count: 65 },
|
||||||
|
{ concept_name: '半导体设备', avg_change_pct: 3.21, stock_count: 38 },
|
||||||
|
{ concept_name: '半导体材料', avg_change_pct: 1.89, stock_count: 32 },
|
||||||
|
{ concept_name: '芯片设计与制造', avg_change_pct: 2.45, stock_count: 56 },
|
||||||
|
{ concept_name: '先进封装', avg_change_pct: 1.23, stock_count: 22 },
|
||||||
|
{ concept_name: '人形机器人整机', avg_change_pct: 5.89, stock_count: 45 },
|
||||||
|
{ concept_name: '机器人核心零部件', avg_change_pct: 3.45, stock_count: 52 },
|
||||||
|
{ concept_name: '其他类型机器人', avg_change_pct: 2.12, stock_count: 31 },
|
||||||
|
{ concept_name: '智能终端', avg_change_pct: 1.78, stock_count: 28 },
|
||||||
|
{ concept_name: 'XR与空间计算', avg_change_pct: 2.56, stock_count: 36 },
|
||||||
|
{ concept_name: '华为产业链', avg_change_pct: 0.89, stock_count: 48 },
|
||||||
|
{ concept_name: '自动驾驶解决方案', avg_change_pct: 4.23, stock_count: 35 },
|
||||||
|
{ concept_name: '智能汽车产业链', avg_change_pct: 2.45, stock_count: 52 },
|
||||||
|
{ concept_name: '车路协同', avg_change_pct: 1.56, stock_count: 25 },
|
||||||
|
{ concept_name: '新型电池技术', avg_change_pct: 0.67, stock_count: 62 },
|
||||||
|
{ concept_name: '电力设备与电网', avg_change_pct: -1.23, stock_count: 78 },
|
||||||
|
{ concept_name: '清洁能源', avg_change_pct: -0.45, stock_count: 46 },
|
||||||
|
{ concept_name: '低空经济', avg_change_pct: 4.56, stock_count: 42 },
|
||||||
|
{ concept_name: '商业航天', avg_change_pct: 1.89, stock_count: 34 },
|
||||||
|
{ concept_name: '无人作战与信息化', avg_change_pct: 2.34, stock_count: 28 },
|
||||||
|
{ concept_name: '海军装备', avg_change_pct: 1.45, stock_count: 32 },
|
||||||
|
{ concept_name: '军贸出海', avg_change_pct: 1.12, stock_count: 18 }
|
||||||
|
];
|
||||||
|
|
||||||
|
// 模拟 lv3 层级涨跌幅数据
|
||||||
|
const lv3_concepts = [
|
||||||
|
{ concept_name: 'AI算力硬件', avg_change_pct: 5.23, stock_count: 32 },
|
||||||
|
{ concept_name: 'AI关键组件', avg_change_pct: 3.89, stock_count: 45 },
|
||||||
|
{ concept_name: 'AI配套设施', avg_change_pct: 2.67, stock_count: 28 },
|
||||||
|
{ concept_name: '智能体与陪伴', avg_change_pct: 3.12, stock_count: 24 },
|
||||||
|
{ concept_name: '行业应用', avg_change_pct: 1.56, stock_count: 18 }
|
||||||
|
];
|
||||||
|
|
||||||
|
// 模拟叶子概念涨跌幅数据
|
||||||
|
const leaf_concepts = [
|
||||||
|
{ concept_name: 'AI芯片', avg_change_pct: 6.78, stock_count: 12, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI算力硬件' },
|
||||||
|
{ concept_name: 'GPU概念股', avg_change_pct: 5.45, stock_count: 8, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI算力硬件' },
|
||||||
|
{ concept_name: 'HBM', avg_change_pct: 8.12, stock_count: 10, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI关键组件' },
|
||||||
|
{ concept_name: 'CPO', avg_change_pct: 9.34, stock_count: 8, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI关键组件' },
|
||||||
|
{ concept_name: '液冷', avg_change_pct: 6.78, stock_count: 12, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI配套设施' },
|
||||||
|
{ concept_name: 'DeepSeek', avg_change_pct: 12.34, stock_count: 15, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: 'KIMI', avg_change_pct: 8.56, stock_count: 12, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: '特斯拉机器人', avg_change_pct: 8.45, stock_count: 18, lv1: '机器人', lv2: '人形机器人整机' },
|
||||||
|
{ concept_name: '人形机器人', avg_change_pct: 7.23, stock_count: 25, lv1: '机器人', lv2: '人形机器人整机' },
|
||||||
|
{ concept_name: '低空经济', avg_change_pct: 6.78, stock_count: 22, lv1: '空天经济', lv2: '低空经济' },
|
||||||
|
{ concept_name: 'eVTOL', avg_change_pct: 7.89, stock_count: 15, lv1: '空天经济', lv2: '低空经济' },
|
||||||
|
{ concept_name: '光刻机', avg_change_pct: 5.67, stock_count: 10, lv1: '半导体', lv2: '半导体设备' },
|
||||||
|
{ concept_name: 'Chiplet', avg_change_pct: 4.56, stock_count: 14, lv1: '半导体', lv2: '先进封装' },
|
||||||
|
{ concept_name: '固态电池', avg_change_pct: 3.45, stock_count: 18, lv1: '新能源与电力', lv2: '新型电池技术' },
|
||||||
|
{ concept_name: 'Robotaxi', avg_change_pct: 5.67, stock_count: 14, lv1: '智能驾驶与汽车', lv2: '自动驾驶解决方案' },
|
||||||
|
{ concept_name: 'AR眼镜', avg_change_pct: 4.56, stock_count: 16, lv1: '消费电子', lv2: 'XR与空间计算' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const today = tradeDate ? new Date(tradeDate) : new Date();
|
||||||
|
const tradeDateStr = today.toISOString().split('T')[0];
|
||||||
|
|
||||||
|
return HttpResponse.json({
|
||||||
|
trade_date: tradeDateStr,
|
||||||
|
lv1_concepts,
|
||||||
|
lv2_concepts,
|
||||||
|
lv3_concepts,
|
||||||
|
leaf_concepts,
|
||||||
|
update_time: new Date().toISOString()
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
// 获取层级涨跌幅数据(实时价格)- 完整版本,包含 leaf_concepts
|
||||||
http.get('/concept-api/hierarchy/price', async ({ request }) => {
|
http.get('/concept-api/hierarchy/price', async ({ request }) => {
|
||||||
await delay(200);
|
await delay(200);
|
||||||
|
|
||||||
@@ -755,7 +1154,14 @@ export const conceptHandlers = [
|
|||||||
{ concept_name: '智能驾驶与汽车', avg_change_pct: 2.89, stock_count: 112 },
|
{ concept_name: '智能驾驶与汽车', avg_change_pct: 2.89, stock_count: 112 },
|
||||||
{ concept_name: '新能源与电力', avg_change_pct: -0.56, stock_count: 186 },
|
{ concept_name: '新能源与电力', avg_change_pct: -0.56, stock_count: 186 },
|
||||||
{ concept_name: '空天经济', avg_change_pct: 3.12, stock_count: 76 },
|
{ concept_name: '空天经济', avg_change_pct: 3.12, stock_count: 76 },
|
||||||
{ concept_name: '国防军工', avg_change_pct: 1.78, stock_count: 89 }
|
{ concept_name: '国防军工', avg_change_pct: 1.78, stock_count: 89 },
|
||||||
|
{ concept_name: '政策与主题', avg_change_pct: 1.23, stock_count: 95 },
|
||||||
|
{ concept_name: '周期与材料', avg_change_pct: -0.89, stock_count: 82 },
|
||||||
|
{ concept_name: '大消费', avg_change_pct: 0.56, stock_count: 115 },
|
||||||
|
{ concept_name: '数字经济与金融科技', avg_change_pct: 2.34, stock_count: 88 },
|
||||||
|
{ concept_name: '医药健康', avg_change_pct: -1.23, stock_count: 142 },
|
||||||
|
{ concept_name: '前沿科技', avg_change_pct: 4.67, stock_count: 56 },
|
||||||
|
{ concept_name: '全球宏观与贸易', avg_change_pct: 0.12, stock_count: 48 }
|
||||||
];
|
];
|
||||||
|
|
||||||
// 模拟 lv2 层级涨跌幅数据
|
// 模拟 lv2 层级涨跌幅数据
|
||||||
@@ -791,7 +1197,29 @@ export const conceptHandlers = [
|
|||||||
// 国防军工下的 lv2
|
// 国防军工下的 lv2
|
||||||
{ concept_name: '无人作战与信息化', avg_change_pct: 2.34, stock_count: 28 },
|
{ concept_name: '无人作战与信息化', avg_change_pct: 2.34, stock_count: 28 },
|
||||||
{ concept_name: '海军装备', avg_change_pct: 1.45, stock_count: 32 },
|
{ concept_name: '海军装备', avg_change_pct: 1.45, stock_count: 32 },
|
||||||
{ concept_name: '军贸出海', avg_change_pct: 1.12, stock_count: 18 }
|
{ concept_name: '军贸出海', avg_change_pct: 1.12, stock_count: 18 },
|
||||||
|
// 政策与主题下的 lv2
|
||||||
|
{ concept_name: '国家战略', avg_change_pct: 1.56, stock_count: 52 },
|
||||||
|
{ concept_name: '区域发展', avg_change_pct: 0.89, stock_count: 43 },
|
||||||
|
// 周期与材料下的 lv2
|
||||||
|
{ concept_name: '有色金属', avg_change_pct: -1.23, stock_count: 45 },
|
||||||
|
{ concept_name: '化工材料', avg_change_pct: -0.56, stock_count: 37 },
|
||||||
|
// 大消费下的 lv2
|
||||||
|
{ concept_name: '食品饮料', avg_change_pct: 0.78, stock_count: 58 },
|
||||||
|
{ concept_name: '消费服务', avg_change_pct: 0.34, stock_count: 57 },
|
||||||
|
// 数字经济与金融科技下的 lv2
|
||||||
|
{ concept_name: '金融科技', avg_change_pct: 2.89, stock_count: 46 },
|
||||||
|
{ concept_name: '数字化转型', avg_change_pct: 1.78, stock_count: 42 },
|
||||||
|
// 医药健康下的 lv2
|
||||||
|
{ concept_name: '创新药', avg_change_pct: -1.56, stock_count: 65 },
|
||||||
|
{ concept_name: '医疗器械', avg_change_pct: -0.89, stock_count: 48 },
|
||||||
|
{ concept_name: '中医药', avg_change_pct: -1.12, stock_count: 29 },
|
||||||
|
// 前沿科技下的 lv2
|
||||||
|
{ concept_name: '量子科技', avg_change_pct: 5.23, stock_count: 28 },
|
||||||
|
{ concept_name: '脑机接口', avg_change_pct: 4.12, stock_count: 28 },
|
||||||
|
// 全球宏观与贸易下的 lv2
|
||||||
|
{ concept_name: '国际贸易', avg_change_pct: 0.23, stock_count: 32 },
|
||||||
|
{ concept_name: '宏观主题', avg_change_pct: -0.01, stock_count: 16 }
|
||||||
];
|
];
|
||||||
|
|
||||||
// 模拟 lv3 层级涨跌幅数据
|
// 模拟 lv3 层级涨跌幅数据
|
||||||
@@ -802,7 +1230,219 @@ export const conceptHandlers = [
|
|||||||
{ concept_name: 'AI配套设施', avg_change_pct: 2.67, stock_count: 28 },
|
{ concept_name: 'AI配套设施', avg_change_pct: 2.67, stock_count: 28 },
|
||||||
// AI应用下的 lv3
|
// AI应用下的 lv3
|
||||||
{ concept_name: '智能体与陪伴', avg_change_pct: 3.12, stock_count: 24 },
|
{ concept_name: '智能体与陪伴', avg_change_pct: 3.12, stock_count: 24 },
|
||||||
{ concept_name: '行业应用', avg_change_pct: 1.56, stock_count: 18 }
|
{ concept_name: '行业应用', avg_change_pct: 1.56, stock_count: 18 },
|
||||||
|
// 半导体设备下的 lv3
|
||||||
|
{ concept_name: '前道设备', avg_change_pct: 3.89, stock_count: 22 },
|
||||||
|
{ concept_name: '后道设备', avg_change_pct: 2.45, stock_count: 16 },
|
||||||
|
// 芯片设计与制造下的 lv3
|
||||||
|
{ concept_name: '数字芯片', avg_change_pct: 2.78, stock_count: 32 },
|
||||||
|
{ concept_name: '模拟芯片', avg_change_pct: 2.12, stock_count: 24 },
|
||||||
|
// 人形机器人下的 lv3
|
||||||
|
{ concept_name: '整机厂商', avg_change_pct: 6.78, stock_count: 25 },
|
||||||
|
{ concept_name: '解决方案', avg_change_pct: 4.56, stock_count: 20 },
|
||||||
|
// XR与空间计算下的 lv3
|
||||||
|
{ concept_name: 'XR硬件', avg_change_pct: 3.12, stock_count: 22 },
|
||||||
|
{ concept_name: 'XR软件与内容', avg_change_pct: 1.89, stock_count: 14 },
|
||||||
|
// 自动驾驶解决方案下的 lv3
|
||||||
|
{ concept_name: '整体方案', avg_change_pct: 5.12, stock_count: 18 },
|
||||||
|
{ concept_name: '核心部件', avg_change_pct: 3.34, stock_count: 17 },
|
||||||
|
// 新型电池技术下的 lv3
|
||||||
|
{ concept_name: '电池类型', avg_change_pct: 1.23, stock_count: 35 },
|
||||||
|
{ concept_name: '电池材料', avg_change_pct: 0.12, stock_count: 27 },
|
||||||
|
// 低空经济下的 lv3
|
||||||
|
{ concept_name: '飞行器', avg_change_pct: 5.67, stock_count: 26 },
|
||||||
|
{ concept_name: '配套设施', avg_change_pct: 3.12, stock_count: 16 }
|
||||||
|
];
|
||||||
|
|
||||||
|
// 模拟叶子概念涨跌幅数据 (leaf_concepts) - 这是最细粒度的概念数据
|
||||||
|
const leaf_concepts = [
|
||||||
|
// 人工智能 - AI基础设施 - AI算力硬件
|
||||||
|
{ concept_name: 'AI芯片', avg_change_pct: 6.78, stock_count: 12, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI算力硬件' },
|
||||||
|
{ concept_name: 'GPU概念股', avg_change_pct: 5.45, stock_count: 8, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI算力硬件' },
|
||||||
|
{ concept_name: '服务器', avg_change_pct: 4.23, stock_count: 15, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI算力硬件' },
|
||||||
|
{ concept_name: 'AI一体机', avg_change_pct: 5.12, stock_count: 6, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI算力硬件' },
|
||||||
|
{ concept_name: '算力租赁', avg_change_pct: 3.89, stock_count: 8, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI算力硬件' },
|
||||||
|
{ concept_name: 'NPU', avg_change_pct: 7.23, stock_count: 5, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI算力硬件' },
|
||||||
|
{ concept_name: '智能计算中心', avg_change_pct: 4.56, stock_count: 9, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI算力硬件' },
|
||||||
|
{ concept_name: '超算中心', avg_change_pct: 3.12, stock_count: 4, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI算力硬件' },
|
||||||
|
// AI关键组件
|
||||||
|
{ concept_name: 'HBM', avg_change_pct: 8.12, stock_count: 10, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI关键组件' },
|
||||||
|
{ concept_name: 'PCB', avg_change_pct: 2.34, stock_count: 18, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI关键组件' },
|
||||||
|
{ concept_name: '光通信', avg_change_pct: 4.56, stock_count: 14, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI关键组件' },
|
||||||
|
{ concept_name: '存储芯片', avg_change_pct: 3.78, stock_count: 12, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI关键组件' },
|
||||||
|
{ concept_name: 'CPO', avg_change_pct: 9.34, stock_count: 8, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI关键组件' },
|
||||||
|
{ concept_name: '光模块', avg_change_pct: 5.67, stock_count: 11, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI关键组件' },
|
||||||
|
{ concept_name: '铜连接', avg_change_pct: 3.45, stock_count: 9, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI关键组件' },
|
||||||
|
{ concept_name: '高速背板', avg_change_pct: 2.89, stock_count: 6, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI关键组件' },
|
||||||
|
// AI配套设施
|
||||||
|
{ concept_name: '数据中心', avg_change_pct: 3.12, stock_count: 16, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI配套设施' },
|
||||||
|
{ concept_name: '液冷', avg_change_pct: 6.78, stock_count: 12, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI配套设施' },
|
||||||
|
{ concept_name: '电力设备', avg_change_pct: 1.23, stock_count: 22, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI配套设施' },
|
||||||
|
{ concept_name: 'UPS', avg_change_pct: 2.45, stock_count: 8, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI配套设施' },
|
||||||
|
{ concept_name: 'IDC服务', avg_change_pct: 1.89, stock_count: 10, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI配套设施' },
|
||||||
|
{ concept_name: '边缘计算', avg_change_pct: 2.67, stock_count: 9, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI配套设施' },
|
||||||
|
{ concept_name: 'AI电源', avg_change_pct: 4.12, stock_count: 7, lv1: '人工智能', lv2: 'AI基础设施', lv3: 'AI配套设施' },
|
||||||
|
// AI模型与软件
|
||||||
|
{ concept_name: 'DeepSeek', avg_change_pct: 12.34, stock_count: 15, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: 'KIMI', avg_change_pct: 8.56, stock_count: 12, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: 'SORA概念', avg_change_pct: 6.78, stock_count: 10, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: '国产大模型', avg_change_pct: 5.45, stock_count: 18, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: 'ChatGPT', avg_change_pct: 4.23, stock_count: 14, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: 'Claude', avg_change_pct: 3.89, stock_count: 8, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: '文心一言', avg_change_pct: 5.12, stock_count: 11, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: '通义千问', avg_change_pct: 4.67, stock_count: 9, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: 'Gemini概念', avg_change_pct: 3.45, stock_count: 6, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
{ concept_name: 'AI推理', avg_change_pct: 4.89, stock_count: 13, lv1: '人工智能', lv2: 'AI模型与软件' },
|
||||||
|
// AI应用 - 智能体与陪伴
|
||||||
|
{ concept_name: 'AI伴侣', avg_change_pct: 4.56, stock_count: 8, lv1: '人工智能', lv2: 'AI应用', lv3: '智能体与陪伴' },
|
||||||
|
{ concept_name: 'AI智能体', avg_change_pct: 5.78, stock_count: 12, lv1: '人工智能', lv2: 'AI应用', lv3: '智能体与陪伴' },
|
||||||
|
{ concept_name: 'AI陪伴', avg_change_pct: 3.23, stock_count: 6, lv1: '人工智能', lv2: 'AI应用', lv3: '智能体与陪伴' },
|
||||||
|
{ concept_name: 'AI助手', avg_change_pct: 2.89, stock_count: 10, lv1: '人工智能', lv2: 'AI应用', lv3: '智能体与陪伴' },
|
||||||
|
{ concept_name: '数字人', avg_change_pct: 4.12, stock_count: 14, lv1: '人工智能', lv2: 'AI应用', lv3: '智能体与陪伴' },
|
||||||
|
{ concept_name: 'AI语音', avg_change_pct: 1.67, stock_count: 9, lv1: '人工智能', lv2: 'AI应用', lv3: '智能体与陪伴' },
|
||||||
|
{ concept_name: 'AI社交', avg_change_pct: 2.34, stock_count: 5, lv1: '人工智能', lv2: 'AI应用', lv3: '智能体与陪伴' },
|
||||||
|
// AI应用 - 行业应用
|
||||||
|
{ concept_name: 'AI编程', avg_change_pct: 3.45, stock_count: 11, lv1: '人工智能', lv2: 'AI应用', lv3: '行业应用' },
|
||||||
|
{ concept_name: '低代码', avg_change_pct: 1.89, stock_count: 8, lv1: '人工智能', lv2: 'AI应用', lv3: '行业应用' },
|
||||||
|
{ concept_name: 'AI教育', avg_change_pct: 2.12, stock_count: 12, lv1: '人工智能', lv2: 'AI应用', lv3: '行业应用' },
|
||||||
|
{ concept_name: 'AI医疗', avg_change_pct: 0.78, stock_count: 15, lv1: '人工智能', lv2: 'AI应用', lv3: '行业应用' },
|
||||||
|
{ concept_name: 'AI金融', avg_change_pct: 1.56, stock_count: 10, lv1: '人工智能', lv2: 'AI应用', lv3: '行业应用' },
|
||||||
|
{ concept_name: 'AI制造', avg_change_pct: 1.23, stock_count: 8, lv1: '人工智能', lv2: 'AI应用', lv3: '行业应用' },
|
||||||
|
{ concept_name: 'AI安防', avg_change_pct: 0.89, stock_count: 11, lv1: '人工智能', lv2: 'AI应用', lv3: '行业应用' },
|
||||||
|
{ concept_name: 'AI营销', avg_change_pct: 2.34, stock_count: 7, lv1: '人工智能', lv2: 'AI应用', lv3: '行业应用' },
|
||||||
|
{ concept_name: 'AI设计', avg_change_pct: 1.67, stock_count: 6, lv1: '人工智能', lv2: 'AI应用', lv3: '行业应用' },
|
||||||
|
// 机器人相关叶子概念
|
||||||
|
{ concept_name: '特斯拉机器人', avg_change_pct: 8.45, stock_count: 18, lv1: '机器人', lv2: '人形机器人整机', lv3: '整机厂商' },
|
||||||
|
{ concept_name: '人形机器人', avg_change_pct: 7.23, stock_count: 25, lv1: '机器人', lv2: '人形机器人整机', lv3: '整机厂商' },
|
||||||
|
{ concept_name: '智元机器人', avg_change_pct: 6.12, stock_count: 10, lv1: '机器人', lv2: '人形机器人整机', lv3: '整机厂商' },
|
||||||
|
{ concept_name: '优必选', avg_change_pct: 5.78, stock_count: 8, lv1: '机器人', lv2: '人形机器人整机', lv3: '整机厂商' },
|
||||||
|
{ concept_name: '滚柱丝杆', avg_change_pct: 4.56, stock_count: 12, lv1: '机器人', lv2: '机器人核心零部件' },
|
||||||
|
{ concept_name: '电子皮肤', avg_change_pct: 5.89, stock_count: 8, lv1: '机器人', lv2: '机器人核心零部件' },
|
||||||
|
{ concept_name: '轴向磁通电机', avg_change_pct: 3.78, stock_count: 6, lv1: '机器人', lv2: '机器人核心零部件' },
|
||||||
|
{ concept_name: '谐波减速器', avg_change_pct: 2.89, stock_count: 10, lv1: '机器人', lv2: '机器人核心零部件' },
|
||||||
|
{ concept_name: '行星减速器', avg_change_pct: 2.45, stock_count: 9, lv1: '机器人', lv2: '机器人核心零部件' },
|
||||||
|
{ concept_name: '伺服电机', avg_change_pct: 3.12, stock_count: 14, lv1: '机器人', lv2: '机器人核心零部件' },
|
||||||
|
{ concept_name: '六维力传感器', avg_change_pct: 4.23, stock_count: 7, lv1: '机器人', lv2: '机器人核心零部件' },
|
||||||
|
{ concept_name: '灵巧手', avg_change_pct: 5.12, stock_count: 6, lv1: '机器人', lv2: '机器人核心零部件' },
|
||||||
|
// 低空经济相关叶子概念
|
||||||
|
{ concept_name: '低空经济', avg_change_pct: 6.78, stock_count: 22, lv1: '空天经济', lv2: '低空经济', lv3: '飞行器' },
|
||||||
|
{ concept_name: 'eVTOL', avg_change_pct: 7.89, stock_count: 15, lv1: '空天经济', lv2: '低空经济', lv3: '飞行器' },
|
||||||
|
{ concept_name: '飞行汽车', avg_change_pct: 5.45, stock_count: 12, lv1: '空天经济', lv2: '低空经济', lv3: '飞行器' },
|
||||||
|
{ concept_name: '无人机', avg_change_pct: 4.23, stock_count: 18, lv1: '空天经济', lv2: '低空经济', lv3: '飞行器' },
|
||||||
|
{ concept_name: '电动垂直起降', avg_change_pct: 6.12, stock_count: 10, lv1: '空天经济', lv2: '低空经济', lv3: '飞行器' },
|
||||||
|
{ concept_name: '卫星互联网', avg_change_pct: 3.45, stock_count: 16, lv1: '空天经济', lv2: '商业航天' },
|
||||||
|
{ concept_name: '商业航天', avg_change_pct: 2.89, stock_count: 14, lv1: '空天经济', lv2: '商业航天' },
|
||||||
|
{ concept_name: '北斗导航', avg_change_pct: 1.56, stock_count: 20, lv1: '空天经济', lv2: '商业航天' },
|
||||||
|
{ concept_name: '星链概念', avg_change_pct: 4.12, stock_count: 8, lv1: '空天经济', lv2: '商业航天' },
|
||||||
|
// 半导体相关叶子概念
|
||||||
|
{ concept_name: '光刻机', avg_change_pct: 5.67, stock_count: 10, lv1: '半导体', lv2: '半导体设备', lv3: '前道设备' },
|
||||||
|
{ concept_name: '刻蚀设备', avg_change_pct: 4.23, stock_count: 8, lv1: '半导体', lv2: '半导体设备', lv3: '前道设备' },
|
||||||
|
{ concept_name: '薄膜沉积', avg_change_pct: 3.89, stock_count: 7, lv1: '半导体', lv2: '半导体设备', lv3: '前道设备' },
|
||||||
|
{ concept_name: '光刻胶', avg_change_pct: 2.34, stock_count: 12, lv1: '半导体', lv2: '半导体材料' },
|
||||||
|
{ concept_name: '半导体材料', avg_change_pct: 1.89, stock_count: 18, lv1: '半导体', lv2: '半导体材料' },
|
||||||
|
{ concept_name: '硅片', avg_change_pct: 1.23, stock_count: 10, lv1: '半导体', lv2: '半导体材料' },
|
||||||
|
{ concept_name: '电子特气', avg_change_pct: 2.56, stock_count: 8, lv1: '半导体', lv2: '半导体材料' },
|
||||||
|
{ concept_name: 'Chiplet', avg_change_pct: 4.56, stock_count: 14, lv1: '半导体', lv2: '先进封装' },
|
||||||
|
{ concept_name: 'CoWoS', avg_change_pct: 5.12, stock_count: 10, lv1: '半导体', lv2: '先进封装' },
|
||||||
|
{ concept_name: '玻璃基板', avg_change_pct: 3.78, stock_count: 8, lv1: '半导体', lv2: '先进封装' },
|
||||||
|
// 新能源相关叶子概念
|
||||||
|
{ concept_name: '固态电池', avg_change_pct: 3.45, stock_count: 18, lv1: '新能源与电力', lv2: '新型电池技术', lv3: '电池类型' },
|
||||||
|
{ concept_name: '钠离子电池', avg_change_pct: 2.12, stock_count: 14, lv1: '新能源与电力', lv2: '新型电池技术', lv3: '电池类型' },
|
||||||
|
{ concept_name: '锂电池', avg_change_pct: 0.89, stock_count: 25, lv1: '新能源与电力', lv2: '新型电池技术', lv3: '电池类型' },
|
||||||
|
{ concept_name: '磷酸铁锂', avg_change_pct: 0.56, stock_count: 16, lv1: '新能源与电力', lv2: '新型电池技术', lv3: '电池类型' },
|
||||||
|
{ concept_name: '硅基负极', avg_change_pct: 1.78, stock_count: 10, lv1: '新能源与电力', lv2: '新型电池技术', lv3: '电池材料' },
|
||||||
|
{ concept_name: '电解液', avg_change_pct: -0.34, stock_count: 12, lv1: '新能源与电力', lv2: '新型电池技术', lv3: '电池材料' },
|
||||||
|
{ concept_name: '光伏', avg_change_pct: -1.23, stock_count: 28, lv1: '新能源与电力', lv2: '清洁能源' },
|
||||||
|
{ concept_name: '核电', avg_change_pct: 0.56, stock_count: 14, lv1: '新能源与电力', lv2: '清洁能源' },
|
||||||
|
{ concept_name: '可控核聚变', avg_change_pct: 2.89, stock_count: 8, lv1: '新能源与电力', lv2: '清洁能源' },
|
||||||
|
{ concept_name: '风电', avg_change_pct: -0.89, stock_count: 20, lv1: '新能源与电力', lv2: '清洁能源' },
|
||||||
|
{ concept_name: '储能', avg_change_pct: -0.45, stock_count: 22, lv1: '新能源与电力', lv2: '电力设备与电网' },
|
||||||
|
{ concept_name: '充电桩', avg_change_pct: 1.23, stock_count: 16, lv1: '新能源与电力', lv2: '电力设备与电网' },
|
||||||
|
{ concept_name: '特高压', avg_change_pct: -1.56, stock_count: 12, lv1: '新能源与电力', lv2: '电力设备与电网' },
|
||||||
|
// 前沿科技叶子概念
|
||||||
|
{ concept_name: '量子计算', avg_change_pct: 6.78, stock_count: 12, lv1: '前沿科技', lv2: '量子科技' },
|
||||||
|
{ concept_name: '量子通信', avg_change_pct: 4.56, stock_count: 10, lv1: '前沿科技', lv2: '量子科技' },
|
||||||
|
{ concept_name: '量子芯片', avg_change_pct: 5.23, stock_count: 8, lv1: '前沿科技', lv2: '量子科技' },
|
||||||
|
{ concept_name: '脑机接口', avg_change_pct: 5.89, stock_count: 14, lv1: '前沿科技', lv2: '脑机接口' },
|
||||||
|
{ concept_name: 'Neuralink概念', avg_change_pct: 4.12, stock_count: 6, lv1: '前沿科技', lv2: '脑机接口' },
|
||||||
|
{ concept_name: '神经科技', avg_change_pct: 3.45, stock_count: 8, lv1: '前沿科技', lv2: '脑机接口' },
|
||||||
|
// 消费电子叶子概念
|
||||||
|
{ concept_name: 'AI PC', avg_change_pct: 2.34, stock_count: 12, lv1: '消费电子', lv2: '智能终端' },
|
||||||
|
{ concept_name: 'AI手机', avg_change_pct: 1.89, stock_count: 14, lv1: '消费电子', lv2: '智能终端' },
|
||||||
|
{ concept_name: '折叠屏', avg_change_pct: 1.56, stock_count: 10, lv1: '消费电子', lv2: '智能终端' },
|
||||||
|
{ concept_name: 'AR眼镜', avg_change_pct: 4.56, stock_count: 16, lv1: '消费电子', lv2: 'XR与空间计算', lv3: 'XR硬件' },
|
||||||
|
{ concept_name: 'MR', avg_change_pct: 3.23, stock_count: 12, lv1: '消费电子', lv2: 'XR与空间计算', lv3: 'XR硬件' },
|
||||||
|
{ concept_name: '智能眼镜', avg_change_pct: 2.89, stock_count: 10, lv1: '消费电子', lv2: 'XR与空间计算', lv3: 'XR硬件' },
|
||||||
|
{ concept_name: 'VR头显', avg_change_pct: 1.78, stock_count: 8, lv1: '消费电子', lv2: 'XR与空间计算', lv3: 'XR硬件' },
|
||||||
|
{ concept_name: '华为Mate70', avg_change_pct: 1.23, stock_count: 12, lv1: '消费电子', lv2: '华为产业链' },
|
||||||
|
{ concept_name: '鸿蒙', avg_change_pct: 0.89, stock_count: 18, lv1: '消费电子', lv2: '华为产业链' },
|
||||||
|
{ concept_name: '华为昇腾', avg_change_pct: 2.12, stock_count: 10, lv1: '消费电子', lv2: '华为产业链' },
|
||||||
|
{ concept_name: '麒麟芯片', avg_change_pct: 1.56, stock_count: 8, lv1: '消费电子', lv2: '华为产业链' },
|
||||||
|
// 智能驾驶叶子概念
|
||||||
|
{ concept_name: 'Robotaxi', avg_change_pct: 5.67, stock_count: 14, lv1: '智能驾驶与汽车', lv2: '自动驾驶解决方案', lv3: '整体方案' },
|
||||||
|
{ concept_name: '无人驾驶', avg_change_pct: 4.89, stock_count: 18, lv1: '智能驾驶与汽车', lv2: '自动驾驶解决方案', lv3: '整体方案' },
|
||||||
|
{ concept_name: '特斯拉FSD', avg_change_pct: 6.12, stock_count: 12, lv1: '智能驾驶与汽车', lv2: '自动驾驶解决方案', lv3: '整体方案' },
|
||||||
|
{ concept_name: '萝卜快跑', avg_change_pct: 7.23, stock_count: 8, lv1: '智能驾驶与汽车', lv2: '自动驾驶解决方案', lv3: '整体方案' },
|
||||||
|
{ concept_name: '激光雷达', avg_change_pct: 3.45, stock_count: 16, lv1: '智能驾驶与汽车', lv2: '自动驾驶解决方案', lv3: '核心部件' },
|
||||||
|
{ concept_name: '毫米波雷达', avg_change_pct: 2.78, stock_count: 10, lv1: '智能驾驶与汽车', lv2: '自动驾驶解决方案', lv3: '核心部件' },
|
||||||
|
{ concept_name: '域控制器', avg_change_pct: 3.12, stock_count: 12, lv1: '智能驾驶与汽车', lv2: '自动驾驶解决方案', lv3: '核心部件' },
|
||||||
|
{ concept_name: '比亚迪产业链', avg_change_pct: 2.89, stock_count: 20, lv1: '智能驾驶与汽车', lv2: '智能汽车产业链' },
|
||||||
|
{ concept_name: '特斯拉产业链', avg_change_pct: 3.56, stock_count: 18, lv1: '智能驾驶与汽车', lv2: '智能汽车产业链' },
|
||||||
|
{ concept_name: '小米汽车产业链', avg_change_pct: 4.12, stock_count: 15, lv1: '智能驾驶与汽车', lv2: '智能汽车产业链' },
|
||||||
|
{ concept_name: '新能源汽车', avg_change_pct: 1.78, stock_count: 35, lv1: '智能驾驶与汽车', lv2: '智能汽车产业链' },
|
||||||
|
// 医药健康叶子概念
|
||||||
|
{ concept_name: '创新药', avg_change_pct: -1.89, stock_count: 22, lv1: '医药健康', lv2: '创新药' },
|
||||||
|
{ concept_name: 'CXO', avg_change_pct: -2.34, stock_count: 14, lv1: '医药健康', lv2: '创新药' },
|
||||||
|
{ concept_name: 'ADC', avg_change_pct: -0.78, stock_count: 10, lv1: '医药健康', lv2: '创新药' },
|
||||||
|
{ concept_name: '减肥药', avg_change_pct: 1.23, stock_count: 12, lv1: '医药健康', lv2: '创新药' },
|
||||||
|
{ concept_name: 'GLP-1', avg_change_pct: 0.89, stock_count: 8, lv1: '医药健康', lv2: '创新药' },
|
||||||
|
{ concept_name: '医疗器械', avg_change_pct: -1.12, stock_count: 18, lv1: '医药健康', lv2: '医疗器械' },
|
||||||
|
{ concept_name: '手术机器人', avg_change_pct: 0.56, stock_count: 10, lv1: '医药健康', lv2: '医疗器械' },
|
||||||
|
{ concept_name: '中药', avg_change_pct: -1.45, stock_count: 16, lv1: '医药健康', lv2: '中医药' },
|
||||||
|
// 大消费叶子概念
|
||||||
|
{ concept_name: '白酒', avg_change_pct: 1.23, stock_count: 18, lv1: '大消费', lv2: '食品饮料' },
|
||||||
|
{ concept_name: '啤酒', avg_change_pct: 0.56, stock_count: 10, lv1: '大消费', lv2: '食品饮料' },
|
||||||
|
{ concept_name: '预制菜', avg_change_pct: -0.34, stock_count: 12, lv1: '大消费', lv2: '食品饮料' },
|
||||||
|
{ concept_name: '免税', avg_change_pct: 0.89, stock_count: 8, lv1: '大消费', lv2: '消费服务' },
|
||||||
|
{ concept_name: '旅游', avg_change_pct: 0.45, stock_count: 14, lv1: '大消费', lv2: '消费服务' },
|
||||||
|
{ concept_name: '电商', avg_change_pct: 0.12, stock_count: 16, lv1: '大消费', lv2: '消费服务' },
|
||||||
|
{ concept_name: '直播带货', avg_change_pct: -0.23, stock_count: 10, lv1: '大消费', lv2: '消费服务' },
|
||||||
|
// 金融科技叶子概念
|
||||||
|
{ concept_name: '数字货币', avg_change_pct: 3.45, stock_count: 16, lv1: '数字经济与金融科技', lv2: '金融科技' },
|
||||||
|
{ concept_name: '区块链', avg_change_pct: 2.89, stock_count: 18, lv1: '数字经济与金融科技', lv2: '金融科技' },
|
||||||
|
{ concept_name: 'Web3', avg_change_pct: 2.12, stock_count: 10, lv1: '数字经济与金融科技', lv2: '金融科技' },
|
||||||
|
{ concept_name: '云计算', avg_change_pct: 2.34, stock_count: 22, lv1: '数字经济与金融科技', lv2: '数字化转型' },
|
||||||
|
{ concept_name: '大数据', avg_change_pct: 1.78, stock_count: 18, lv1: '数字经济与金融科技', lv2: '数字化转型' },
|
||||||
|
{ concept_name: '物联网', avg_change_pct: 1.45, stock_count: 16, lv1: '数字经济与金融科技', lv2: '数字化转型' },
|
||||||
|
{ concept_name: '5G', avg_change_pct: 0.89, stock_count: 20, lv1: '数字经济与金融科技', lv2: '数字化转型' },
|
||||||
|
{ concept_name: '6G', avg_change_pct: 2.56, stock_count: 10, lv1: '数字经济与金融科技', lv2: '数字化转型' },
|
||||||
|
{ concept_name: '元宇宙', avg_change_pct: 1.23, stock_count: 14, lv1: '数字经济与金融科技', lv2: '数字化转型' },
|
||||||
|
// 政策主题叶子概念
|
||||||
|
{ concept_name: '一带一路', avg_change_pct: 1.89, stock_count: 22, lv1: '政策与主题', lv2: '国家战略' },
|
||||||
|
{ concept_name: '国产替代', avg_change_pct: 2.34, stock_count: 28, lv1: '政策与主题', lv2: '国家战略' },
|
||||||
|
{ concept_name: '自主可控', avg_change_pct: 2.12, stock_count: 24, lv1: '政策与主题', lv2: '国家战略' },
|
||||||
|
{ concept_name: '信创', avg_change_pct: 1.56, stock_count: 18, lv1: '政策与主题', lv2: '国家战略' },
|
||||||
|
{ concept_name: '数字经济', avg_change_pct: 1.78, stock_count: 20, lv1: '政策与主题', lv2: '国家战略' },
|
||||||
|
{ concept_name: '粤港澳大湾区', avg_change_pct: 0.89, stock_count: 16, lv1: '政策与主题', lv2: '区域发展' },
|
||||||
|
{ concept_name: '长三角一体化', avg_change_pct: 0.56, stock_count: 14, lv1: '政策与主题', lv2: '区域发展' },
|
||||||
|
{ concept_name: '海南自贸港', avg_change_pct: 1.23, stock_count: 10, lv1: '政策与主题', lv2: '区域发展' },
|
||||||
|
// 周期材料叶子概念
|
||||||
|
{ concept_name: '黄金', avg_change_pct: -0.45, stock_count: 14, lv1: '周期与材料', lv2: '有色金属' },
|
||||||
|
{ concept_name: '白银', avg_change_pct: -0.78, stock_count: 10, lv1: '周期与材料', lv2: '有色金属' },
|
||||||
|
{ concept_name: '铜', avg_change_pct: -1.23, stock_count: 12, lv1: '周期与材料', lv2: '有色金属' },
|
||||||
|
{ concept_name: '稀土', avg_change_pct: -1.56, stock_count: 16, lv1: '周期与材料', lv2: '有色金属' },
|
||||||
|
{ concept_name: '锂', avg_change_pct: -2.34, stock_count: 14, lv1: '周期与材料', lv2: '有色金属' },
|
||||||
|
{ concept_name: '氟化工', avg_change_pct: -0.34, stock_count: 10, lv1: '周期与材料', lv2: '化工材料' },
|
||||||
|
{ concept_name: '碳纤维', avg_change_pct: 0.12, stock_count: 8, lv1: '周期与材料', lv2: '化工材料' },
|
||||||
|
{ concept_name: '石墨烯', avg_change_pct: 0.89, stock_count: 12, lv1: '周期与材料', lv2: '化工材料' },
|
||||||
|
// 国防军工叶子概念
|
||||||
|
{ concept_name: 'AI军工', avg_change_pct: 3.12, stock_count: 10, lv1: '国防军工', lv2: '无人作战与信息化' },
|
||||||
|
{ concept_name: '无人机蜂群', avg_change_pct: 2.78, stock_count: 8, lv1: '国防军工', lv2: '无人作战与信息化' },
|
||||||
|
{ concept_name: '军工信息化', avg_change_pct: 1.89, stock_count: 12, lv1: '国防军工', lv2: '无人作战与信息化' },
|
||||||
|
{ concept_name: '国产航母', avg_change_pct: 1.56, stock_count: 10, lv1: '国防军工', lv2: '海军装备' },
|
||||||
|
{ concept_name: '电磁弹射', avg_change_pct: 1.23, stock_count: 8, lv1: '国防军工', lv2: '海军装备' },
|
||||||
|
{ concept_name: '军贸', avg_change_pct: 1.45, stock_count: 10, lv1: '国防军工', lv2: '军贸出海' },
|
||||||
|
{ concept_name: '航展概念', avg_change_pct: 0.89, stock_count: 8, lv1: '国防军工', lv2: '军贸出海' }
|
||||||
];
|
];
|
||||||
|
|
||||||
// 计算交易日期(如果没有传入则使用今天)
|
// 计算交易日期(如果没有传入则使用今天)
|
||||||
@@ -814,6 +1454,7 @@ export const conceptHandlers = [
|
|||||||
lv1_concepts,
|
lv1_concepts,
|
||||||
lv2_concepts,
|
lv2_concepts,
|
||||||
lv3_concepts,
|
lv3_concepts,
|
||||||
|
leaf_concepts,
|
||||||
update_time: new Date().toISOString()
|
update_time: new Date().toISOString()
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -239,8 +239,238 @@ const generateDailyAnalysis = (date) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ==================== 静态文件 Mock Handlers ====================
|
||||||
|
// 这些 handlers 用于拦截 /data/zt/* 静态文件请求
|
||||||
|
|
||||||
|
// 生成 dates.json 数据
|
||||||
|
const generateDatesJson = () => {
|
||||||
|
const dates = [];
|
||||||
|
const today = new Date();
|
||||||
|
|
||||||
|
for (let i = 0; i < 60; i++) {
|
||||||
|
const date = new Date(today);
|
||||||
|
date.setDate(date.getDate() - i);
|
||||||
|
const dayOfWeek = date.getDay();
|
||||||
|
|
||||||
|
// 跳过周末
|
||||||
|
if (dayOfWeek !== 0 && dayOfWeek !== 6) {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
|
||||||
|
dates.push({
|
||||||
|
date: `${year}${month}${day}`,
|
||||||
|
formatted_date: `${year}-${month}-${day}`,
|
||||||
|
count: Math.floor(Math.random() * 60) + 40 // 40-100 只涨停股票
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dates.length >= 30) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { dates };
|
||||||
|
};
|
||||||
|
|
||||||
|
// 生成每日分析 JSON 数据(用于 /data/zt/daily/${date}.json)
|
||||||
|
const generateDailyJson = (date) => {
|
||||||
|
// 板块名称列表
|
||||||
|
const sectorNames = [
|
||||||
|
'公告', '人工智能', 'ChatGPT', '大模型', '算力',
|
||||||
|
'光伏', '新能源汽车', '锂电池', '储能', '充电桩',
|
||||||
|
'半导体', '芯片', '集成电路', '国产替代',
|
||||||
|
'医药', '创新药', 'CXO', '医疗器械',
|
||||||
|
'军工', '航空航天', '其他'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 股票名称模板
|
||||||
|
const stockPrefixes = [
|
||||||
|
'龙头', '科技', '新能', '智能', '数字', '云计', '创新',
|
||||||
|
'生物', '医疗', '通信', '电子', '材料', '能源', '互联',
|
||||||
|
'天马', '华鑫', '中科', '东方', '西部', '南方', '北方',
|
||||||
|
'金龙', '银河', '星辰', '宏达', '盛世', '鹏程', '万里'
|
||||||
|
];
|
||||||
|
|
||||||
|
const stockSuffixes = [
|
||||||
|
'股份', '科技', '电子', '信息', '新材', '能源', '医药',
|
||||||
|
'通讯', '智造', '集团', '实业', '控股', '产业', '发展'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 生成所有股票
|
||||||
|
const stocks = [];
|
||||||
|
const sectorData = {};
|
||||||
|
let stockIndex = 0;
|
||||||
|
|
||||||
|
sectorNames.forEach((sectorName, sectorIdx) => {
|
||||||
|
const stockCount = sectorName === '公告'
|
||||||
|
? Math.floor(Math.random() * 5) + 8 // 公告板块 8-12 只
|
||||||
|
: sectorName === '其他'
|
||||||
|
? Math.floor(Math.random() * 4) + 3 // 其他板块 3-6 只
|
||||||
|
: Math.floor(Math.random() * 8) + 3; // 普通板块 3-10 只
|
||||||
|
|
||||||
|
const sectorStockCodes = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < stockCount; i++) {
|
||||||
|
const code = `${Math.random() > 0.6 ? '6' : Math.random() > 0.3 ? '0' : '3'}${String(Math.floor(Math.random() * 100000)).padStart(5, '0')}`;
|
||||||
|
const continuousDays = Math.floor(Math.random() * 6) + 1;
|
||||||
|
const ztHour = Math.floor(Math.random() * 4) + 9;
|
||||||
|
const ztMinute = Math.floor(Math.random() * 60);
|
||||||
|
const ztSecond = Math.floor(Math.random() * 60);
|
||||||
|
|
||||||
|
const prefix = stockPrefixes[Math.floor(Math.random() * stockPrefixes.length)];
|
||||||
|
const suffix = stockSuffixes[Math.floor(Math.random() * stockSuffixes.length)];
|
||||||
|
const stockName = `${prefix}${suffix}`;
|
||||||
|
|
||||||
|
// 生成关联板块
|
||||||
|
const coreSectors = [sectorName];
|
||||||
|
if (Math.random() > 0.5) {
|
||||||
|
const otherSector = sectorNames[Math.floor(Math.random() * (sectorNames.length - 1))];
|
||||||
|
if (otherSector !== sectorName && otherSector !== '其他' && otherSector !== '公告') {
|
||||||
|
coreSectors.push(otherSector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stocks.push({
|
||||||
|
scode: code,
|
||||||
|
sname: stockName,
|
||||||
|
zt_time: `${date.slice(0,4)}-${date.slice(4,6)}-${date.slice(6,8)} ${String(ztHour).padStart(2,'0')}:${String(ztMinute).padStart(2,'0')}:${String(ztSecond).padStart(2,'0')}`,
|
||||||
|
formatted_time: `${String(ztHour).padStart(2,'0')}:${String(ztMinute).padStart(2,'0')}`,
|
||||||
|
continuous_days: continuousDays === 1 ? '首板' : `${continuousDays}连板`,
|
||||||
|
brief: sectorName === '公告'
|
||||||
|
? `${stockName}发布重大公告,公司拟收购资产/重组/增发等利好消息。`
|
||||||
|
: `${sectorName}板块异动,${stockName}因板块热点涨停。公司是${sectorName}行业核心标的。`,
|
||||||
|
summary: `${sectorName}概念活跃`,
|
||||||
|
first_time: `${date.slice(0,4)}-${date.slice(4,6)}-${String(parseInt(date.slice(6,8)) - (continuousDays - 1)).padStart(2,'0')}`,
|
||||||
|
change_pct: parseFloat((Math.random() * 1.5 + 9.5).toFixed(2)),
|
||||||
|
core_sectors: coreSectors
|
||||||
|
});
|
||||||
|
|
||||||
|
sectorStockCodes.push(code);
|
||||||
|
stockIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
sectorData[sectorName] = {
|
||||||
|
count: stockCount,
|
||||||
|
stock_codes: sectorStockCodes
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 生成词频数据
|
||||||
|
const wordFreqData = [
|
||||||
|
{ name: '人工智能', value: Math.floor(Math.random() * 30) + 20 },
|
||||||
|
{ name: 'ChatGPT', value: Math.floor(Math.random() * 25) + 15 },
|
||||||
|
{ name: '大模型', value: Math.floor(Math.random() * 20) + 12 },
|
||||||
|
{ name: '算力', value: Math.floor(Math.random() * 18) + 10 },
|
||||||
|
{ name: '光伏', value: Math.floor(Math.random() * 15) + 10 },
|
||||||
|
{ name: '新能源', value: Math.floor(Math.random() * 15) + 8 },
|
||||||
|
{ name: '锂电池', value: Math.floor(Math.random() * 12) + 8 },
|
||||||
|
{ name: '储能', value: Math.floor(Math.random() * 12) + 6 },
|
||||||
|
{ name: '半导体', value: Math.floor(Math.random() * 15) + 10 },
|
||||||
|
{ name: '芯片', value: Math.floor(Math.random() * 15) + 8 },
|
||||||
|
{ name: '集成电路', value: Math.floor(Math.random() * 10) + 5 },
|
||||||
|
{ name: '国产替代', value: Math.floor(Math.random() * 10) + 5 },
|
||||||
|
{ name: '医药', value: Math.floor(Math.random() * 12) + 6 },
|
||||||
|
{ name: '创新药', value: Math.floor(Math.random() * 10) + 5 },
|
||||||
|
{ name: '医疗器械', value: Math.floor(Math.random() * 8) + 4 },
|
||||||
|
{ name: '军工', value: Math.floor(Math.random() * 10) + 5 },
|
||||||
|
{ name: '航空航天', value: Math.floor(Math.random() * 8) + 4 },
|
||||||
|
{ name: '数字经济', value: Math.floor(Math.random() * 12) + 6 },
|
||||||
|
{ name: '工业4.0', value: Math.floor(Math.random() * 8) + 4 },
|
||||||
|
{ name: '机器人', value: Math.floor(Math.random() * 10) + 5 },
|
||||||
|
{ name: '自动驾驶', value: Math.floor(Math.random() * 8) + 4 },
|
||||||
|
{ name: '元宇宙', value: Math.floor(Math.random() * 6) + 3 },
|
||||||
|
{ name: 'Web3.0', value: Math.floor(Math.random() * 5) + 2 },
|
||||||
|
{ name: '区块链', value: Math.floor(Math.random() * 5) + 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
date: date,
|
||||||
|
total_stocks: stocks.length,
|
||||||
|
total_sectors: Object.keys(sectorData).length,
|
||||||
|
stocks: stocks,
|
||||||
|
sector_data: sectorData,
|
||||||
|
word_freq_data: wordFreqData,
|
||||||
|
summary: {
|
||||||
|
top_sector: '人工智能',
|
||||||
|
top_sector_count: sectorData['人工智能']?.count || 0,
|
||||||
|
announcement_stocks: sectorData['公告']?.count || 0,
|
||||||
|
zt_time_distribution: {
|
||||||
|
morning: Math.floor(stocks.length * 0.4),
|
||||||
|
afternoon: Math.floor(stocks.length * 0.6),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 生成 stocks.jsonl 数据
|
||||||
|
const generateStocksJsonl = () => {
|
||||||
|
const stocks = [];
|
||||||
|
const today = new Date();
|
||||||
|
|
||||||
|
// 生成 200 只历史涨停股票记录
|
||||||
|
for (let i = 0; i < 200; i++) {
|
||||||
|
const daysAgo = Math.floor(Math.random() * 30);
|
||||||
|
const date = new Date(today);
|
||||||
|
date.setDate(date.getDate() - daysAgo);
|
||||||
|
|
||||||
|
// 跳过周末
|
||||||
|
while (date.getDay() === 0 || date.getDay() === 6) {
|
||||||
|
date.setDate(date.getDate() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
|
||||||
|
stocks.push({
|
||||||
|
scode: `${Math.random() > 0.6 ? '6' : Math.random() > 0.3 ? '0' : '3'}${String(Math.floor(Math.random() * 100000)).padStart(5, '0')}`,
|
||||||
|
sname: ['龙头', '科技', '新能', '智能', '数字', '云计'][Math.floor(Math.random() * 6)] +
|
||||||
|
['股份', '科技', '电子', '信息', '新材'][Math.floor(Math.random() * 5)],
|
||||||
|
date: `${year}${month}${day}`,
|
||||||
|
formatted_date: `${year}-${month}-${day}`,
|
||||||
|
continuous_days: Math.floor(Math.random() * 5) + 1,
|
||||||
|
core_sectors: [['人工智能', 'ChatGPT', '光伏', '锂电池', '芯片'][Math.floor(Math.random() * 5)]]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return stocks;
|
||||||
|
};
|
||||||
|
|
||||||
// Mock Handlers
|
// Mock Handlers
|
||||||
export const limitAnalyseHandlers = [
|
export const limitAnalyseHandlers = [
|
||||||
|
// ==================== 静态文件路径 Handlers ====================
|
||||||
|
|
||||||
|
// 1. /data/zt/dates.json - 可用日期列表
|
||||||
|
http.get('/data/zt/dates.json', async () => {
|
||||||
|
await delay(200);
|
||||||
|
console.log('[Mock LimitAnalyse] 获取 dates.json');
|
||||||
|
const data = generateDatesJson();
|
||||||
|
return HttpResponse.json(data);
|
||||||
|
}),
|
||||||
|
|
||||||
|
// 2. /data/zt/daily/:date.json - 每日分析数据
|
||||||
|
http.get('/data/zt/daily/:date', async ({ params }) => {
|
||||||
|
await delay(300);
|
||||||
|
// 移除 .json 后缀和查询参数
|
||||||
|
const dateParam = params.date.replace('.json', '').split('?')[0];
|
||||||
|
console.log('[Mock LimitAnalyse] 获取每日数据:', dateParam);
|
||||||
|
const data = generateDailyJson(dateParam);
|
||||||
|
return HttpResponse.json(data);
|
||||||
|
}),
|
||||||
|
|
||||||
|
// 3. /data/zt/stocks.jsonl - 股票列表(用于搜索)
|
||||||
|
http.get('/data/zt/stocks.jsonl', async () => {
|
||||||
|
await delay(200);
|
||||||
|
console.log('[Mock LimitAnalyse] 获取 stocks.jsonl');
|
||||||
|
const stocks = generateStocksJsonl();
|
||||||
|
// JSONL 格式:每行一个 JSON
|
||||||
|
const jsonl = stocks.map(s => JSON.stringify(s)).join('\n');
|
||||||
|
return new HttpResponse(jsonl, {
|
||||||
|
headers: { 'Content-Type': 'text/plain' }
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
// ==================== API 路径 Handlers (兼容旧版本) ====================
|
||||||
|
|
||||||
// 1. 获取可用日期列表
|
// 1. 获取可用日期列表
|
||||||
http.get('http://111.198.58.126:5001/api/v1/dates/available', async () => {
|
http.get('http://111.198.58.126:5001/api/v1/dates/available', async () => {
|
||||||
await delay(300);
|
await delay(300);
|
||||||
|
|||||||
@@ -825,7 +825,7 @@ const ConceptTimelineModal = ({
|
|||||||
bg="whiteAlpha.100"
|
bg="whiteAlpha.100"
|
||||||
borderRadius="lg"
|
borderRadius="lg"
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="orange.400"
|
borderColor="red.500"
|
||||||
flexShrink={0}
|
flexShrink={0}
|
||||||
>
|
>
|
||||||
<Text fontSize={{ base: 'xs', md: 'sm' }} fontWeight="bold">🔥</Text>
|
<Text fontSize={{ base: 'xs', md: 'sm' }} fontWeight="bold">🔥</Text>
|
||||||
|
|||||||
@@ -1006,7 +1006,7 @@ const ForceGraphView = ({
|
|||||||
|
|
||||||
// 获取容器高度
|
// 获取容器高度
|
||||||
const containerHeight = useMemo(() => {
|
const containerHeight = useMemo(() => {
|
||||||
if (isFullscreen) return '100vh';
|
if (isFullscreen) return 'calc(100vh - 60px)';
|
||||||
return isMobile ? '500px' : '700px';
|
return isMobile ? '500px' : '700px';
|
||||||
}, [isFullscreen, isMobile]);
|
}, [isFullscreen, isMobile]);
|
||||||
|
|
||||||
@@ -1069,161 +1069,84 @@ const ForceGraphView = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<VStack spacing={3} align="stretch" w="100%">
|
||||||
ref={containerRef}
|
{/* 外部工具栏 - 在蓝紫色背景外面 */}
|
||||||
position={isFullscreen ? 'fixed' : 'relative'}
|
<HStack spacing={3} px={2} justify="space-between" align="center">
|
||||||
top={isFullscreen ? 0 : 'auto'}
|
<HStack spacing={3}>
|
||||||
left={isFullscreen ? 0 : 'auto'}
|
{/* 返回按钮 */}
|
||||||
right={isFullscreen ? 0 : 'auto'}
|
{drillPath && (
|
||||||
bottom={isFullscreen ? 0 : 'auto'}
|
<Tooltip label="返回上一层" placement="bottom">
|
||||||
zIndex={isFullscreen ? 1000 : 'auto'}
|
<IconButton
|
||||||
borderRadius={isFullscreen ? '0' : '3xl'}
|
size="sm"
|
||||||
overflow="hidden"
|
icon={<FaArrowLeft />}
|
||||||
border={isFullscreen ? 'none' : '1px solid'}
|
onClick={handleGoBack}
|
||||||
borderColor="whiteAlpha.100"
|
bg="whiteAlpha.100"
|
||||||
h={containerHeight}
|
color="white"
|
||||||
bg="transparent"
|
border="1px solid"
|
||||||
>
|
borderColor="whiteAlpha.200"
|
||||||
{/* 极光背景层 */}
|
borderRadius="full"
|
||||||
<Box
|
_hover={{
|
||||||
position="absolute"
|
bg: 'purple.500',
|
||||||
top={0}
|
borderColor: 'purple.400',
|
||||||
left={0}
|
transform: 'scale(1.05)',
|
||||||
right={0}
|
}}
|
||||||
bottom={0}
|
transition="all 0.2s"
|
||||||
bg="linear-gradient(135deg, #0F172A 0%, #1E1B4B 25%, #312E81 50%, #1E1B4B 75%, #0F172A 100%)"
|
aria-label="返回"
|
||||||
backgroundSize="400% 400%"
|
/>
|
||||||
animation={`${auroraAnimation} 15s ease infinite`}
|
</Tooltip>
|
||||||
/>
|
)}
|
||||||
|
|
||||||
{/* 弥散光晕层 */}
|
<HStack
|
||||||
<Box
|
bg="whiteAlpha.100"
|
||||||
position="absolute"
|
px={4}
|
||||||
top="20%"
|
py={2}
|
||||||
left="10%"
|
borderRadius="full"
|
||||||
w="300px"
|
border="1px solid"
|
||||||
h="300px"
|
borderColor="whiteAlpha.200"
|
||||||
bg="radial-gradient(circle, rgba(139, 92, 246, 0.3) 0%, transparent 70%)"
|
>
|
||||||
filter="blur(60px)"
|
<Icon as={FaTh} color="purple.300" />
|
||||||
pointerEvents="none"
|
<Text color="white" fontWeight="bold" fontSize="sm">
|
||||||
animation={`${glowPulse} 4s ease-in-out infinite`}
|
概念矩形树图
|
||||||
/>
|
</Text>
|
||||||
<Box
|
|
||||||
position="absolute"
|
|
||||||
bottom="20%"
|
|
||||||
right="15%"
|
|
||||||
w="250px"
|
|
||||||
h="250px"
|
|
||||||
bg="radial-gradient(circle, rgba(59, 130, 246, 0.25) 0%, transparent 70%)"
|
|
||||||
filter="blur(50px)"
|
|
||||||
pointerEvents="none"
|
|
||||||
animation={`${glowPulse} 5s ease-in-out infinite 1s`}
|
|
||||||
/>
|
|
||||||
<Box
|
|
||||||
position="absolute"
|
|
||||||
top="50%"
|
|
||||||
right="30%"
|
|
||||||
w="200px"
|
|
||||||
h="200px"
|
|
||||||
bg="radial-gradient(circle, rgba(236, 72, 153, 0.2) 0%, transparent 70%)"
|
|
||||||
filter="blur(40px)"
|
|
||||||
pointerEvents="none"
|
|
||||||
animation={`${glowPulse} 6s ease-in-out infinite 2s`}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* 顶部工具栏 - 毛玻璃风格 */}
|
|
||||||
<Flex
|
|
||||||
position="absolute"
|
|
||||||
top={isFullscreen ? '70px' : 4}
|
|
||||||
left={4}
|
|
||||||
right={4}
|
|
||||||
justify="space-between"
|
|
||||||
align="flex-start"
|
|
||||||
zIndex={10}
|
|
||||||
pointerEvents="none"
|
|
||||||
>
|
|
||||||
{/* 左侧标题和面包屑 */}
|
|
||||||
<VStack align="start" spacing={2} pointerEvents="auto">
|
|
||||||
<HStack spacing={3}>
|
|
||||||
{/* 返回按钮 */}
|
|
||||||
{drillPath && (
|
|
||||||
<Tooltip label="返回上一层" placement="bottom">
|
|
||||||
<IconButton
|
|
||||||
size="sm"
|
|
||||||
icon={<FaArrowLeft />}
|
|
||||||
onClick={handleGoBack}
|
|
||||||
bg="rgba(255, 255, 255, 0.1)"
|
|
||||||
backdropFilter="blur(20px)"
|
|
||||||
color="white"
|
|
||||||
border="1px solid"
|
|
||||||
borderColor="whiteAlpha.200"
|
|
||||||
borderRadius="full"
|
|
||||||
_hover={{
|
|
||||||
bg: 'rgba(139, 92, 246, 0.4)',
|
|
||||||
borderColor: 'purple.400',
|
|
||||||
transform: 'scale(1.05)',
|
|
||||||
}}
|
|
||||||
transition="all 0.2s"
|
|
||||||
aria-label="返回"
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<HStack
|
|
||||||
bg="rgba(255, 255, 255, 0.08)"
|
|
||||||
backdropFilter="blur(20px)"
|
|
||||||
px={5}
|
|
||||||
py={2.5}
|
|
||||||
borderRadius="full"
|
|
||||||
border="1px solid"
|
|
||||||
borderColor="whiteAlpha.150"
|
|
||||||
boxShadow="0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)"
|
|
||||||
>
|
|
||||||
<Icon as={FaTh} color="purple.300" />
|
|
||||||
<Text color="white" fontWeight="bold" fontSize="sm">
|
|
||||||
概念矩形树图
|
|
||||||
</Text>
|
|
||||||
</HStack>
|
|
||||||
|
|
||||||
{/* 面包屑导航 */}
|
|
||||||
<HStack
|
|
||||||
bg="rgba(255, 255, 255, 0.06)"
|
|
||||||
backdropFilter="blur(20px)"
|
|
||||||
px={4}
|
|
||||||
py={2}
|
|
||||||
borderRadius="full"
|
|
||||||
border="1px solid"
|
|
||||||
borderColor="whiteAlpha.100"
|
|
||||||
spacing={2}
|
|
||||||
>
|
|
||||||
{breadcrumbItems.map((item, index) => (
|
|
||||||
<HStack key={index} spacing={2}>
|
|
||||||
{index > 0 && (
|
|
||||||
<Icon as={FaChevronRight} color="whiteAlpha.400" boxSize={3} />
|
|
||||||
)}
|
|
||||||
<Text
|
|
||||||
color={index === breadcrumbItems.length - 1 ? 'purple.300' : 'whiteAlpha.700'}
|
|
||||||
fontSize="sm"
|
|
||||||
fontWeight={index === breadcrumbItems.length - 1 ? 'bold' : 'normal'}
|
|
||||||
cursor={index < breadcrumbItems.length - 1 ? 'pointer' : 'default'}
|
|
||||||
_hover={index < breadcrumbItems.length - 1 ? { color: 'white' } : {}}
|
|
||||||
transition="color 0.2s"
|
|
||||||
onClick={() => {
|
|
||||||
if (index < breadcrumbItems.length - 1) {
|
|
||||||
setDrillPath(item.path);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{item.label}
|
|
||||||
</Text>
|
|
||||||
</HStack>
|
|
||||||
))}
|
|
||||||
</HStack>
|
|
||||||
</HStack>
|
</HStack>
|
||||||
</VStack>
|
|
||||||
|
{/* 面包屑导航 */}
|
||||||
|
<HStack
|
||||||
|
bg="whiteAlpha.50"
|
||||||
|
px={4}
|
||||||
|
py={2}
|
||||||
|
borderRadius="full"
|
||||||
|
border="1px solid"
|
||||||
|
borderColor="whiteAlpha.100"
|
||||||
|
spacing={2}
|
||||||
|
>
|
||||||
|
{breadcrumbItems.map((item, index) => (
|
||||||
|
<HStack key={index} spacing={2}>
|
||||||
|
{index > 0 && (
|
||||||
|
<Icon as={FaChevronRight} color="whiteAlpha.400" boxSize={3} />
|
||||||
|
)}
|
||||||
|
<Text
|
||||||
|
color={index === breadcrumbItems.length - 1 ? 'purple.300' : 'whiteAlpha.700'}
|
||||||
|
fontSize="sm"
|
||||||
|
fontWeight={index === breadcrumbItems.length - 1 ? 'bold' : 'normal'}
|
||||||
|
cursor={index < breadcrumbItems.length - 1 ? 'pointer' : 'default'}
|
||||||
|
_hover={index < breadcrumbItems.length - 1 ? { color: 'white' } : {}}
|
||||||
|
transition="color 0.2s"
|
||||||
|
onClick={() => {
|
||||||
|
if (index < breadcrumbItems.length - 1) {
|
||||||
|
setDrillPath(item.path);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
))}
|
||||||
|
</HStack>
|
||||||
|
</HStack>
|
||||||
|
|
||||||
{/* 右侧控制按钮 */}
|
{/* 右侧控制按钮 */}
|
||||||
<HStack spacing={2} pointerEvents="auto">
|
<HStack spacing={2}>
|
||||||
{priceLoading && <Spinner size="sm" color="purple.300" />}
|
{priceLoading && <Spinner size="sm" color="purple.300" />}
|
||||||
|
|
||||||
{drillPath && (
|
{drillPath && (
|
||||||
@@ -1232,14 +1155,13 @@ const ForceGraphView = ({
|
|||||||
size="sm"
|
size="sm"
|
||||||
icon={<FaHome />}
|
icon={<FaHome />}
|
||||||
onClick={handleGoHome}
|
onClick={handleGoHome}
|
||||||
bg="rgba(255, 255, 255, 0.1)"
|
bg="whiteAlpha.100"
|
||||||
backdropFilter="blur(20px)"
|
|
||||||
color="white"
|
color="white"
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="whiteAlpha.200"
|
borderColor="whiteAlpha.200"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: 'rgba(139, 92, 246, 0.4)',
|
bg: 'purple.500',
|
||||||
borderColor: 'purple.400',
|
borderColor: 'purple.400',
|
||||||
transform: 'scale(1.05)',
|
transform: 'scale(1.05)',
|
||||||
}}
|
}}
|
||||||
@@ -1255,14 +1177,13 @@ const ForceGraphView = ({
|
|||||||
icon={<FaSync />}
|
icon={<FaSync />}
|
||||||
onClick={handleRefresh}
|
onClick={handleRefresh}
|
||||||
isLoading={priceLoading}
|
isLoading={priceLoading}
|
||||||
bg="rgba(255, 255, 255, 0.1)"
|
bg="whiteAlpha.100"
|
||||||
backdropFilter="blur(20px)"
|
|
||||||
color="white"
|
color="white"
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="whiteAlpha.200"
|
borderColor="whiteAlpha.200"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: 'rgba(255, 255, 255, 0.2)',
|
bg: 'whiteAlpha.200',
|
||||||
borderColor: 'whiteAlpha.300',
|
borderColor: 'whiteAlpha.300',
|
||||||
transform: 'scale(1.05)',
|
transform: 'scale(1.05)',
|
||||||
}}
|
}}
|
||||||
@@ -1276,14 +1197,13 @@ const ForceGraphView = ({
|
|||||||
size="sm"
|
size="sm"
|
||||||
icon={isFullscreen ? <FaCompress /> : <FaExpand />}
|
icon={isFullscreen ? <FaCompress /> : <FaExpand />}
|
||||||
onClick={toggleFullscreen}
|
onClick={toggleFullscreen}
|
||||||
bg="rgba(255, 255, 255, 0.1)"
|
bg="whiteAlpha.100"
|
||||||
backdropFilter="blur(20px)"
|
|
||||||
color="white"
|
color="white"
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="whiteAlpha.200"
|
borderColor="whiteAlpha.200"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
_hover={{
|
_hover={{
|
||||||
bg: 'rgba(255, 255, 255, 0.2)',
|
bg: 'whiteAlpha.200',
|
||||||
borderColor: 'whiteAlpha.300',
|
borderColor: 'whiteAlpha.300',
|
||||||
transform: 'scale(1.05)',
|
transform: 'scale(1.05)',
|
||||||
}}
|
}}
|
||||||
@@ -1292,9 +1212,72 @@ const ForceGraphView = ({
|
|||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Flex>
|
</HStack>
|
||||||
|
|
||||||
{/* 底部图例 - 毛玻璃风格 */}
|
{/* 蓝紫色背景容器 */}
|
||||||
|
<Box
|
||||||
|
ref={containerRef}
|
||||||
|
position={isFullscreen ? 'fixed' : 'relative'}
|
||||||
|
top={isFullscreen ? '60px' : 'auto'}
|
||||||
|
left={isFullscreen ? 0 : 'auto'}
|
||||||
|
right={isFullscreen ? 0 : 'auto'}
|
||||||
|
bottom={isFullscreen ? 0 : 'auto'}
|
||||||
|
zIndex={isFullscreen ? 1000 : 'auto'}
|
||||||
|
borderRadius={isFullscreen ? '0' : '3xl'}
|
||||||
|
overflow="hidden"
|
||||||
|
border={isFullscreen ? 'none' : '1px solid'}
|
||||||
|
borderColor="whiteAlpha.100"
|
||||||
|
h={containerHeight}
|
||||||
|
bg="transparent"
|
||||||
|
>
|
||||||
|
{/* 极光背景层 */}
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
top={0}
|
||||||
|
left={0}
|
||||||
|
right={0}
|
||||||
|
bottom={0}
|
||||||
|
bg="linear-gradient(135deg, #0F172A 0%, #1E1B4B 25%, #312E81 50%, #1E1B4B 75%, #0F172A 100%)"
|
||||||
|
backgroundSize="400% 400%"
|
||||||
|
animation={`${auroraAnimation} 15s ease infinite`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 弥散光晕层 */}
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
top="20%"
|
||||||
|
left="10%"
|
||||||
|
w="300px"
|
||||||
|
h="300px"
|
||||||
|
bg="radial-gradient(circle, rgba(139, 92, 246, 0.3) 0%, transparent 70%)"
|
||||||
|
filter="blur(60px)"
|
||||||
|
pointerEvents="none"
|
||||||
|
animation={`${glowPulse} 4s ease-in-out infinite`}
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
bottom="20%"
|
||||||
|
right="15%"
|
||||||
|
w="250px"
|
||||||
|
h="250px"
|
||||||
|
bg="radial-gradient(circle, rgba(59, 130, 246, 0.25) 0%, transparent 70%)"
|
||||||
|
filter="blur(50px)"
|
||||||
|
pointerEvents="none"
|
||||||
|
animation={`${glowPulse} 5s ease-in-out infinite 1s`}
|
||||||
|
/>
|
||||||
|
<Box
|
||||||
|
position="absolute"
|
||||||
|
top="50%"
|
||||||
|
right="30%"
|
||||||
|
w="200px"
|
||||||
|
h="200px"
|
||||||
|
bg="radial-gradient(circle, rgba(236, 72, 153, 0.2) 0%, transparent 70%)"
|
||||||
|
filter="blur(40px)"
|
||||||
|
pointerEvents="none"
|
||||||
|
animation={`${glowPulse} 6s ease-in-out infinite 2s`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 底部图例 - 毛玻璃风格 */}
|
||||||
<Flex
|
<Flex
|
||||||
position="absolute"
|
position="absolute"
|
||||||
bottom={4}
|
bottom={4}
|
||||||
@@ -1370,7 +1353,8 @@ const ForceGraphView = ({
|
|||||||
onEvents={onChartEvents}
|
onEvents={onChartEvents}
|
||||||
opts={{ renderer: 'canvas' }}
|
opts={{ renderer: 'canvas' }}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
</VStack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -814,49 +814,10 @@ const HierarchyView = ({
|
|||||||
|
|
||||||
{/* 内容层 */}
|
{/* 内容层 */}
|
||||||
<Box position="relative" zIndex={1}>
|
<Box position="relative" zIndex={1}>
|
||||||
{/* 简化的工具栏 - 仅显示功能按钮 */}
|
{/* 面包屑导航 + 工具栏(同一行) */}
|
||||||
<Flex
|
|
||||||
justify="flex-end"
|
|
||||||
align="center"
|
|
||||||
mb={4}
|
|
||||||
gap={2}
|
|
||||||
>
|
|
||||||
{priceLoading && (
|
|
||||||
<Spinner size="sm" color="purple.300" mr={2} />
|
|
||||||
)}
|
|
||||||
<Tooltip label="刷新涨跌幅" placement="top">
|
|
||||||
<IconButton
|
|
||||||
size="sm"
|
|
||||||
icon={<FaSync />}
|
|
||||||
onClick={handleRefreshPrice}
|
|
||||||
isLoading={priceLoading}
|
|
||||||
bg="whiteAlpha.100"
|
|
||||||
color="white"
|
|
||||||
border="1px solid"
|
|
||||||
borderColor="whiteAlpha.200"
|
|
||||||
_hover={{ bg: 'whiteAlpha.200' }}
|
|
||||||
aria-label="刷新涨跌幅"
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip label={isFullscreen ? '退出全屏' : '全屏'} placement="top">
|
|
||||||
<IconButton
|
|
||||||
size="sm"
|
|
||||||
icon={isFullscreen ? <FaCompress /> : <FaExpand />}
|
|
||||||
onClick={toggleFullscreen}
|
|
||||||
bg="whiteAlpha.100"
|
|
||||||
color="white"
|
|
||||||
border="1px solid"
|
|
||||||
borderColor="whiteAlpha.200"
|
|
||||||
_hover={{ bg: 'whiteAlpha.200' }}
|
|
||||||
aria-label={isFullscreen ? '退出全屏' : '全屏'}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
{/* 面包屑导航 */}
|
|
||||||
<Flex
|
<Flex
|
||||||
align="center"
|
align="center"
|
||||||
|
justify="space-between"
|
||||||
mb={5}
|
mb={5}
|
||||||
p={3}
|
p={3}
|
||||||
bg="whiteAlpha.50"
|
bg="whiteAlpha.50"
|
||||||
@@ -864,31 +825,68 @@ const HierarchyView = ({
|
|||||||
borderRadius="2xl"
|
borderRadius="2xl"
|
||||||
border="1px solid"
|
border="1px solid"
|
||||||
borderColor="whiteAlpha.100"
|
borderColor="whiteAlpha.100"
|
||||||
flexWrap="wrap"
|
gap={2}
|
||||||
gap={1}
|
|
||||||
>
|
>
|
||||||
{breadcrumbs.map((crumb, index) => (
|
{/* 左侧:面包屑导航 */}
|
||||||
<React.Fragment key={index}>
|
<Flex align="center" flexWrap="wrap" gap={1} flex={1}>
|
||||||
{index > 0 && (
|
{breadcrumbs.map((crumb, index) => (
|
||||||
<Icon as={FaChevronRight} color="whiteAlpha.400" boxSize={3} mx={1} />
|
<React.Fragment key={index}>
|
||||||
)}
|
{index > 0 && (
|
||||||
<Button
|
<Icon as={FaChevronRight} color="whiteAlpha.400" boxSize={3} mx={1} />
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
bg={index === breadcrumbs.length - 1 ? 'purple.500' : 'transparent'}
|
||||||
|
color={index === breadcrumbs.length - 1 ? 'white' : 'whiteAlpha.700'}
|
||||||
|
leftIcon={index === 0 ? <FaHome /> : undefined}
|
||||||
|
onClick={() => handleBreadcrumbClick(crumb, index)}
|
||||||
|
isDisabled={index === breadcrumbs.length - 1}
|
||||||
|
fontWeight={index === breadcrumbs.length - 1 ? 'bold' : 'medium'}
|
||||||
|
borderRadius="xl"
|
||||||
|
_hover={index !== breadcrumbs.length - 1 ? { bg: 'whiteAlpha.100' } : {}}
|
||||||
|
boxShadow={index === breadcrumbs.length - 1 ? '0 0 20px rgba(139, 92, 246, 0.5)' : 'none'}
|
||||||
|
>
|
||||||
|
{crumb.label}
|
||||||
|
</Button>
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
{/* 右侧:工具栏按钮 */}
|
||||||
|
<HStack spacing={2} flexShrink={0}>
|
||||||
|
{priceLoading && (
|
||||||
|
<Spinner size="sm" color="purple.300" />
|
||||||
|
)}
|
||||||
|
<Tooltip label="刷新涨跌幅" placement="top">
|
||||||
|
<IconButton
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
icon={<FaSync />}
|
||||||
bg={index === breadcrumbs.length - 1 ? 'purple.500' : 'transparent'}
|
onClick={handleRefreshPrice}
|
||||||
color={index === breadcrumbs.length - 1 ? 'white' : 'whiteAlpha.700'}
|
isLoading={priceLoading}
|
||||||
leftIcon={index === 0 ? <FaHome /> : undefined}
|
bg="whiteAlpha.100"
|
||||||
onClick={() => handleBreadcrumbClick(crumb, index)}
|
color="white"
|
||||||
isDisabled={index === breadcrumbs.length - 1}
|
border="1px solid"
|
||||||
fontWeight={index === breadcrumbs.length - 1 ? 'bold' : 'medium'}
|
borderColor="whiteAlpha.200"
|
||||||
borderRadius="xl"
|
_hover={{ bg: 'whiteAlpha.200' }}
|
||||||
_hover={index !== breadcrumbs.length - 1 ? { bg: 'whiteAlpha.100' } : {}}
|
aria-label="刷新涨跌幅"
|
||||||
boxShadow={index === breadcrumbs.length - 1 ? '0 0 20px rgba(139, 92, 246, 0.5)' : 'none'}
|
/>
|
||||||
>
|
</Tooltip>
|
||||||
{crumb.label}
|
|
||||||
</Button>
|
<Tooltip label={isFullscreen ? '退出全屏' : '全屏'} placement="top">
|
||||||
</React.Fragment>
|
<IconButton
|
||||||
))}
|
size="sm"
|
||||||
|
icon={isFullscreen ? <FaCompress /> : <FaExpand />}
|
||||||
|
onClick={toggleFullscreen}
|
||||||
|
bg="whiteAlpha.100"
|
||||||
|
color="white"
|
||||||
|
border="1px solid"
|
||||||
|
borderColor="whiteAlpha.200"
|
||||||
|
_hover={{ bg: 'whiteAlpha.200' }}
|
||||||
|
aria-label={isFullscreen ? '退出全屏' : '全屏'}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</HStack>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{/* 图例说明 */}
|
{/* 图例说明 */}
|
||||||
|
|||||||
@@ -1417,7 +1417,7 @@ const ConceptCenter = () => {
|
|||||||
align={{ base: 'stretch', lg: 'center' }}
|
align={{ base: 'stretch', lg: 'center' }}
|
||||||
gap={4}
|
gap={4}
|
||||||
>
|
>
|
||||||
{/* 使用通用日期选择器组件 */}
|
{/* 使用通用日期选择器组件 - 不显示最新日期提示,由下方单独渲染 */}
|
||||||
<TradeDatePicker
|
<TradeDatePicker
|
||||||
value={selectedDate}
|
value={selectedDate}
|
||||||
onChange={(date) => {
|
onChange={(date) => {
|
||||||
@@ -1432,9 +1432,10 @@ const ConceptCenter = () => {
|
|||||||
latestTradeDate={latestTradeDate}
|
latestTradeDate={latestTradeDate}
|
||||||
label="交易日期"
|
label="交易日期"
|
||||||
isDarkMode={true}
|
isDarkMode={true}
|
||||||
|
showLatestTradeDateTip={false}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 快捷按钮 - 深色主题,更有区分度 */}
|
{/* 快捷按钮 - 紧跟日期选择器 */}
|
||||||
<ButtonGroup size="sm" flexWrap="wrap" spacing={2}>
|
<ButtonGroup size="sm" flexWrap="wrap" spacing={2}>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleQuickDateSelect(0)}
|
onClick={() => handleQuickDateSelect(0)}
|
||||||
@@ -1505,6 +1506,26 @@ const ConceptCenter = () => {
|
|||||||
一月前
|
一月前
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|
||||||
|
{/* 最新交易日期提示 - 靠右显示 */}
|
||||||
|
{latestTradeDate && (
|
||||||
|
<Tooltip label="数据库中最新的交易日期">
|
||||||
|
<HStack
|
||||||
|
spacing={1.5}
|
||||||
|
ml="auto"
|
||||||
|
px={2}
|
||||||
|
py={1}
|
||||||
|
opacity={0.7}
|
||||||
|
_hover={{ opacity: 1 }}
|
||||||
|
transition="opacity 0.2s"
|
||||||
|
>
|
||||||
|
<Icon as={InfoIcon} color="blue.300" boxSize={3} />
|
||||||
|
<Text fontSize="xs" color="blue.200">
|
||||||
|
数据更新至 {latestTradeDate.toLocaleDateString('zh-CN')}
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@@ -1752,52 +1773,55 @@ const ConceptCenter = () => {
|
|||||||
align={{ base: 'stretch', md: 'center' }}
|
align={{ base: 'stretch', md: 'center' }}
|
||||||
gap={4}
|
gap={4}
|
||||||
>
|
>
|
||||||
<HStack spacing={4} align="center">
|
{/* 排序方式 - 仅在列表视图显示 */}
|
||||||
<Icon as={FaTags} boxSize={4} color="purple.300" />
|
{viewMode === 'list' && (
|
||||||
<Text fontWeight="bold" color="white">排序方式:</Text>
|
<HStack spacing={4} align="center">
|
||||||
<Select
|
<Icon as={FaTags} boxSize={4} color="purple.300" />
|
||||||
value={sortBy}
|
<Text fontWeight="bold" color="white">排序方式:</Text>
|
||||||
onChange={(e) => handleSortChange(e.target.value)}
|
<Select
|
||||||
width="200px"
|
value={sortBy}
|
||||||
focusBorderColor="purple.400"
|
onChange={(e) => handleSortChange(e.target.value)}
|
||||||
borderColor="whiteAlpha.300"
|
width="200px"
|
||||||
borderRadius="lg"
|
focusBorderColor="purple.400"
|
||||||
fontWeight="medium"
|
borderColor="whiteAlpha.300"
|
||||||
color="white"
|
borderRadius="lg"
|
||||||
bg="whiteAlpha.50"
|
fontWeight="medium"
|
||||||
_hover={{ borderColor: 'purple.400' }}
|
color="white"
|
||||||
sx={{
|
bg="whiteAlpha.50"
|
||||||
option: {
|
_hover={{ borderColor: 'purple.400' }}
|
||||||
bg: 'gray.800',
|
sx={{
|
||||||
color: 'white',
|
option: {
|
||||||
},
|
bg: 'gray.800',
|
||||||
}}
|
color: 'white',
|
||||||
>
|
},
|
||||||
<option value="change_pct">涨跌幅</option>
|
}}
|
||||||
<option value="_score">相关度</option>
|
>
|
||||||
<option value="stock_count">股票数量</option>
|
<option value="change_pct">涨跌幅</option>
|
||||||
<option value="outbreak_date">爆发日期</option>
|
<option value="_score">相关度</option>
|
||||||
</Select>
|
<option value="stock_count">股票数量</option>
|
||||||
{searchQuery && sortBy === '_score' && (
|
<option value="outbreak_date">爆发日期</option>
|
||||||
<Tooltip label="搜索时自动切换到相关度排序,以显示最匹配的结果。您也可以手动切换其他排序方式。">
|
</Select>
|
||||||
<HStack
|
{searchQuery && sortBy === '_score' && (
|
||||||
spacing={1}
|
<Tooltip label="搜索时自动切换到相关度排序,以显示最匹配的结果。您也可以手动切换其他排序方式。">
|
||||||
bg="blue.500"
|
<HStack
|
||||||
px={3}
|
spacing={1}
|
||||||
py={1}
|
bg="blue.500"
|
||||||
borderRadius="full"
|
px={3}
|
||||||
boxShadow="0 0 10px rgba(59, 130, 246, 0.4)"
|
py={1}
|
||||||
>
|
borderRadius="full"
|
||||||
<Icon as={InfoIcon} color="white" boxSize={3} />
|
boxShadow="0 0 10px rgba(59, 130, 246, 0.4)"
|
||||||
<Text fontSize="xs" color="white" fontWeight="medium">
|
>
|
||||||
智能排序
|
<Icon as={InfoIcon} color="white" boxSize={3} />
|
||||||
</Text>
|
<Text fontSize="xs" color="white" fontWeight="medium">
|
||||||
</HStack>
|
智能排序
|
||||||
</Tooltip>
|
</Text>
|
||||||
)}
|
</HStack>
|
||||||
</HStack>
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</HStack>
|
||||||
|
)}
|
||||||
|
|
||||||
<ButtonGroup size="sm" isAttached variant="outline">
|
<ButtonGroup size="sm" isAttached variant="outline" ml={viewMode !== 'list' ? 'auto' : undefined}>
|
||||||
<Tooltip label="概念矩形树图" placement="top">
|
<Tooltip label="概念矩形树图" placement="top">
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<FaCube />}
|
icon={<FaCube />}
|
||||||
|
|||||||
@@ -297,15 +297,17 @@ const SectorHeatMap = ({ data }) => {
|
|||||||
rx="8"
|
rx="8"
|
||||||
style={{
|
style={{
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
transition: 'all 0.3s'
|
transition: 'all 0.2s ease-in-out'
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
e.target.style.opacity = '0.8';
|
e.target.style.stroke = '#FFD700';
|
||||||
e.target.style.transform = 'scale(1.05)';
|
e.target.style.strokeWidth = '4';
|
||||||
|
e.target.style.filter = 'brightness(1.2) drop-shadow(0 0 8px rgba(255, 215, 0, 0.6))';
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
e.target.style.opacity = '1';
|
e.target.style.stroke = '#fff';
|
||||||
e.target.style.transform = 'scale(1)';
|
e.target.style.strokeWidth = '2';
|
||||||
|
e.target.style.filter = 'none';
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<title>{`${sector.name}: ${sector.count}只涨停`}</title>
|
<title>{`${sector.name}: ${sector.count}只涨停`}</title>
|
||||||
|
|||||||
Reference in New Issue
Block a user