feat(DeepAnalysis): 竞争地位分析增加行业排名弹窗
- CompetitiveAnalysisCard 新增 Modal 弹窗展示行业排名详情 - 点击 Badge 或查看详情按钮可打开弹窗 - 弹窗采用黑金主题样式 - StrategyTab 移除独立的 IndustryRankingView 展示
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
* 竞争地位分析卡片
|
||||
*
|
||||
* 显示竞争力评分、雷达图和竞争分析
|
||||
* 包含行业排名弹窗功能
|
||||
*/
|
||||
|
||||
import React, { memo, useMemo } from 'react';
|
||||
@@ -22,6 +23,14 @@ import {
|
||||
Icon,
|
||||
Divider,
|
||||
SimpleGrid,
|
||||
Button,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import {
|
||||
FaTrophy,
|
||||
@@ -33,11 +42,32 @@ import {
|
||||
FaShieldAlt,
|
||||
FaRocket,
|
||||
FaUsers,
|
||||
FaExternalLinkAlt,
|
||||
} from 'react-icons/fa';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import { ScoreBar } from '../atoms';
|
||||
import { getRadarChartOption } from '../utils/chartOptions';
|
||||
import type { ComprehensiveData, CompetitivePosition } from '../types';
|
||||
import { IndustryRankingView } from '../../../FinancialPanorama/components';
|
||||
import type { ComprehensiveData, CompetitivePosition, IndustryRankData } from '../types';
|
||||
|
||||
// 黑金主题弹窗样式
|
||||
const MODAL_STYLES = {
|
||||
content: {
|
||||
bg: 'gray.900',
|
||||
borderColor: 'rgba(212, 175, 55, 0.3)',
|
||||
borderWidth: '1px',
|
||||
maxW: '900px',
|
||||
},
|
||||
header: {
|
||||
color: 'yellow.500',
|
||||
borderBottomColor: 'rgba(212, 175, 55, 0.2)',
|
||||
borderBottomWidth: '1px',
|
||||
},
|
||||
closeButton: {
|
||||
color: 'yellow.500',
|
||||
_hover: { bg: 'rgba(212, 175, 55, 0.1)' },
|
||||
},
|
||||
} as const;
|
||||
|
||||
// 样式常量 - 避免每次渲染创建新对象
|
||||
const CARD_STYLES = {
|
||||
@@ -57,6 +87,7 @@ const CHART_STYLE = { height: '320px' } as const;
|
||||
|
||||
interface CompetitiveAnalysisCardProps {
|
||||
comprehensiveData: ComprehensiveData;
|
||||
industryRankData?: IndustryRankData[];
|
||||
}
|
||||
|
||||
// 竞争对手标签组件
|
||||
@@ -141,8 +172,10 @@ const AdvantagesSection = memo<AdvantagesSectionProps>(
|
||||
AdvantagesSection.displayName = 'AdvantagesSection';
|
||||
|
||||
const CompetitiveAnalysisCard: React.FC<CompetitiveAnalysisCardProps> = memo(
|
||||
({ comprehensiveData }) => {
|
||||
({ comprehensiveData, industryRankData }) => {
|
||||
const competitivePosition = comprehensiveData.competitive_position;
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
if (!competitivePosition) return null;
|
||||
|
||||
// 缓存雷达图配置
|
||||
@@ -160,7 +193,11 @@ const CompetitiveAnalysisCard: React.FC<CompetitiveAnalysisCardProps> = memo(
|
||||
[competitivePosition.analysis?.main_competitors]
|
||||
);
|
||||
|
||||
// 判断是否有行业排名数据可展示
|
||||
const hasIndustryRankData = industryRankData && industryRankData.length > 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card {...CARD_STYLES}>
|
||||
<CardHeader>
|
||||
<HStack>
|
||||
@@ -173,11 +210,26 @@ const CompetitiveAnalysisCard: React.FC<CompetitiveAnalysisCardProps> = memo(
|
||||
border="1px solid"
|
||||
borderColor="yellow.600"
|
||||
color="yellow.500"
|
||||
cursor={hasIndustryRankData ? 'pointer' : 'default'}
|
||||
onClick={hasIndustryRankData ? onOpen : undefined}
|
||||
_hover={hasIndustryRankData ? { bg: 'rgba(212, 175, 55, 0.1)' } : undefined}
|
||||
>
|
||||
行业排名 {competitivePosition.ranking.industry_rank}/
|
||||
{competitivePosition.ranking.total_companies}
|
||||
</Badge>
|
||||
)}
|
||||
{hasIndustryRankData && (
|
||||
<Button
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
color="yellow.500"
|
||||
rightIcon={<Icon as={FaExternalLinkAlt} boxSize={3} />}
|
||||
onClick={onOpen}
|
||||
_hover={{ bg: 'rgba(212, 175, 55, 0.1)' }}
|
||||
>
|
||||
查看详情
|
||||
</Button>
|
||||
)}
|
||||
</HStack>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
@@ -210,6 +262,30 @@ const CompetitiveAnalysisCard: React.FC<CompetitiveAnalysisCardProps> = memo(
|
||||
/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
{/* 行业排名弹窗 - 黑金主题 */}
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="4xl" scrollBehavior="inside">
|
||||
<ModalOverlay bg="blackAlpha.700" />
|
||||
<ModalContent {...MODAL_STYLES.content}>
|
||||
<ModalHeader {...MODAL_STYLES.header}>
|
||||
<HStack>
|
||||
<Icon as={FaTrophy} color="yellow.500" />
|
||||
<Text>行业排名详情</Text>
|
||||
</HStack>
|
||||
</ModalHeader>
|
||||
<ModalCloseButton {...MODAL_STYLES.closeButton} />
|
||||
<ModalBody py={4}>
|
||||
{hasIndustryRankData && (
|
||||
<IndustryRankingView
|
||||
industryRank={industryRankData}
|
||||
bgColor="gray.800"
|
||||
borderColor="rgba(212, 175, 55, 0.3)"
|
||||
/>
|
||||
)}
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 战略分析 Tab
|
||||
*
|
||||
* 包含:核心定位 + 战略分析 + 竞争地位分析 + 行业排名
|
||||
* 包含:核心定位 + 战略分析 + 竞争地位分析(含行业排名弹窗)
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
StrategyAnalysisCard,
|
||||
CompetitiveAnalysisCard,
|
||||
} from '../components';
|
||||
import { IndustryRankingView } from '../../../FinancialPanorama/components';
|
||||
import type { ComprehensiveData, IndustryRankData } from '../types';
|
||||
|
||||
export interface StrategyTabProps {
|
||||
@@ -43,17 +42,11 @@ const StrategyTab: React.FC<StrategyTabProps> = memo(({
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 竞争地位分析 */}
|
||||
{/* 竞争地位分析(包含行业排名弹窗) */}
|
||||
{comprehensiveData?.competitive_position && (
|
||||
<CompetitiveAnalysisCard comprehensiveData={comprehensiveData} />
|
||||
)}
|
||||
|
||||
{/* 行业排名 */}
|
||||
{industryRankData && industryRankData.length > 0 && (
|
||||
<IndustryRankingView
|
||||
industryRank={industryRankData}
|
||||
bgColor="white"
|
||||
borderColor="gray.200"
|
||||
<CompetitiveAnalysisCard
|
||||
comprehensiveData={comprehensiveData}
|
||||
industryRankData={industryRankData}
|
||||
/>
|
||||
)}
|
||||
</TabPanelContainer>
|
||||
|
||||
Reference in New Issue
Block a user