更新Company页面的UI为FUI风格

This commit is contained in:
2025-12-18 20:06:51 +08:00
parent bc319f63d0
commit a0388f73b0
5 changed files with 165 additions and 78 deletions

View File

@@ -26,7 +26,8 @@ import { getApiBase } from '@utils/apiConfig';
/**
* 相关概念区组件
* @param {Object} props
* @param {string} props.eventTitle - 事件标题(用于搜索概念
* @param {number} props.eventId - 事件ID(用于获取 related_concepts 表数据
* @param {string} props.eventTitle - 事件标题(备用,当 eventId 不存在时使用搜索)
* @param {string} props.effectiveTradingDate - 有效交易日期(涨跌幅数据日期)
* @param {string|Object} props.eventTime - 事件发生时间
* @param {React.ReactNode} props.subscriptionBadge - 订阅徽章组件(可选)
@@ -34,6 +35,7 @@ import { getApiBase } from '@utils/apiConfig';
* @param {Function} props.onLockedClick - 锁定时的点击回调(触发付费弹窗)
*/
const RelatedConceptsSection = ({
eventId,
eventTitle,
effectiveTradingDate,
eventTime,
@@ -57,6 +59,7 @@ const RelatedConceptsSection = ({
const textColor = useColorModeValue('gray.600', 'gray.400');
console.log('[RelatedConceptsSection] 组件渲染', {
eventId,
eventTitle,
effectiveTradingDate,
eventTime,
@@ -65,16 +68,76 @@ const RelatedConceptsSection = ({
error
});
// 搜索相关概念
// 获取相关概念 - 优先使用 eventId 从数据库获取
useEffect(() => {
const searchConcepts = async () => {
const fetchConcepts = async () => {
console.log('[RelatedConceptsSection] useEffect 触发', {
eventId,
eventTitle,
effectiveTradingDate
});
// 优先使用 eventId 获取数据库中的相关概念
if (eventId) {
try {
setLoading(true);
setError(null);
const apiUrl = `${getApiBase()}/api/events/${eventId}/concepts`;
console.log('[RelatedConceptsSection] 从数据库获取相关概念', { url: apiUrl });
const response = await fetch(apiUrl, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
credentials: 'include'
});
if (!response.ok) {
// 如果是 403说明需要订阅不是错误
if (response.status === 403) {
console.log('[RelatedConceptsSection] 需要订阅才能查看');
setConcepts([]);
setLoading(false);
return;
}
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('[RelatedConceptsSection] 数据库响应', data);
if (data.success && Array.isArray(data.data)) {
// 转换数据格式,使其与原有展示逻辑兼容
const formattedConcepts = data.data.map(item => ({
concept: item.concept,
reason: item.reason,
concept_code: item.concept_code,
// 保留原有字段以兼容 DetailedConceptCard
score: 1, // 数据库中的都是高相关度
description: item.reason, // reason 作为描述
stocks: [], // 暂无股票数据
stock_count: 0
}));
console.log('[RelatedConceptsSection] 设置概念数据', formattedConcepts);
setConcepts(formattedConcepts);
} else {
setConcepts([]);
}
} catch (err) {
console.error('[RelatedConceptsSection] 获取概念失败', err);
logger.error('RelatedConceptsSection', 'fetchConcepts', err);
setError('加载概念数据失败');
setConcepts([]);
} finally {
setLoading(false);
}
return;
}
// 降级方案:使用 eventTitle 搜索概念(兼容旧逻辑)
if (!eventTitle || !effectiveTradingDate) {
console.log('[RelatedConceptsSection] 缺少必要参数,跳过搜索', {
hasEventId: !!eventId,
hasEventTitle: !!eventTitle,
hasEffectiveTradingDate: !!effectiveTradingDate
});
@@ -86,19 +149,14 @@ const RelatedConceptsSection = ({
setLoading(true);
setError(null);
// 格式化交易日期 - 统一使用 moment 处理
// 格式化交易日期
let formattedTradeDate;
try {
// 不管传入的是什么格式,都用 moment 解析并格式化为 YYYY-MM-DD
formattedTradeDate = dayjs(effectiveTradingDate).format('YYYY-MM-DD');
// 验证日期是否有效
if (!dayjs(formattedTradeDate, 'YYYY-MM-DD', true).isValid()) {
console.warn('[RelatedConceptsSection] 无效日期,使用当前日期');
formattedTradeDate = dayjs().format('YYYY-MM-DD');
}
} catch (error) {
console.warn('[RelatedConceptsSection] 日期格式化失败,使用当前日期', error);
formattedTradeDate = dayjs().format('YYYY-MM-DD');
}
@@ -111,67 +169,37 @@ const RelatedConceptsSection = ({
};
const apiUrl = `${getApiBase()}/concept-api/search`;
console.log('[RelatedConceptsSection] 发送请求', {
url: apiUrl,
requestBody
});
logger.debug('RelatedConceptsSection', '搜索概念', requestBody);
console.log('[RelatedConceptsSection] 降级:使用搜索接口', { url: apiUrl, requestBody });
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody)
});
console.log('[RelatedConceptsSection] 响应状态', {
ok: response.ok,
status: response.status,
statusText: response.statusText
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('[RelatedConceptsSection] 响应数据', {
hasResults: !!data.results,
resultsCount: data.results?.length || 0,
hasDataConcepts: !!(data.data && data.data.concepts),
data: data
});
logger.debug('RelatedConceptsSection', '概念搜索响应', {
hasResults: !!data.results,
resultsCount: data.results?.length || 0
});
// 设置概念数据
if (data.results && Array.isArray(data.results)) {
console.log('[RelatedConceptsSection] 设置概念数据 (results)', data.results);
setConcepts(data.results);
} else if (data.data && data.data.concepts) {
// 向后兼容
console.log('[RelatedConceptsSection] 设置概念数据 (data.concepts)', data.data.concepts);
setConcepts(data.data.concepts);
} else {
console.log('[RelatedConceptsSection] 没有找到概念数据,设置为空数组');
setConcepts([]);
}
} catch (err) {
console.error('[RelatedConceptsSection] 搜索概念失败', err);
logger.error('RelatedConceptsSection', 'searchConcepts', err);
setError('加载概念数据失败');
setConcepts([]);
} finally {
console.log('[RelatedConceptsSection] 加载完成');
setLoading(false);
}
};
searchConcepts();
}, [eventTitle, effectiveTradingDate]);
fetchConcepts();
}, [eventId, eventTitle, effectiveTradingDate]);
// 加载中状态
if (loading) {