updated
This commit is contained in:
@@ -122,13 +122,14 @@ const ConceptTimelineModal = ({
|
||||
})
|
||||
);
|
||||
|
||||
// 获取新闻(精确匹配,最近100天,最多100条)
|
||||
// 获取新闻(使用与原代码相同的参数)
|
||||
const newsParams = new URLSearchParams({
|
||||
query: conceptName,
|
||||
exact_match: 1,
|
||||
start_date: startDateStr,
|
||||
end_date: endDateStr,
|
||||
top_k: 100
|
||||
top_k: 100, // 与原代码一致
|
||||
pagenum: 1, // 第一页
|
||||
pagesize: 100 // 一次获取100条,避免分页
|
||||
});
|
||||
|
||||
const newsUrl = `${NEWS_API_URL}/search_china_news?${newsParams}`;
|
||||
@@ -149,13 +150,14 @@ const ConceptTimelineModal = ({
|
||||
})
|
||||
);
|
||||
|
||||
// 获取研报(文本模式、精确匹配,最近100天,最多30条)
|
||||
// 获取研报(使用与原代码相同的参数结构)
|
||||
const reportParams = new URLSearchParams({
|
||||
query: conceptName,
|
||||
mode: 'text',
|
||||
exact_match: 1,
|
||||
size: 30,
|
||||
start_date: startDateStr
|
||||
start_date: startDateStr,
|
||||
end_date: endDateStr,
|
||||
size: 100, // 一次获取100条
|
||||
from: 0, // 从第0条开始
|
||||
mode: 'hybrid' // 与原代码一致
|
||||
});
|
||||
|
||||
const reportUrl = `${REPORT_API_URL}/search?${reportParams}`;
|
||||
@@ -233,41 +235,34 @@ const ConceptTimelineModal = ({
|
||||
});
|
||||
}
|
||||
|
||||
// 处理研报(按时间降序排序,最新的在前),兼容 data.results 与 results
|
||||
if (reportResult) {
|
||||
const reports = (reportResult.data && Array.isArray(reportResult.data.results))
|
||||
? reportResult.data.results
|
||||
: (Array.isArray(reportResult.results) ? reportResult.results : []);
|
||||
// 处理研报(按时间降序排序,最新的在前)
|
||||
if (reportResult && reportResult.results && Array.isArray(reportResult.results)) {
|
||||
// 先排序
|
||||
const sortedReports = reportResult.results.sort((a, b) => {
|
||||
const dateA = new Date(a.declare_date || 0);
|
||||
const dateB = new Date(b.declare_date || 0);
|
||||
return dateB - dateA; // 降序
|
||||
});
|
||||
|
||||
if (reports.length > 0) {
|
||||
const sortedReports = reports.sort((a, b) => {
|
||||
const dateA = new Date((a.declare_date || '').replace(' ', 'T'));
|
||||
const dateB = new Date((b.declare_date || '').replace(' ', 'T'));
|
||||
return dateB - dateA; // 降序
|
||||
});
|
||||
sortedReports.forEach(report => {
|
||||
if (report.declare_date) {
|
||||
// 研报日期格式已经是 YYYY-MM-DD
|
||||
const dateOnly = report.declare_date;
|
||||
|
||||
sortedReports.forEach(report => {
|
||||
const rawDate = report.declare_date || '';
|
||||
if (rawDate) {
|
||||
const dateOnly = rawDate.includes('T') ? rawDate.split('T')[0]
|
||||
: rawDate.includes(' ') ? rawDate.split(' ')[0]
|
||||
: rawDate;
|
||||
|
||||
events.push({
|
||||
type: 'report',
|
||||
date: dateOnly,
|
||||
time: rawDate,
|
||||
title: report.report_title,
|
||||
content: report.content,
|
||||
publisher: report.publisher,
|
||||
author: report.author,
|
||||
rating: report.rating,
|
||||
security_name: report.security_name,
|
||||
content_url: report.content_url
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
events.push({
|
||||
type: 'report',
|
||||
date: dateOnly, // 日期
|
||||
time: report.declare_date, // 研报没有具体时间
|
||||
title: report.report_title,
|
||||
content: report.content,
|
||||
publisher: report.publisher,
|
||||
author: report.author,
|
||||
rating: report.rating,
|
||||
security_name: report.security_name,
|
||||
content_url: report.content_url
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 按日期分组
|
||||
@@ -326,17 +321,18 @@ const ConceptTimelineModal = ({
|
||||
}));
|
||||
};
|
||||
|
||||
// 格式化日期显示(包含年份)
|
||||
// 格式化日期显示
|
||||
const formatDateDisplay = (dateStr) => {
|
||||
const date = new Date(dateStr);
|
||||
const today = new Date();
|
||||
const diffTime = today - date;
|
||||
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const formatted = `${year}-${month}-${day}`;
|
||||
const formatted = date.toLocaleDateString('zh-CN', {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
weekday: 'short'
|
||||
});
|
||||
|
||||
if (diffDays === 0) return `今天 ${formatted}`;
|
||||
if (diffDays === 1) return `昨天 ${formatted}`;
|
||||
@@ -346,20 +342,6 @@ const ConceptTimelineModal = ({
|
||||
return formatted;
|
||||
};
|
||||
|
||||
// 格式化完整时间(YYYY-MM-DD HH:mm)
|
||||
const formatDateTime = (dateTimeStr) => {
|
||||
if (!dateTimeStr) return '-';
|
||||
const normalized = typeof dateTimeStr === 'string' ? dateTimeStr.replace(' ', 'T') : dateTimeStr;
|
||||
const dt = new Date(normalized);
|
||||
if (isNaN(dt.getTime())) return '-';
|
||||
const y = dt.getFullYear();
|
||||
const m = String(dt.getMonth() + 1).padStart(2, '0');
|
||||
const d = String(dt.getDate()).padStart(2, '0');
|
||||
const hh = String(dt.getHours()).padStart(2, '0');
|
||||
const mm = String(dt.getMinutes()).padStart(2, '0');
|
||||
return `${y}-${m}-${d} ${hh}:${mm}`;
|
||||
};
|
||||
|
||||
// 获取涨跌幅颜色和图标
|
||||
const getPriceInfo = (price) => {
|
||||
if (!price || price.avg_change_pct === null) {
|
||||
@@ -411,33 +393,11 @@ const ConceptTimelineModal = ({
|
||||
<Badge colorScheme="yellow" ml={2}>
|
||||
最近100天
|
||||
</Badge>
|
||||
<Badge colorScheme="purple" ml={2} fontSize="xs">
|
||||
🔥 Max版功能
|
||||
</Badge>
|
||||
</HStack>
|
||||
</ModalHeader>
|
||||
<ModalCloseButton color="white" />
|
||||
|
||||
<ModalBody
|
||||
py={6}
|
||||
bg="gray.50"
|
||||
css={{
|
||||
'&::-webkit-scrollbar': {
|
||||
width: '8px',
|
||||
},
|
||||
'&::-webkit-scrollbar-track': {
|
||||
background: '#f1f1f1',
|
||||
borderRadius: '10px',
|
||||
},
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
background: '#c1c1c1',
|
||||
borderRadius: '10px',
|
||||
},
|
||||
'&::-webkit-scrollbar-thumb:hover': {
|
||||
background: '#a8a8a8',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ModalBody py={6} bg="gray.50">
|
||||
{loading ? (
|
||||
<Center py={20}>
|
||||
<VStack spacing={4}>
|
||||
@@ -654,22 +614,6 @@ const ConceptTimelineModal = ({
|
||||
boxShadow="sm"
|
||||
border="1px solid"
|
||||
borderColor="gray.200"
|
||||
css={{
|
||||
'&::-webkit-scrollbar': {
|
||||
width: '6px',
|
||||
},
|
||||
'&::-webkit-scrollbar-track': {
|
||||
background: '#f1f1f1',
|
||||
borderRadius: '10px',
|
||||
},
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
background: '#c1c1c1',
|
||||
borderRadius: '10px',
|
||||
},
|
||||
'&::-webkit-scrollbar-thumb:hover': {
|
||||
background: '#a8a8a8',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{item.events.map((event, eventIdx) => (
|
||||
<Box
|
||||
@@ -723,38 +667,17 @@ const ConceptTimelineModal = ({
|
||||
{event.content || '暂无内容'}
|
||||
</Text>
|
||||
|
||||
<Button
|
||||
size="xs"
|
||||
variant="link"
|
||||
colorScheme="blue"
|
||||
leftIcon={<ViewIcon />}
|
||||
onClick={() => {
|
||||
if (event.type === 'news') {
|
||||
setSelectedNews({
|
||||
title: event.title,
|
||||
content: event.content,
|
||||
source: event.source,
|
||||
time: event.time,
|
||||
url: event.url
|
||||
});
|
||||
setIsNewsModalOpen(true);
|
||||
} else if (event.type === 'report') {
|
||||
setSelectedReport({
|
||||
title: event.title,
|
||||
content: event.content,
|
||||
publisher: event.publisher,
|
||||
author: event.author,
|
||||
time: event.time,
|
||||
rating: event.rating,
|
||||
security_name: event.security_name,
|
||||
content_url: event.content_url
|
||||
});
|
||||
setIsReportModalOpen(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
查看详情
|
||||
</Button>
|
||||
{event.url && (
|
||||
<Button
|
||||
size="xs"
|
||||
variant="link"
|
||||
colorScheme="blue"
|
||||
rightIcon={<ExternalLinkIcon />}
|
||||
onClick={() => window.open(event.url, '_blank')}
|
||||
>
|
||||
查看原文
|
||||
</Button>
|
||||
)}
|
||||
</VStack>
|
||||
</Box>
|
||||
))}
|
||||
@@ -834,7 +757,7 @@ const ConceptTimelineModal = ({
|
||||
<Text>{selectedReport.author}</Text>
|
||||
)}
|
||||
{selectedReport?.time && (
|
||||
<Text>{formatDateTime(selectedReport.time)}</Text>
|
||||
<Text>{selectedReport.time}</Text>
|
||||
)}
|
||||
{selectedReport?.rating && (
|
||||
<Badge colorScheme="orange" variant="solid">
|
||||
@@ -912,8 +835,17 @@ const ConceptTimelineModal = ({
|
||||
{selectedNews.source === 'zsxq' ? '知识星球' : selectedNews.source}
|
||||
</Badge>
|
||||
)}
|
||||
{selectedNews?.time && (
|
||||
<Text>{formatDateTime(selectedNews.time)}</Text>
|
||||
{selectedNews?.time && selectedNews.time.includes('T') && (
|
||||
<Text>
|
||||
{new Date(selectedNews.time).toLocaleString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
})}
|
||||
</Text>
|
||||
)}
|
||||
</HStack>
|
||||
</VStack>
|
||||
|
||||
Reference in New Issue
Block a user