diff --git a/src/views/Concept/ConceptTimelineModal.js b/src/views/Concept/ConceptTimelineModal.js index 51c35ec6..b876d28c 100644 --- a/src/views/Concept/ConceptTimelineModal.js +++ b/src/views/Concept/ConceptTimelineModal.js @@ -137,58 +137,130 @@ const ConceptTimelineModal = ({ ); // 获取新闻(精确匹配,最近100天,最多100条) - const newsParams = new URLSearchParams({ - query: conceptName, - exact_match: 1, - start_date: startDateStr, - end_date: endDateStr, - top_k: 100 - }); + // 🔄 添加回退逻辑:如果结果不足30条,去掉 exact_match 参数重新搜索 + const fetchNews = async () => { + try { + // 第一次尝试:使用精确匹配 + const newsParams = new URLSearchParams({ + query: conceptName, + exact_match: 1, + start_date: startDateStr, + end_date: endDateStr, + top_k: 100 + }); - const newsUrl = `${NEWS_API_URL}/search_china_news?${newsParams}`; + const newsUrl = `${NEWS_API_URL}/search_china_news?${newsParams}`; + const res = await fetch(newsUrl); - promises.push( - fetch(newsUrl) - .then(async res => { - if (!res.ok) { - const text = await res.text(); - logger.error('ConceptTimelineModal', 'fetchTimelineData - News API', new Error(`HTTP ${res.status}`), { conceptName, status: res.status, response: text.substring(0, 200) }); - return []; - } - return res.json(); - }) - .catch(err => { - logger.error('ConceptTimelineModal', 'fetchTimelineData - News API', err, { conceptName }); + if (!res.ok) { + const text = await res.text(); + logger.error('ConceptTimelineModal', 'fetchTimelineData - News API (exact_match=1)', new Error(`HTTP ${res.status}`), { conceptName, status: res.status, response: text.substring(0, 200) }); return []; - }) - ); + } + + const newsResult = await res.json(); + const newsArray = Array.isArray(newsResult) ? newsResult : []; + + // 检查结果数量,如果不足30条则进行回退搜索 + if (newsArray.length < 30) { + logger.info('ConceptTimelineModal', `新闻精确搜索结果不足30条 (${newsArray.length}),尝试模糊搜索`, { conceptName }); + + // 第二次尝试:去掉精确匹配参数 + const fallbackParams = new URLSearchParams({ + query: conceptName, + start_date: startDateStr, + end_date: endDateStr, + top_k: 100 + }); + + const fallbackUrl = `${NEWS_API_URL}/search_china_news?${fallbackParams}`; + const fallbackRes = await fetch(fallbackUrl); + + if (!fallbackRes.ok) { + logger.warn('ConceptTimelineModal', '新闻模糊搜索失败,使用精确搜索结果', { conceptName }); + return newsArray; + } + + const fallbackResult = await fallbackRes.json(); + const fallbackArray = Array.isArray(fallbackResult) ? fallbackResult : []; + + logger.info('ConceptTimelineModal', `新闻模糊搜索成功,获取 ${fallbackArray.length} 条结果`, { conceptName }); + return fallbackArray; + } + + return newsArray; + } catch (err) { + logger.error('ConceptTimelineModal', 'fetchTimelineData - News API', err, { conceptName }); + return []; + } + }; + + promises.push(fetchNews()); // 获取研报(文本模式、精确匹配,最近100天,最多30条) - const reportParams = new URLSearchParams({ - query: conceptName, - mode: 'text', - exact_match: 1, - size: 30, - start_date: startDateStr - }); + // 🔄 添加回退逻辑:如果结果不足10条,去掉 exact_match 参数重新搜索 + const fetchReports = async () => { + try { + // 第一次尝试:使用精确匹配 + const reportParams = new URLSearchParams({ + query: conceptName, + mode: 'text', + exact_match: 1, + size: 30, + start_date: startDateStr + }); - const reportUrl = `${REPORT_API_URL}/search?${reportParams}`; + const reportUrl = `${REPORT_API_URL}/search?${reportParams}`; + const res = await fetch(reportUrl); - promises.push( - fetch(reportUrl) - .then(async res => { - if (!res.ok) { - const text = await res.text(); - logger.error('ConceptTimelineModal', 'fetchTimelineData - Report API', new Error(`HTTP ${res.status}`), { conceptName, status: res.status, response: text.substring(0, 200) }); - return { results: [] }; - } - return res.json(); - }) - .catch(err => { - logger.error('ConceptTimelineModal', 'fetchTimelineData - Report API', err, { conceptName }); + if (!res.ok) { + const text = await res.text(); + logger.error('ConceptTimelineModal', 'fetchTimelineData - Report API (exact_match=1)', new Error(`HTTP ${res.status}`), { conceptName, status: res.status, response: text.substring(0, 200) }); return { results: [] }; - }) - ); + } + + const reportResult = await res.json(); + const reports = (reportResult.data && Array.isArray(reportResult.data.results)) + ? reportResult.data.results + : (Array.isArray(reportResult.results) ? reportResult.results : []); + + // 检查结果数量,如果不足10条则进行回退搜索 + if (reports.length < 10) { + logger.info('ConceptTimelineModal', `研报精确搜索结果不足10条 (${reports.length}),尝试模糊搜索`, { conceptName }); + + // 第二次尝试:去掉精确匹配参数 + const fallbackParams = new URLSearchParams({ + query: conceptName, + mode: 'text', + size: 30, + start_date: startDateStr + }); + + const fallbackUrl = `${REPORT_API_URL}/search?${fallbackParams}`; + const fallbackRes = await fetch(fallbackUrl); + + if (!fallbackRes.ok) { + logger.warn('ConceptTimelineModal', '研报模糊搜索失败,使用精确搜索结果', { conceptName }); + return { results: reports }; + } + + const fallbackResult = await fallbackRes.json(); + const fallbackReports = (fallbackResult.data && Array.isArray(fallbackResult.data.results)) + ? fallbackResult.data.results + : (Array.isArray(fallbackResult.results) ? fallbackResult.results : []); + + logger.info('ConceptTimelineModal', `研报模糊搜索成功,获取 ${fallbackReports.length} 条结果`, { conceptName }); + return { results: fallbackReports }; + } + + return { results: reports }; + } catch (err) { + logger.error('ConceptTimelineModal', 'fetchTimelineData - Report API', err, { conceptName }); + return { results: [] }; + } + }; + + promises.push(fetchReports()); const [priceResult, newsResult, reportResult] = await Promise.all(promises); diff --git a/src/views/EventDetail/components/LimitAnalyse.js b/src/views/EventDetail/components/LimitAnalyse.js index 0c180f9f..6732efdb 100644 --- a/src/views/EventDetail/components/LimitAnalyse.js +++ b/src/views/EventDetail/components/LimitAnalyse.js @@ -819,7 +819,9 @@ const StockCard = ({ stock, idx }) => { - (\s*)/g, '\n').replace(/\n{2,}/g, '\n').replace(/\n/g, '
') }} /> + + {(stock.summary || '').replace(//gi, '\n')} +