feat: DynamicNewsDetailPanel 支持无头部模式和精简模式优化

新增功能:
- 添加 showHeader prop 控制头部显示/隐藏(默认 true)
- 无头部模式下显示 CompactMetaBar 精简信息栏(右上角浮动)
- 相关股票支持精简模式(使用 CompactStockItem + Wrap 布局)
- 添加 showModeToggle 和 simpleContent props 到相关股票模块

Bug 修复和优化:
- 修复 isStocksOpen 初始值依赖未就绪变量的问题(改为 false)
- 优化股票加载逻辑:PRO 和 MAX 会员都默认展开和自动加载
- 更新日志文案:从"PRO会员"改为"PRO/MAX会员"

导入调整:
- 添加 Wrap, WrapItem(用于精简模式布局)
- 添加 CompactMetaBar(无头部模式信息栏)
- 添加 CompactStockItem(精简模式股票卡片)

🤖 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:48:08 +08:00
parent 7b49062986
commit 00aabfacea

View File

@@ -21,9 +21,11 @@ import { useEventStocks } from '../StockDetailPanel/hooks/useEventStocks';
import { toggleEventFollow, selectEventFollowStatus } from '../../../../store/slices/communityDataSlice';
import { useAuth } from '../../../../contexts/AuthContext';
import EventHeaderInfo from './EventHeaderInfo';
import CompactMetaBar from './CompactMetaBar';
import EventDescriptionSection from './EventDescriptionSection';
import RelatedConceptsSection from './RelatedConceptsSection';
import RelatedStocksSection from './RelatedStocksSection';
import CompactStockItem from './CompactStockItem';
import CollapsibleSection from './CollapsibleSection';
import HistoricalEvents from '../../../EventDetail/components/HistoricalEvents';
import TransmissionChainAnalysis from '../../../EventDetail/components/TransmissionChainAnalysis';
@@ -114,8 +116,8 @@ const DynamicNewsDetailPanel = ({ event, showHeader = true }) => {
const canAccessTransmission = hasAccess('max');
// 子区块折叠状态管理 + 加载追踪
// PRO 会员的相关股票默认展开
const [isStocksOpen, setIsStocksOpen] = useState(canAccessStocks && userTier === 'pro');
// 初始值为 false由 useEffect 根据权限动态设置
const [isStocksOpen, setIsStocksOpen] = useState(false);
const [hasLoadedStocks, setHasLoadedStocks] = useState(false);
const [isConceptsOpen, setIsConceptsOpen] = useState(false);
@@ -202,14 +204,18 @@ const DynamicNewsDetailPanel = ({ event, showHeader = true }) => {
// 🎯 加载事件详情(增加浏览量)
loadEventDetail();
// PRO 会员的相关股票默认展开,其他情况收起
const shouldOpenStocks = canAccessStocks && userTier === 'pro';
// PRO 和 MAX 会员的相关股票默认展开,其他情况收起
const shouldOpenStocks = canAccessStocks;
setIsStocksOpen(shouldOpenStocks);
setHasLoadedStocks(false);
// PRO 会员默认展开时,自动加载股票数据
if (shouldOpenStocks) {
console.log('%c📊 [PRO会员] 自动加载相关股票数据', 'color: #10B981; font-weight: bold;', { eventId: event?.id });
// PRO 和 MAX 会员自动加载股票数据(无论是否展开)
const shouldLoadStocks = canAccessStocks; // PRO 或 MAX 都有权限
if (shouldLoadStocks) {
console.log('%c📊 [PRO/MAX会员] 自动加载相关股票数据', 'color: #10B981; font-weight: bold;', {
eventId: event?.id,
userTier
});
loadStocksData();
setHasLoadedStocks(true);
}
@@ -281,9 +287,21 @@ const DynamicNewsDetailPanel = ({ event, showHeader = true }) => {
return (
<Card bg={cardBg} borderColor={borderColor} borderWidth="1px">
<CardBody>
<CardBody position="relative">
{/* 无头部模式:显示右上角精简信息栏 */}
{!showHeader && (
<CompactMetaBar
event={fullEventDetail || event}
importance={importance}
isFollowing={isFollowing}
followerCount={followerCount}
onToggleFollow={handleToggleFollow}
/>
)}
<VStack align="stretch" spacing={3}>
{/* 头部信息区 - 优先使用完整详情数据(包含最新浏览量) */}
{/* 头部信息区 - 优先使用完整详情数据(包含最新浏览量) - 可配置显示/隐藏 */}
{showHeader && (
<EventHeaderInfo
event={fullEventDetail || event}
importance={importance}
@@ -291,11 +309,12 @@ const DynamicNewsDetailPanel = ({ event, showHeader = true }) => {
followerCount={followerCount}
onToggleFollow={handleToggleFollow}
/>
)}
{/* 事件描述 */}
<EventDescriptionSection description={event.description} />
{/* 相关股票(可折叠) - 懒加载 - 需要 PRO 权限 */}
{/* 相关股票(可折叠) - 懒加载 - 需要 PRO 权限 - 支持精简/详细模式 */}
<CollapsibleSection
title="相关股票"
isOpen={isStocksOpen}
@@ -309,6 +328,27 @@ const DynamicNewsDetailPanel = ({ event, showHeader = true }) => {
})()}
isLocked={!canAccessStocks}
onLockedClick={() => handleLockedClick('相关股票', 'pro')}
showModeToggle={canAccessStocks}
defaultMode="detailed"
simpleContent={
loading.stocks || loading.quotes ? (
<Center py={2}>
<Spinner size="sm" color="blue.500" />
<Text ml={2} color={textColor} fontSize="sm">加载股票数据中...</Text>
</Center>
) : (
<Wrap spacing={4}>
{stocks?.map((stock, index) => (
<WrapItem key={index}>
<CompactStockItem
stock={stock}
quote={quotes[stock.stock_code]}
/>
</WrapItem>
))}
</Wrap>
)
}
>
{loading.stocks || loading.quotes ? (
<Center py={4}>