style: 移除 Tab 导航和卡片内部左右 padding

- TabNavigation/SubTabContainer: 移除左侧 padding (pl=0)
- BusinessStructureCard/BusinessSegmentsCard: 移除 CardBody 左右 padding
- BusinessTreeItem: 黑金主题样式优化

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-12-12 13:13:34 +08:00
parent e049429b09
commit 7c7c70c4d9
6 changed files with 170 additions and 166 deletions

View File

@@ -3,6 +3,7 @@
*
* 递归显示业务结构层级
* 使用位置:业务结构分析卡片
* 黑金主题风格
*/
import React from 'react';
@@ -10,9 +11,17 @@ import { Box, HStack, VStack, Text, Badge, Tag, TagLabel } from '@chakra-ui/reac
import { formatPercentage, formatBusinessRevenue } from '@utils/priceFormatters';
import type { BusinessTreeItemProps } from '../types';
const BusinessTreeItem: React.FC<BusinessTreeItemProps> = ({ business, depth = 0 }) => {
const bgColor = 'gray.50';
// 黑金主题配置
const THEME = {
bg: 'gray.700',
gold: '#D4AF37',
goldLight: '#F0D78C',
textPrimary: '#D4AF37',
textSecondary: 'gray.400',
border: 'rgba(212, 175, 55, 0.5)',
};
const BusinessTreeItem: React.FC<BusinessTreeItemProps> = ({ business, depth = 0 }) => {
// 获取营收显示
const getRevenueDisplay = (): string => {
const revenue = business.revenue || business.financial_metrics?.revenue;
@@ -27,40 +36,39 @@ const BusinessTreeItem: React.FC<BusinessTreeItemProps> = ({ business, depth = 0
<Box
ml={depth * 6}
p={3}
bg={bgColor}
bg={THEME.bg}
borderLeft={depth > 0 ? '4px solid' : 'none'}
borderLeftColor="blue.400"
borderLeftColor={THEME.gold}
borderRadius="md"
mb={2}
_hover={{ shadow: 'md' }}
_hover={{ shadow: 'md', bg: 'gray.600' }}
transition="all 0.2s"
>
<HStack justify="space-between">
<VStack align="start" spacing={1}>
<HStack>
<Text fontWeight="bold" fontSize={depth === 0 ? 'md' : 'sm'}>
<Text fontWeight="bold" fontSize={depth === 0 ? 'md' : 'sm'} color={THEME.textPrimary}>
{business.business_name}
</Text>
{business.financial_metrics?.revenue_ratio &&
business.financial_metrics.revenue_ratio > 30 && (
<Badge colorScheme="purple" size="sm">
<Badge bg={THEME.gold} color="gray.900" size="sm">
</Badge>
)}
</HStack>
<HStack spacing={4} flexWrap="wrap">
<Tag size="sm" variant="subtle">
<Tag size="sm" bg="gray.600" color={THEME.textPrimary}>
: {formatPercentage(business.financial_metrics?.revenue_ratio)}
</Tag>
<Tag size="sm" variant="subtle">
<Tag size="sm" bg="gray.600" color={THEME.textPrimary}>
: {formatPercentage(business.financial_metrics?.gross_margin)}
</Tag>
{business.growth_metrics?.revenue_growth !== undefined && (
<Tag
size="sm"
colorScheme={
business.growth_metrics.revenue_growth > 0 ? 'red' : 'green'
}
bg={business.growth_metrics.revenue_growth > 0 ? 'red.600' : 'green.600'}
color="white"
>
<TagLabel>
: {business.growth_metrics.revenue_growth > 0 ? '+' : ''}
@@ -71,10 +79,10 @@ const BusinessTreeItem: React.FC<BusinessTreeItemProps> = ({ business, depth = 0
</HStack>
</VStack>
<VStack align="end" spacing={0}>
<Text fontSize="lg" fontWeight="bold" color="blue.500">
<Text fontSize="lg" fontWeight="bold" color={THEME.gold}>
{getRevenueDisplay()}
</Text>
<Text fontSize="xs" color="gray.500">
<Text fontSize="xs" color={THEME.textSecondary}>
</Text>
</VStack>

View File

@@ -2,6 +2,7 @@
* 业务板块详情卡片
*
* 显示公司各业务板块的详细信息
* 黑金主题风格
*/
import React from 'react';
@@ -20,9 +21,19 @@ import {
Button,
} from '@chakra-ui/react';
import { FaIndustry, FaExpandAlt, FaCompressAlt } from 'react-icons/fa';
import { DisclaimerBox } from '../atoms';
import type { BusinessSegment } from '../types';
// 黑金主题配置
const THEME = {
cardBg: 'gray.800',
innerCardBg: 'gray.700',
gold: '#D4AF37',
goldLight: '#F0D78C',
textPrimary: '#D4AF37',
textSecondary: 'gray.400',
border: 'rgba(212, 175, 55, 0.3)',
};
interface BusinessSegmentsCardProps {
businessSegments: BusinessSegment[];
expandedSegments: Record<number, boolean>;
@@ -34,31 +45,29 @@ const BusinessSegmentsCard: React.FC<BusinessSegmentsCardProps> = ({
businessSegments,
expandedSegments,
onToggleSegment,
cardBg,
}) => {
if (!businessSegments || businessSegments.length === 0) return null;
return (
<Card bg={cardBg} shadow="md">
<Card bg={THEME.cardBg} shadow="md">
<CardHeader>
<HStack>
<Icon as={FaIndustry} color="indigo.500" />
<Heading size="sm"></Heading>
<Badge>{businessSegments.length} </Badge>
<Icon as={FaIndustry} color={THEME.gold} />
<Heading size="sm" color={THEME.textPrimary}></Heading>
<Badge bg={THEME.gold} color="gray.900">{businessSegments.length} </Badge>
</HStack>
</CardHeader>
<CardBody>
<DisclaimerBox />
<CardBody px={2}>
<SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing={4}>
{businessSegments.map((segment, idx) => {
const isExpanded = expandedSegments[idx];
return (
<Card key={idx} variant="outline">
<CardBody>
<Card key={idx} bg={THEME.innerCardBg}>
<CardBody px={2}>
<VStack align="stretch" spacing={3}>
<HStack justify="space-between">
<Text fontWeight="bold" fontSize="md">
<Text fontWeight="bold" fontSize="md" color={THEME.textPrimary}>
{segment.segment_name}
</Text>
<Button
@@ -68,18 +77,20 @@ const BusinessSegmentsCard: React.FC<BusinessSegmentsCardProps> = ({
<Icon as={isExpanded ? FaCompressAlt : FaExpandAlt} />
}
onClick={() => onToggleSegment(idx)}
colorScheme="blue"
color={THEME.gold}
_hover={{ bg: 'gray.600' }}
>
{isExpanded ? '折叠' : '展开'}
</Button>
</HStack>
<Box>
<Text fontSize="xs" color="gray.500" mb={1}>
<Text fontSize="xs" color={THEME.textSecondary} mb={1}>
</Text>
<Text
fontSize="sm"
color={THEME.textPrimary}
noOfLines={isExpanded ? undefined : 3}
>
{segment.segment_description || '暂无描述'}
@@ -87,11 +98,12 @@ const BusinessSegmentsCard: React.FC<BusinessSegmentsCardProps> = ({
</Box>
<Box>
<Text fontSize="xs" color="gray.500" mb={1}>
<Text fontSize="xs" color={THEME.textSecondary} mb={1}>
</Text>
<Text
fontSize="sm"
color={THEME.textPrimary}
noOfLines={isExpanded ? undefined : 2}
>
{segment.competitive_position || '暂无数据'}
@@ -99,13 +111,13 @@ const BusinessSegmentsCard: React.FC<BusinessSegmentsCardProps> = ({
</Box>
<Box>
<Text fontSize="xs" color="gray.500" mb={1}>
<Text fontSize="xs" color={THEME.textSecondary} mb={1}>
</Text>
<Text
fontSize="sm"
noOfLines={isExpanded ? undefined : 2}
color="blue.600"
color={THEME.goldLight}
>
{segment.future_potential || '暂无数据'}
</Text>
@@ -113,10 +125,10 @@ const BusinessSegmentsCard: React.FC<BusinessSegmentsCardProps> = ({
{isExpanded && segment.key_products && (
<Box>
<Text fontSize="xs" color="gray.500" mb={1}>
<Text fontSize="xs" color={THEME.textSecondary} mb={1}>
</Text>
<Text fontSize="sm" color="green.600">
<Text fontSize="sm" color="green.300">
{segment.key_products}
</Text>
</Box>
@@ -124,10 +136,10 @@ const BusinessSegmentsCard: React.FC<BusinessSegmentsCardProps> = ({
{isExpanded && segment.market_share !== undefined && (
<Box>
<Text fontSize="xs" color="gray.500" mb={1}>
<Text fontSize="xs" color={THEME.textSecondary} mb={1}>
</Text>
<Badge colorScheme="purple" fontSize="sm">
<Badge bg="purple.600" color="white" fontSize="sm">
{segment.market_share}%
</Badge>
</Box>
@@ -135,10 +147,10 @@ const BusinessSegmentsCard: React.FC<BusinessSegmentsCardProps> = ({
{isExpanded && segment.revenue_contribution !== undefined && (
<Box>
<Text fontSize="xs" color="gray.500" mb={1}>
<Text fontSize="xs" color={THEME.textSecondary} mb={1}>
</Text>
<Badge colorScheme="orange" fontSize="sm">
<Badge bg={THEME.gold} color="gray.900" fontSize="sm">
{segment.revenue_contribution}%
</Badge>
</Box>

View File

@@ -2,6 +2,7 @@
* 业务结构分析卡片
*
* 显示公司业务结构树形图
* 黑金主题风格
*/
import React from 'react';
@@ -16,9 +17,17 @@ import {
Icon,
} from '@chakra-ui/react';
import { FaChartPie } from 'react-icons/fa';
import { DisclaimerBox, BusinessTreeItem } from '../atoms';
import { BusinessTreeItem } from '../atoms';
import type { BusinessStructure } from '../types';
// 黑金主题配置
const THEME = {
cardBg: 'gray.800',
gold: '#D4AF37',
textPrimary: '#D4AF37',
border: 'rgba(212, 175, 55, 0.3)',
};
interface BusinessStructureCardProps {
businessStructure: BusinessStructure[];
cardBg?: string;
@@ -26,21 +35,19 @@ interface BusinessStructureCardProps {
const BusinessStructureCard: React.FC<BusinessStructureCardProps> = ({
businessStructure,
cardBg,
}) => {
if (!businessStructure || businessStructure.length === 0) return null;
return (
<Card bg={cardBg} shadow="md">
<Card bg={THEME.cardBg} shadow="md">
<CardHeader>
<HStack>
<Icon as={FaChartPie} color="purple.500" />
<Heading size="sm"></Heading>
<Badge>{businessStructure[0]?.report_period}</Badge>
<Icon as={FaChartPie} color={THEME.gold} />
<Heading size="sm" color={THEME.textPrimary}></Heading>
<Badge bg={THEME.gold} color="gray.900">{businessStructure[0]?.report_period}</Badge>
</HStack>
</CardHeader>
<CardBody>
<DisclaimerBox />
<CardBody px={0}>
<VStack spacing={3} align="stretch">
{businessStructure.map((business, idx) => (
<BusinessTreeItem