148 lines
4.3 KiB
JavaScript
148 lines
4.3 KiB
JavaScript
// src/utils/citationUtils.js
|
||
// 引用数据处理工具
|
||
|
||
import { logger } from './logger';
|
||
|
||
/**
|
||
* 处理后端返回的引用数据
|
||
*
|
||
* @param {Object} rawData - 后端返回的原始数据
|
||
* @param {Array} rawData.data - 引用数据数组
|
||
* @returns {Object|null} 处理后的数据结构,包含 segments 和 citations
|
||
*
|
||
* @example
|
||
* 输入格式:
|
||
* {
|
||
* data: [
|
||
* {
|
||
* author: "陈彤",
|
||
* sentences: "核心结论:...",
|
||
* query_part: "国内领先的IT解决方案提供商",
|
||
* match_score: "好",
|
||
* declare_date: "2025-04-17T00:00:00",
|
||
* report_title: "深度布局..."
|
||
* }
|
||
* ]
|
||
* }
|
||
*
|
||
* 输出格式:
|
||
* {
|
||
* segments: [
|
||
* { text: "国内领先的IT解决方案提供商", citationId: 1 } // 优先使用 query_part
|
||
* ],
|
||
* citations: {
|
||
* 1: {
|
||
* author: "陈彤",
|
||
* report_title: "深度布局...",
|
||
* declare_date: "2025-04-17",
|
||
* sentences: "核心结论:..." // sentences 显示在弹窗中
|
||
* }
|
||
* }
|
||
* }
|
||
*/
|
||
export const processCitationData = (rawData) => {
|
||
// 验证输入数据
|
||
if (!rawData || !rawData.data || !Array.isArray(rawData.data)) {
|
||
logger.warn('citationUtils', '无效的数据格式', {
|
||
hasRawData: !!rawData,
|
||
hasDataField: !!(rawData && rawData.data),
|
||
isArray: !!(rawData && rawData.data && Array.isArray(rawData.data))
|
||
});
|
||
return null;
|
||
}
|
||
|
||
if (rawData.data.length === 0) {
|
||
logger.warn('citationUtils', '数据数组为空');
|
||
return null;
|
||
}
|
||
|
||
const segments = [];
|
||
const citations = {};
|
||
|
||
// 处理每个引用数据项
|
||
rawData.data.forEach((item, index) => {
|
||
// 验证必需字段(至少需要 query_part 或 sentences 之一)
|
||
if (!item.query_part && !item.sentences) {
|
||
logger.warn('citationUtils', '缺少必需字段', {
|
||
itemIndex: index,
|
||
hasQueryPart: !!item.query_part,
|
||
hasSentences: !!item.sentences
|
||
});
|
||
return;
|
||
}
|
||
|
||
const citationId = index + 1; // 引用 ID 从 1 开始
|
||
|
||
// 构建文本片段
|
||
segments.push({
|
||
text: item.query_part || item.sentences, // 优先使用 query_part,降级到 sentences
|
||
citationId: citationId
|
||
});
|
||
|
||
// 构建引用信息映射
|
||
citations[citationId] = {
|
||
author: item.author || '未知作者',
|
||
organization: item.organization || '', // 券商名/机构名,可选字段
|
||
report_title: item.report_title || '未知报告',
|
||
declare_date: formatDate(item.declare_date),
|
||
sentences: item.sentences,
|
||
// 保留原始数据以备扩展
|
||
query_part: item.query_part,
|
||
match_score: item.match_score
|
||
};
|
||
});
|
||
|
||
// 如果没有有效的片段,返回 null
|
||
if (segments.length === 0) {
|
||
logger.warn('citationUtils', '没有找到有效的片段', {
|
||
totalItems: rawData.data.length
|
||
});
|
||
return null;
|
||
}
|
||
|
||
return {
|
||
segments,
|
||
citations
|
||
};
|
||
};
|
||
|
||
/**
|
||
* 格式化日期
|
||
* @param {string} dateStr - ISO 格式日期字符串
|
||
* @returns {string} 格式化后的日期 YYYY-MM-DD
|
||
*/
|
||
const formatDate = (dateStr) => {
|
||
if (!dateStr) return '--';
|
||
|
||
try {
|
||
const date = new Date(dateStr);
|
||
if (isNaN(date.getTime())) return '--';
|
||
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
|
||
return `${year}-${month}-${day}`;
|
||
} catch (e) {
|
||
logger.warn('citationUtils', '日期格式化错误', {
|
||
dateStr,
|
||
error: e.message
|
||
});
|
||
return '--';
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 验证引用数据格式是否有效
|
||
* @param {Object} data - 待验证的数据
|
||
* @returns {boolean} 是否有效
|
||
*/
|
||
export const isValidCitationData = (data) => {
|
||
if (!data || typeof data !== 'object') return false;
|
||
if (!data.data || !Array.isArray(data.data)) return false;
|
||
if (data.data.length === 0) return false;
|
||
|
||
// 检查至少有一个有效的 query_part 或 sentences 字段
|
||
return data.data.some(item => item && (item.query_part || item.sentences));
|
||
};
|