| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- function asArray(value) {
- return Array.isArray(value) ? value : [];
- }
- function hasSourceUrl(item) {
- return Boolean(item && (item.sourceUrl || item.webUrl || item.url));
- }
- function hasImage(item) {
- return Boolean(
- item &&
- (item.localCoverPath ||
- item.coverUrl ||
- (Array.isArray(item.imageUrls) && item.imageUrls.length))
- );
- }
- function hasText(item) {
- return Boolean(
- item &&
- String(item.contentExcerpt || item.rawExcerpt || item.content || item.desc || item.title || '').trim()
- );
- }
- function assessEvidenceQuality({ items, comments, itemLabel = '样本', collectionMode = 'sample' }) {
- const rows = asArray(items);
- const commentRows = asArray(comments);
- const sourceUrlCount = rows.filter(hasSourceUrl).length;
- const imageCount = rows.filter(hasImage).length;
- const textCount = rows.filter(hasText).length;
- const highLikeCommentCount = commentRows.filter(comment => Number(comment.likeCount || 0) > 0).length;
- let score = 0;
- if (rows.length >= 8) score += 2;
- else if (rows.length >= 3) score += 1;
- if (commentRows.length >= 50) score += 2;
- else if (commentRows.length >= 10) score += 1;
- if (sourceUrlCount >= Math.min(rows.length, 3)) score += 1;
- if (imageCount >= Math.min(rows.length, 3)) score += 1;
- if (highLikeCommentCount >= 3) score += 1;
- if (textCount >= Math.min(rows.length, 3)) score += 1;
- const grade = score >= 7 ? 'A' : score >= 4 ? 'B' : 'C';
- const canMakeBusinessDecision = grade === 'A' || (grade === 'B' && collectionMode === 'live');
- const recommendation = canMakeBusinessDecision
- ? '可以作为第一轮经营判断依据,但仍建议结合门店/销售/私域反馈校准。'
- : '只适合作为初步机会假设,不建议直接当最终经营结论。';
- return {
- grade,
- itemLabel,
- itemCount: rows.length,
- commentCount: commentRows.length,
- sourceUrlCount,
- imageCount,
- textCount,
- highLikeCommentCount,
- canMakeBusinessDecision,
- recommendation
- };
- }
- function buildEvidenceQualitySection(quality) {
- return [
- '## 证据质量门槛',
- '',
- `- 本轮证据质量:${quality.grade}`,
- `- ${quality.itemLabel}数量:${quality.itemCount}`,
- `- 评论数量:${quality.commentCount}`,
- `- 含原文/原视频链接:${quality.sourceUrlCount}`,
- `- 含图片/封面:${quality.imageCount}`,
- `- 含文本摘录:${quality.textCount}`,
- `- 含点赞评论:${quality.highLikeCommentCount}`,
- `- 是否适合直接做经营判断:${quality.canMakeBusinessDecision ? '适合第一轮判断' : '仅适合初步假设'}`,
- `- 使用建议:${quality.recommendation}`
- ];
- }
- function buildNoSampleFallbackMessage({ platformLabel, profile, examples = [] }) {
- const keywords = asArray(profile && profile.keywords).slice(0, 5).join('、') || '当前关键词';
- const exampleLines = examples.length ? examples.map(item => `- ${item}`) : [
- '- 换成更具体的品类词、场景词或城市词',
- '- 从产品词扩展到用户真实说法',
- '- 先用 sample 模式演示完整流程,但明确标注非真实采集'
- ];
- return [
- `本次 live 模式没有采到可用于分析的${platformLabel}样本。`,
- '',
- '这不代表行业没有机会,更可能是关键词过窄、平台内容表达不一样,或本轮上游没有返回可用内容。',
- '',
- '建议按这三步继续:',
- `1. 先保留当前方向:${keywords}`,
- '2. 自动换一组更贴近用户说法的关键词再试一次',
- '3. 如果仍然没有样本,降级到相关大词做第一轮机会假设,并明确标注“非真实采集/待验证”',
- '',
- '可尝试的关键词方向:',
- ...exampleLines
- ].join('\n');
- }
- module.exports = {
- assessEvidenceQuality,
- buildEvidenceQualitySection,
- buildNoSampleFallbackMessage
- };
|