| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- #!/usr/bin/env node
- // ==============================================================================
- // 江中肝纯片 · VOC 验证报告生成器
- // 用法:node scripts/tools/gen-voc-validation.js
- // 输出:reports/jiangzhong-liver-voc-validation-report.html
- // 依赖:
- // - data/jiangzhong-liver-voc.json (已有 VOC 基础数据)
- // - data/jiangzhong-liver-voc-extended.json (Batch 2 多平台扩采数据,可选)
- // - scripts/tools/voc-analyze.js (分析层)
- // - scripts/tools/voc-validation-render.js (渲染层,分批次扩展)
- // ==============================================================================
- const fs = require('fs');
- const path = require('path');
- const { analyze } = require('./voc-analyze.js');
- const { buildHTML, CHAPTERS, CHAPTER_SUBSECTIONS } = require('./voc-validation-render.js');
- const INPUT_BASE = path.join('data', 'jiangzhong-liver-voc.json');
- const INPUT_EXTENDED = path.join('data', 'jiangzhong-liver-voc-extended.json');
- const OUTPUT = path.join('reports', 'jiangzhong-liver-voc-validation-report.html');
- function mtimeStr(fp) {
- try {
- const d = new Date(fs.statSync(fp).mtime);
- return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
- } catch { return '—'; }
- }
- // 计算实际 slide 总数(2 + 各章节 1 divider + N 子章)
- const actualTotal = 2 + CHAPTERS.map((c) => 1 + (CHAPTER_SUBSECTIONS[c.key] || []).length).reduce((a, b) => a + b, 0);
- console.log(`╔═══════════════════════════════════════════════════════════╗`);
- console.log(`║ 江中肝纯片 · VOC 验证报告生成(10亿×4渠道×5模块) ║`);
- console.log(`╚═══════════════════════════════════════════════════════════╝`);
- console.log(` 输入基础: ${INPUT_BASE}`);
- console.log(` 输入扩展: ${fs.existsSync(INPUT_EXTENDED) ? INPUT_EXTENDED : '(未生成,可跳过)'}`);
- console.log(` 输出: ${OUTPUT}`);
- console.log(` 章节: ${CHAPTERS.length} 大维度(方法论/包装/定价/定位话术/场景/竞品/落地)`);
- console.log(` slide 总数: ${actualTotal}`);
- if (!fs.existsSync(INPUT_BASE)) {
- console.error(`\n ❌ 基础 VOC 数据不存在:${INPUT_BASE}`);
- process.exit(1);
- }
- const t0 = Date.now();
- const vocBase = JSON.parse(fs.readFileSync(INPUT_BASE, 'utf-8'));
- // 合并扩展数据(Batch 2 采集后会生成)
- let vocExtended = null;
- if (fs.existsSync(INPUT_EXTENDED)) {
- try {
- vocExtended = JSON.parse(fs.readFileSync(INPUT_EXTENDED, 'utf-8'));
- console.log(` ✓ 已合并 VOC 扩展数据`);
- } catch (e) {
- console.warn(` ⚠ VOC 扩展数据解析失败:${e.message}`);
- }
- }
- const A = analyze(vocBase);
- // 附加扩展数据引用,便于 Ch2-7 渲染器使用
- A.extended = vocExtended;
- const collectedAt = mtimeStr(INPUT_BASE);
- const html = buildHTML({ product: '江中肝纯片', A, collectedAt });
- fs.mkdirSync(path.dirname(OUTPUT), { recursive: true });
- fs.writeFileSync(OUTPUT, html, 'utf-8');
- const size = fs.statSync(OUTPUT).size;
- const ms = Date.now() - t0;
- console.log(`\n ✅ 生成完成`);
- console.log(` 路径: ${OUTPUT}`);
- console.log(` 大小: ${(size / 1024).toFixed(1)} KB`);
- console.log(` 耗时: ${ms} ms`);
- console.log(` VOC 基础: ${A.metrics?.notes || '?'} 笔记 / ${A.metrics?.sampleComments || '?'} 评论 / Amazon ${A.amazon?.total || 0} 款`);
- if (vocExtended) {
- console.log(` VOC 扩展: 多平台数据已合并`);
- }
- console.log('');
|