updated
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useState, useEffect } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Card,
|
||||
@@ -36,9 +36,7 @@ import {
|
||||
WrapItem,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import { getFormattedTextProps } from '../../../utils/textUtils';
|
||||
import { ExternalLinkIcon } from '@chakra-ui/icons';
|
||||
import './WordCloud.css';
|
||||
import {
|
||||
BarChart, Bar,
|
||||
PieChart, Pie, Cell,
|
||||
@@ -50,7 +48,7 @@ import {
|
||||
Treemap,
|
||||
Area, AreaChart,
|
||||
} from 'recharts';
|
||||
import ReactWordcloud from 'react-wordcloud';
|
||||
|
||||
// 颜色配置
|
||||
const CHART_COLORS = [
|
||||
'#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEEAD',
|
||||
@@ -69,34 +67,70 @@ const WordCloud = ({ data }) => {
|
||||
);
|
||||
}
|
||||
|
||||
const words = data.slice(0, 100).map(item => ({
|
||||
text: item.name || item.text,
|
||||
value: item.value || item.count || 1
|
||||
const treemapData = data.slice(0, 30).map((item, index) => ({
|
||||
name: item.name,
|
||||
size: item.value,
|
||||
color: CHART_COLORS[index % CHART_COLORS.length]
|
||||
}));
|
||||
|
||||
const options = {
|
||||
rotations: 2,
|
||||
rotationAngles: [-90, 0],
|
||||
fontFamily: 'Microsoft YaHei, sans-serif',
|
||||
fontSizes: [16, 80],
|
||||
fontWeight: 'bold',
|
||||
padding: 3,
|
||||
scale: 'sqrt',
|
||||
};
|
||||
const CustomContent = (props) => {
|
||||
const { x, y, width, height, name, size, color } = props;
|
||||
const fontSize = Math.min(Math.max(Math.sqrt(width * height) / 4, 10), 24);
|
||||
|
||||
const callbacks = {
|
||||
getWordColor: () => {
|
||||
const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEEAD'];
|
||||
return colors[Math.floor(Math.random() * colors.length)];
|
||||
}
|
||||
if (width < 30 || height < 20) return null;
|
||||
|
||||
return (
|
||||
<g>
|
||||
<rect
|
||||
x={x}
|
||||
y={y}
|
||||
width={width}
|
||||
height={height}
|
||||
style={{
|
||||
fill: color,
|
||||
stroke: '#fff',
|
||||
strokeWidth: 2,
|
||||
strokeOpacity: 1,
|
||||
}}
|
||||
/>
|
||||
<text
|
||||
x={x + width / 2}
|
||||
y={y + height / 2}
|
||||
textAnchor="middle"
|
||||
dominantBaseline="central"
|
||||
fill="white"
|
||||
fontSize={fontSize}
|
||||
fontWeight="bold"
|
||||
>
|
||||
{name}
|
||||
</text>
|
||||
{width > 50 && height > 40 && (
|
||||
<text
|
||||
x={x + width / 2}
|
||||
y={y + height / 2 + fontSize + 2}
|
||||
textAnchor="middle"
|
||||
dominantBaseline="central"
|
||||
fill="white"
|
||||
fontSize={fontSize * 0.6}
|
||||
opacity={0.8}
|
||||
>
|
||||
{size}
|
||||
</text>
|
||||
)}
|
||||
</g>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactWordcloud
|
||||
words={words}
|
||||
options={options}
|
||||
callbacks={callbacks}
|
||||
/>
|
||||
<ResponsiveContainer width="100%" height={400}>
|
||||
<Treemap
|
||||
data={treemapData}
|
||||
dataKey="size"
|
||||
aspectRatio={4 / 3}
|
||||
stroke="#fff"
|
||||
content={<CustomContent />}
|
||||
/>
|
||||
</ResponsiveContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -576,9 +610,7 @@ export const StockDetailModal = ({ isOpen, onClose, selectedStock }) => {
|
||||
<Box>
|
||||
<Text fontWeight="bold" mb={2}>详细分析</Text>
|
||||
<Box p={4} bg="gray.50" borderRadius="md">
|
||||
<Text {...getFormattedTextProps(selectedStock.summary).props}>
|
||||
{getFormattedTextProps(selectedStock.summary).children}
|
||||
</Text>
|
||||
<Text whiteSpace="pre-wrap">{selectedStock.summary}</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user