Files
vf_react/src/utils/citationUtils.js
2025-10-23 11:44:58 +08:00

148 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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));
};