| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- const fs = require('fs');
- const path = require('path');
- function attachReferenceBaselines(criteria, input = {}) {
- const baselines = loadReferenceBaselines(input);
- const providerStatus = input.referenceProviderStatus || {};
- if (!baselines.length) {
- return {
- ...criteria,
- referenceBaselines: [],
- referenceEvidenceStatus: buildEvidenceStatus(criteria, [], providerStatus)
- };
- }
- return {
- ...criteria,
- referenceBaselines: baselines,
- referenceBaselineSignals: [...new Set(baselines.flatMap(item => item.topSignals || []))],
- referenceEvidenceStatus: buildEvidenceStatus(criteria, baselines, providerStatus)
- };
- }
- function loadReferenceBaselines(input = {}) {
- const fromInput = Array.isArray(input.referenceBaselines) ? input.referenceBaselines : [];
- const baselinePath = input.referenceBaselinePath || input.referenceBaselinesPath || '';
- const fromPath = readBaselineFile(baselinePath);
- return dedupe([...fromInput, ...fromPath].map(normalizeBaseline).filter(Boolean));
- }
- function readBaselineFile(file) {
- if (!file) return [];
- const resolved = path.resolve(file);
- if (!fs.existsSync(resolved)) return [];
- try {
- const parsed = JSON.parse(fs.readFileSync(resolved, 'utf8'));
- if (Array.isArray(parsed)) return parsed;
- if (Array.isArray(parsed.referenceBaselines)) return parsed.referenceBaselines;
- if (Array.isArray(parsed.data)) return parsed.data;
- return [];
- } catch {
- return [];
- }
- }
- function normalizeBaseline(item) {
- if (!item || typeof item !== 'object') return null;
- const topSignals = normalizeSignals(item.topSignals || item.signals || item.referenceSignals || []);
- return {
- bucket: String(item.bucket || item.referenceBucket || '参考账号'),
- platform: item.platform || 'xiaohongshu',
- name: String(item.name || item.nickname || item.displayName || '').trim(),
- redId: String(item.redId || item.red_id || '').trim(),
- userId: String(item.userId || item.user_id || '').trim(),
- fans: Number(item.fans || item.fansCount || item.fansNum || 0),
- location: String(item.location || item.ipLocation || ''),
- profileDesc: String(item.profileDesc || item.desc || ''),
- sampleCount: Number(item.sampleCount || item.notesCount || 0),
- typeMix: String(item.typeMix || ''),
- collectMedian: toNullableNumber(item.collectMedian),
- commentMedian: toNullableNumber(item.commentMedian),
- topSignals,
- sampleTitles: normalizeTextList(item.sampleTitles || item.titles || []),
- source: item.source || 'reference-baseline-cache'
- };
- }
- function normalizeSignals(values) {
- return normalizeTextList(values)
- .map(item => item.replace(/\(\d+\)\s*$/, '').trim())
- .filter(Boolean);
- }
- function normalizeTextList(values) {
- return (Array.isArray(values) ? values : [values])
- .flatMap(item => String(item || '').split(/[、,;;]/))
- .map(item => item.trim())
- .filter(Boolean);
- }
- function buildEvidenceStatus(criteria, baselines, providerStatus = {}) {
- const linkCount = (criteria.referenceLinks || []).length;
- const status = baselines.length ? 'baseline_loaded' : linkCount ? 'needs_social_analysis_enrichment' : 'no_reference_links';
- return {
- referenceLinkCount: linkCount,
- baselineCount: baselines.length,
- status,
- providerRequested: Boolean(providerStatus.requested),
- providerStatus: providerStatus.status || 'not_requested',
- providerHttpStatus: providerStatus.httpStatus || 0,
- providerWarning: providerStatus.warning || '',
- note: providerStatus.warning || (baselines.length
- ? '已加载参考账号基线,可用于相似度与报告复核。'
- : linkCount
- ? '已识别参考链接,但尚未通过社媒分析服务加载账号详情。'
- : 'Brief 未提供明确参考链接。')
- };
- }
- function dedupe(items) {
- const seen = new Set();
- const result = [];
- for (const item of items) {
- const key = `${item.platform}:${item.userId || item.redId || item.name}:${item.bucket}`;
- if (seen.has(key)) continue;
- seen.add(key);
- result.push(item);
- }
- return result;
- }
- function toNullableNumber(value) {
- const number = Number(value);
- return Number.isFinite(number) ? number : null;
- }
- module.exports = {
- attachReferenceBaselines,
- loadReferenceBaselines,
- normalizeBaseline
- };
|