feat(DeepAnalysis): 竞争地位分析增加行业排名弹窗

- CompetitiveAnalysisCard 新增 Modal 弹窗展示行业排名详情
  - 点击 Badge 或查看详情按钮可打开弹窗
  - 弹窗采用黑金主题样式
  - StrategyTab 移除独立的 IndustryRankingView 展示
This commit is contained in:
zdl
2025-12-16 16:33:45 +08:00
parent 6a4c475d3a
commit 2eb2a22495
2 changed files with 128 additions and 59 deletions

View File

@@ -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>
</>
);
}
);

View File

@@ -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>