feat: RelatedConceptsSection 支持受控模式和优化

- 新增 isOpen, onToggle props 支持外部控制展开状态(受控模式)
- 添加 hasNoConcepts 判断,优化空数据处理逻辑
- 改进精简模式和详细模式的空状态显示
- 增强点击处理逻辑,支持受控/非受控两种模式

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-11-07 19:46:29 +08:00
parent b30cbd6c62
commit 4979293320
2 changed files with 54 additions and 27 deletions

View File

@@ -10,6 +10,8 @@ import {
Text,
Spinner,
Center,
Wrap,
WrapItem,
useColorModeValue,
useToast,
} from '@chakra-ui/react';
@@ -32,8 +34,9 @@ import SubscriptionUpgradeModal from '../../../../components/SubscriptionUpgrade
* 动态新闻详情面板主组件
* @param {Object} props
* @param {Object} props.event - 事件对象(包含详情数据)
* @param {boolean} props.showHeader - 是否显示头部信息(默认 true
*/
const DynamicNewsDetailPanel = ({ event }) => {
const DynamicNewsDetailPanel = ({ event, showHeader = true }) => {
const dispatch = useDispatch();
const { user } = useAuth();
const cardBg = useColorModeValue('white', 'gray.800');

View File

@@ -38,9 +38,13 @@ const RelatedConceptsSection = ({
eventTime,
subscriptionBadge = null,
isLocked = false,
onLockedClick = null
onLockedClick = null,
isOpen = undefined, // 新增:受控模式(外部控制展开状态)
onToggle = undefined // 新增:受控模式(外部控制展开回调)
}) => {
const [isExpanded, setIsExpanded] = useState(false);
// 使用外部 isOpen如果没有则使用内部 useState
const [internalExpanded, setInternalExpanded] = useState(false);
const isExpanded = onToggle !== undefined ? isOpen : internalExpanded;
const [concepts, setConcepts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
@@ -179,10 +183,8 @@ const RelatedConceptsSection = ({
);
}
// 如果没有概念,不渲染
if (!concepts || concepts.length === 0) {
return null;
}
// 判断是否有数据
const hasNoConcepts = !concepts || concepts.length === 0;
/**
* 根据相关度获取颜色(浅色背景 + 深色文字)
@@ -232,9 +234,12 @@ const RelatedConceptsSection = ({
// 如果被锁定且有回调函数,触发付费弹窗
if (isLocked && onLockedClick) {
onLockedClick();
} else if (onToggle !== undefined) {
// 受控模式:调用外部回调
onToggle();
} else {
// 否则正常展开/收起
setIsExpanded(!isExpanded);
// 非受控模式:使用内部状态
setInternalExpanded(!internalExpanded);
}
}}
>
@@ -249,6 +254,15 @@ const RelatedConceptsSection = ({
</Box>
{/* 简单模式:横向卡片列表(总是显示) */}
{hasNoConcepts ? (
<Box mb={isExpanded ? 3 : 0}>
{error ? (
<Text color="red.500" fontSize="sm">{error}</Text>
) : (
<Text color={textColor} fontSize="sm">暂无相关概念数据</Text>
)}
</Box>
) : (
<Flex gap={2} flexWrap="wrap" mb={isExpanded ? 3 : 0}>
{concepts.map((concept, index) => (
<SimpleConceptCard
@@ -259,11 +273,20 @@ const RelatedConceptsSection = ({
/>
))}
</Flex>
)}
{/* 详细模式:卡片网格(可折叠) */}
<Collapse in={isExpanded} animateOpacity>
{/* 详细概念卡片网格 */}
{hasNoConcepts ? (
<Box py={4}>
{error ? (
<Text color="red.500" fontSize="sm" textAlign="center">{error}</Text>
) : (
<Text color={textColor} fontSize="sm" textAlign="center">暂无详细数据</Text>
)}
</Box>
) : (
/* 详细概念卡片网格 */
<SimpleGrid columns={{ base: 1, md: 2 }} spacing={4}>
{concepts.map((concept, index) => (
<DetailedConceptCard
@@ -273,6 +296,7 @@ const RelatedConceptsSection = ({
/>
))}
</SimpleGrid>
)}
</Collapse>
</Box>
);