| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- #!/usr/bin/env node
- const fs = require('fs');
- const path = require('path');
- const KA = require('./ks-analyze.js');
- const ROOT = path.resolve(__dirname, '..', '..');
- const OUT_DIR = path.join(ROOT, 'reports');
- const OUT_FILE = path.join(OUT_DIR, 'ks-voc-insight-report.html');
- const data = KA.loadRawFiles();
- const meta = KA.getMeta(data);
- const topLiked = KA.getTopLiked(data, 30);
- const byHypothesis = KA.getByHypothesis(data);
- const byKeyword = KA.getTopByKeyword(data, 8);
- const highRiskVOC = KA.getHighRiskVOC(data, 15);
- function esc(s) { return String(s ?? '').replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); }
- function fmtLikes(n) { if (n == null) return '0'; if (n >= 10000) return (n/10000).toFixed(1).replace(/\.0$/,'')+'w'; if (n >= 1000) return (n/1000).toFixed(1).replace(/\.0$/,'')+'k'; return String(n); }
- function truncate(s, n=200) { s = String(s ?? ''); return s.length > n ? s.slice(0,n-1)+'…' : s; }
- const hypos = [
- {h:'H1',title:'快聘是蓝领求职主阵地',count:byHypothesis.H1?.length||0,color:'#F5A623'},
- {h:'H3',title:'薪资透明度是核心关切',count:byHypothesis.H3?.length||0,color:'#00DC82'},
- {h:'H4',title:'食宿条件影响求职决策',count:byHypothesis.H4?.length||0,color:'#8B5CF6'},
- {h:'H5',title:'入职流程便捷性',count:byHypothesis.H5?.length||0,color:'#F97316'},
- {h:'H6',title:'求职被骗是普遍焦虑',count:byHypothesis.H6?.length||0,color:'#FF4D8D'},
- {h:'H7',title:'黑中介是核心痛点',count:byHypothesis.H7?.length||0,color:'#EF4444'},
- {h:'H8',title:'工资结算方式差异',count:byHypothesis.H8?.length||0,color:'#6B6B6B'},
- ].filter(h => h.count > 0);
- function vocCard(item, showKeyword = false) {
- const ip = item.ip_location ? ` [${esc(item.ip_location)}]` : '';
- const likes = item.likes || 0;
- return `<div style="background:linear-gradient(180deg,rgba(255,255,255,0.03) 0%,rgba(255,255,255,0.01) 100%),var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);padding:18px 20px;backdrop-filter:blur(8px);margin-bottom:12px;">
- <div style="display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap;">
- <div style="display:flex;align-items:center;gap:8px;">
- <span style="width:20px;height:20px;border-radius:50%;background:#FF2442;color:#fff;font-size:0.55rem;font-weight:700;display:flex;align-items:center;justify-content:center;">快</span>
- <span style="font-weight:600;font-size:0.82rem;">${esc(item.nickname||'匿名用户')}</span>
- <span style="font-size:0.7rem;color:var(--text-3);">${ip}</span>
- </div>
- <div style="display:flex;align-items:center;gap:8px;">
- <span style="font-size:0.72rem;color:var(--text-3);font-family:var(--font-mono);">♥${fmtLikes(likes)}</span>
- ${showKeyword && item.keyword ? `<span class="tag" style="font-size:0.6rem;padding:2px 6px;">${esc(item.keyword)}</span>` : ''}
- </div>
- </div>
- <div style="font-size:0.88rem;line-height:1.6;color:var(--text-1);">"${esc(truncate(item.content,180))}"</div>
- </div>`;
- }
- function insightBanner(num, title, body, stat, statLabel, color) {
- return `<div style="background:var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);padding:clamp(24px,3vw,40px);position:relative;overflow:hidden;min-height:200px;display:flex;flex-direction:column;justify-content:space-between;">
- <div style="position:absolute;top:12px;right:20px;font-family:var(--font-head);font-weight:900;font-size:clamp(3rem,6vw,5rem);color:var(--bg-3);pointer-events:none;">${num}</div>
- <h3 style="font-family:var(--font-head);font-weight:800;font-size:clamp(1.2rem,2vw,1.8rem);letter-spacing:-0.02em;max-width:85%;position:relative;z-index:1;">${title}</h3>
- <p style="color:var(--text-2);font-size:0.95rem;line-height:1.7;max-width:85%;position:relative;z-index:1;">${body}</p>
- <div style="display:flex;gap:20px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border);position:relative;z-index:1;">
- <div><span style="font-size:1.4rem;font-weight:800;color:${color};font-family:var(--font-head);">${stat}</span><span style="font-size:0.72rem;color:var(--text-3);margin-left:6px;">${statLabel}</span></div>
- </div>
- </div>`;
- }
- function barChart(rows, accent) {
- const max = Math.max(...rows.map(r=>r.value),1);
- const barH=32,gap=12,padL=120,padR=80,padV=12,W=900;
- const totalH = rows.length*(barH+gap)+padV*2;
- return `<div style="background:var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);padding:16px 20px;">
- <svg viewBox="0 0 ${W} ${totalH}" style="width:100%;height:auto;" preserveAspectRatio="xMidYMid meet">
- ${rows.map((r,i)=>{const y=padV+i*(barH+gap);const w=Math.max((r.value/max)*(W-padL-padR),4);return `<text x="${padL-8}" y="${y+barH/2+4}" text-anchor="end" font-size="12" fill="var(--text-2)">${esc(r.label)}</text><rect x="${padL}" y="${y}" width="${w}" height="${barH}" rx="3" fill="${r.color||accent}" opacity="0.85"/><text x="${padL+w+8}" y="${y+barH/2+4}" font-size="12" font-weight="700" fill="${r.color||accent}" font-family="monospace">${esc(r.valueLabel||r.value)}</text>`;}).join('')}
- </svg>
- </div>`;
- }
- const html = `<!DOCTYPE html>
- <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
- <title>快手快聘 · 蓝领求职洞察报告</title>
- <style>
- :root{--bg-0:#0A0A0A;--bg-1:#111111;--bg-2:#1A1A1A;--bg-3:#252525;--border:rgba(255,255,255,0.08);--border-strong:rgba(255,255,255,0.16);--text-1:#F5F5F5;--text-2:#A8A8A8;--text-3:#6B6B6B;--amber:#F5A623;--amber-glow:rgba(245,166,35,0.15);--green:#00DC82;--purple:#8B5CF6;--rose:#FF4D8D;--blue:#3B82F6;--red:#EF4444;--orange:#F97316;--font-head:'Inter','Noto Sans SC','PingFang SC','Microsoft YaHei',sans-serif;--font-body:'Noto Sans SC','Inter','PingFang SC','Microsoft YaHei',sans-serif;--font-mono:'JetBrains Mono','SF Mono','Fira Code',monospace;--max-w:1280px;--radius-sm:8px;--radius-md:12px;--radius-lg:20px;}
- *{margin:0;padding:0;box-sizing:border-box}
- html{scroll-behavior:smooth;font-size:16px;scroll-snap-type:y proximity;}
- body{font-family:var(--font-body);background:var(--bg-0);color:var(--text-1);line-height:1.65;-webkit-font-smoothing:antialiased;overflow-x:hidden}
- body::before{content:'';position:fixed;inset:0;pointer-events:none;z-index:0;background:radial-gradient(ellipse 900px 700px at var(--amb-x,20%) var(--amb-y,25%),rgba(245,166,35,0.10),transparent 60%),radial-gradient(ellipse 800px 600px at calc(100% - var(--amb-x,20%)) calc(100% - var(--amb-y,25%)),rgba(139,92,246,0.07),transparent 60%);transition:background 1.4s cubic-bezier(.2,.7,.2,1);}
- body::after{content:'';position:fixed;inset:0;pointer-events:none;z-index:0;background-image:linear-gradient(rgba(255,255,255,0.015) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,0.015) 1px,transparent 1px);background-size:80px 80px;mask-image:radial-gradient(ellipse 90% 95% at 50% 50%,black 0%,transparent 85%);-webkit-mask-image:radial-gradient(ellipse 90% 95% at 50% 50%,black 0%,transparent 85%);}
- main.deck{position:relative;z-index:1}
- ::selection{background:var(--amber);color:#000}
- .text-hero{font-family:var(--font-head);font-weight:900;letter-spacing:-0.04em;line-height:0.95;font-size:clamp(3.5rem,10vw,8rem)}
- .text-poster{font-family:var(--font-head);font-weight:800;letter-spacing:-0.03em;line-height:1.05;font-size:clamp(2.5rem,6vw,5rem)}
- .text-h1{font-family:var(--font-head);font-weight:700;letter-spacing:-0.02em;line-height:1.1;font-size:clamp(1.8rem,3.5vw,3rem)}
- .text-h2{font-family:var(--font-head);font-weight:700;letter-spacing:-0.015em;line-height:1.2;font-size:clamp(1.3rem,2.2vw,1.8rem)}
- .text-h3{font-weight:600;font-size:clamp(1rem,1.5vw,1.2rem);letter-spacing:-0.01em}
- .text-body{font-size:clamp(0.9rem,1.05vw,1rem);line-height:1.8;color:var(--text-2)}
- .text-sm{font-size:0.85rem;color:var(--text-2)}
- .text-xs{font-size:0.72rem;color:var(--text-3);letter-spacing:0.02em}
- .text-mono{font-family:var(--font-mono)}
- .text-amber{color:var(--amber)}.text-green{color:var(--green)}.text-purple{color:var(--purple)}.text-rose{color:var(--rose)}.text-blue{color:var(--blue)}.text-red{color:var(--red)}.text-orange{color:var(--orange)}
- section.report-section{min-height:100vh;padding:clamp(60px,10vh,120px) clamp(24px,6vw,80px);position:relative;border-bottom:1px solid var(--border);display:flex;flex-direction:column;justify-content:center;scroll-snap-align:start;scroll-snap-stop:always;overflow:hidden;isolation:isolate}
- section.report-section::before{content:attr(data-slide-num);position:absolute;top:clamp(20px,3vh,36px);right:clamp(24px,4vw,60px);font-family:var(--font-mono);font-weight:600;font-size:clamp(0.68rem,0.75vw,0.78rem);letter-spacing:0.25em;color:var(--text-3);z-index:4;pointer-events:none}
- section.report-section::after{content:'';position:absolute;inset:0;pointer-events:none;z-index:-1;background:radial-gradient(ellipse 70% 60% at 85% 15%,var(--slide-glow-1,rgba(245,166,35,0.06)),transparent 55%),radial-gradient(ellipse 60% 50% at 15% 85%,var(--slide-glow-2,rgba(139,92,246,0.04)),transparent 55%);opacity:0;transition:opacity 1s cubic-bezier(.2,.7,.2,1)}
- section.report-section.in-view::after{opacity:1}
- section.report-section[data-tone="amber"]{--slide-glow-1:rgba(245,166,35,0.10);--slide-glow-2:rgba(245,166,35,0.04)}
- section.report-section[data-tone="rose"]{--slide-glow-1:rgba(255,77,141,0.09);--slide-glow-2:rgba(255,77,141,0.04)}
- section.report-section[data-tone="green"]{--slide-glow-1:rgba(0,220,130,0.08);--slide-glow-2:rgba(0,220,130,0.03)}
- section.report-section[data-tone="purple"]{--slide-glow-1:rgba(139,92,246,0.10);--slide-glow-2:rgba(139,92,246,0.04)}
- section.report-section[data-tone="blue"]{--slide-glow-1:rgba(59,130,246,0.08);--slide-glow-2:rgba(59,130,246,0.03)}
- section.report-section[data-tone="orange"]{--slide-glow-1:rgba(249,115,22,0.10);--slide-glow-2:rgba(249,115,22,0.04)}
- section.report-section[data-tone="red"]{--slide-glow-1:rgba(239,68,68,0.10);--slide-glow-2:rgba(239,68,68,0.05)}
- .section-inner{width:100%;max-width:var(--max-w);margin:0 auto;position:relative}
- .section-head{margin-bottom:clamp(28px,4vh,56px)}
- .section-eyebrow{display:inline-flex;align-items:center;gap:10px;font-family:var(--font-mono);font-size:0.72rem;letter-spacing:0.18em;text-transform:uppercase;color:var(--amber);font-weight:500;margin-bottom:16px}
- .section-eyebrow::before{content:'';display:inline-block;width:24px;height:1px;background:var(--amber)}
- .section-sub{color:var(--text-2);font-size:1rem;max-width:720px;margin-top:12px;line-height:1.8}
- .grid{display:grid;gap:clamp(12px,1.4vw,20px)}
- .grid-2{grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}
- .grid-3{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
- .grid-4{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}
- .card{background:linear-gradient(180deg,rgba(255,255,255,0.025) 0%,rgba(255,255,255,0.008) 100%),var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);padding:clamp(18px,2vw,28px);position:relative;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);transition:transform 0.4s cubic-bezier(.2,.7,.2,1),border-color 0.3s ease,box-shadow 0.4s ease}
- .card:hover{border-color:var(--border-strong);transform:translateY(-2px);box-shadow:0 8px 32px rgba(0,0,0,0.3)}
- .card-accent{border-left:3px solid var(--amber)}
- .metric{background:var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);padding:clamp(20px,2.2vw,32px);position:relative;overflow:hidden}
- .metric::before{content:'';position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,var(--amber),transparent);opacity:0.6}
- .metric .metric-label{font-family:var(--font-mono);font-size:0.7rem;letter-spacing:0.15em;text-transform:uppercase;color:var(--text-3);margin-bottom:8px}
- .metric .metric-value{font-family:var(--font-head);font-weight:800;font-size:clamp(2rem,3.5vw,3rem);letter-spacing:-0.03em;line-height:1;color:var(--text-1);margin-bottom:6px}
- .metric .metric-sub{margin-top:10px;font-size:0.8rem;color:var(--text-2);line-height:1.4}
- .tag{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:4px;font-size:0.72rem;font-weight:500;letter-spacing:0.02em;font-family:var(--font-head);background:rgba(245,166,35,0.1);color:var(--amber);border:1px solid rgba(245,166,35,0.22)}
- .tag.green{background:rgba(0,220,130,0.08);color:var(--green);border-color:rgba(0,220,130,0.2)}
- .tag.purple{background:rgba(139,92,246,0.08);color:var(--purple);border-color:rgba(139,92,246,0.2)}
- .tag.rose{background:rgba(255,77,141,0.08);color:var(--rose);border-color:rgba(255,77,141,0.2)}
- .tag.blue{background:rgba(59,130,246,0.08);color:var(--blue);border-color:rgba(59,130,246,0.2)}
- .tag.orange{background:rgba(249,115,22,0.08);color:var(--orange);border-color:rgba(249,115,22,0.2)}
- .tag.red{background:rgba(239,68,68,0.08);color:var(--red);border-color:rgba(239,68,68,0.2)}
- .tag.gray{background:rgba(107,107,107,0.1);color:var(--text-2);border-color:rgba(107,107,107,0.2)}
- .cover-hero{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;padding:clamp(40px,8vh,100px) clamp(24px,6vw,80px);background:radial-gradient(ellipse 60% 80% at 30% 30%,rgba(245,166,35,0.08) 0%,transparent 70%),radial-gradient(ellipse 40% 60% at 80% 70%,rgba(139,92,246,0.05) 0%,transparent 70%),var(--bg-0)}
- .cover-grid-bg{position:absolute;inset:0;background-image:linear-gradient(rgba(255,255,255,0.025) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,0.025) 1px,transparent 1px);background-size:60px 60px;mask-image:radial-gradient(ellipse 80% 80% at 50% 50%,black 0%,transparent 70%);-webkit-mask-image:radial-gradient(ellipse 80% 80% at 50% 50%,black 0%,transparent 70%)}
- .footer{text-align:center;padding:40px 24px;color:var(--text-3);font-size:0.8rem;border-top:1px solid var(--border)}
- .progress-line{position:fixed;top:0;left:0;height:2px;background:linear-gradient(90deg,var(--amber),var(--rose));z-index:1000;width:0%;transition:width 0.3s ease}
- .nav-rail{position:fixed;left:clamp(16px,2vw,32px);top:50%;transform:translateY(-50%);z-index:100;display:flex;flex-direction:column;gap:10px}
- .nav-dot{width:28px;height:3px;border-radius:2px;background:rgba(255,255,255,0.14);cursor:pointer;transition:all 0.5s cubic-bezier(.2,.7,.2,1)}
- .nav-dot.active{background:var(--amber);width:40px;box-shadow:0 0 10px rgba(245,166,35,0.4)}
- .nav-dot::after{content:attr(data-tip);position:absolute;left:calc(100% + 12px);top:50%;transform:translateY(-50%);background:rgba(20,20,20,0.92);backdrop-filter:blur(8px);border:1px solid var(--border);padding:5px 10px;border-radius:6px;font-size:0.7rem;color:var(--text-1);white-space:nowrap;opacity:0;pointer-events:none;transition:opacity 0.2s}
- .nav-dot:hover::after,.nav-dot.active::after{opacity:1}
- .slide-counter{position:fixed;left:clamp(16px,2vw,28px);bottom:clamp(16px,2vh,28px);z-index:100;display:flex;align-items:center;gap:8px;padding:8px 14px;border-radius:999px;background:rgba(20,20,20,0.85);backdrop-filter:blur(16px);border:1px solid var(--border-strong);font-family:var(--font-mono);font-size:0.74rem;letter-spacing:0.1em;color:var(--text-2)}
- .slide-counter .now{color:var(--amber);font-weight:700}
- .kbd-hint{position:fixed;right:clamp(16px,2vw,28px);bottom:clamp(16px,2vh,28px);z-index:100;display:flex;align-items:center;gap:10px;padding:10px 16px;border-radius:999px;background:rgba(20,20,20,0.85);backdrop-filter:blur(16px);border:1px solid var(--border-strong);font-family:var(--font-mono);font-size:0.72rem;color:var(--text-2);letter-spacing:0.04em}
- .kbd-hint kbd{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 6px;background:var(--bg-3);border:1px solid var(--border-strong);border-radius:4px;font-size:0.7rem;font-family:var(--font-mono);color:var(--text-1);box-shadow:0 1px 0 rgba(0,0,0,0.4)}
- @media(max-width:900px){.nav-rail{display:none}.slide-counter,.kbd-hint{display:none}}
- </style>
- </head>
- <body>
- <div class="progress-line" id="progressLine"></div>
- <nav class="nav-rail" id="navRail"></nav>
- <div class="slide-counter"><span class="now" id="slideNow">01</span><div style="width:60px;height:2px;background:rgba(255,255,255,0.1);border-radius:2px;overflow:hidden;"><div id="slideBar" style="height:100%;width:0%;background:linear-gradient(90deg,var(--amber),var(--rose));transition:width 0.6s cubic-bezier(.2,.7,.2,1);"></div></div><span id="slideTotal">09</span></div>
- <div class="kbd-hint"><kbd>↓</kbd><kbd>↑</kbd> 滚动</div>
- <main class="deck">
- <!-- 封面 -->
- <section class="report-section" data-slide-num="COVER" data-tone="amber" style="position:relative;min-height:100vh;">
- <div class="cover-grid-bg"></div>
- <div class="cover-hero">
- <div style="margin-bottom:20px;">
- <span class="tag rose" style="font-size:0.8rem;padding:6px 14px;">快手快聘 · 蓝领求职生态洞察</span>
- </div>
- <h1 class="text-hero" style="margin-bottom:16px;background:linear-gradient(135deg,#fff 30%,rgba(245,166,35,0.9) 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;">蓝领求职</h1>
- <h2 class="text-hero" style="margin-bottom:24px;background:linear-gradient(135deg,rgba(245,166,35,0.7) 0%,rgba(139,92,246,0.8) 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;">最担心什么?</h2>
- <p class="text-body" style="font-size:1.1rem;max-width:580px;margin-bottom:32px;line-height:1.8;">基于<span style="color:var(--amber);font-weight:600;">${meta.comments.toLocaleString()}</span>条真实评论的深度分析 · 揭示4亿蓝领劳动者的求职焦虑与核心诉求</p>
- <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:16px;max-width:800px;margin-bottom:32px;">
- <div style="padding:16px 18px;background:rgba(255,255,255,0.03);border:1px solid var(--border);border-radius:var(--radius-md);">
- <div style="font-size:1.8rem;font-weight:800;color:var(--amber);font-family:var(--font-head);">2.5亿</div>
- <div class="text-xs" style="margin-top:4px;">蓝领月活用户</div>
- </div>
- <div style="padding:16px 18px;background:rgba(255,255,255,0.03);border:1px solid var(--border);border-radius:var(--radius-md);">
- <div style="font-size:1.8rem;font-weight:800;color:var(--green);font-family:var(--font-head);">40万+</div>
- <div class="text-xs" style="margin-top:4px;">带岗主播</div>
- </div>
- <div style="padding:16px 18px;background:rgba(255,255,255,0.03);border:1px solid var(--border);border-radius:var(--radius-md);">
- <div style="font-size:1.8rem;font-weight:800;color:var(--rose);font-family:var(--font-head);">${fmtLikes(topLiked[0]?.likes||0)}</div>
- <div class="text-xs" style="margin-top:4px;">最高点赞评论</div>
- </div>
- <div style="padding:16px 18px;background:rgba(255,255,255,0.03);border:1px solid var(--border);border-radius:var(--radius-md);">
- <div style="font-size:1.8rem;font-weight:800;color:var(--purple);font-family:var(--font-head);">${hypos.length}</div>
- <div class="text-xs" style="margin-top:4px;">验证假设数</div>
- </div>
- </div>
- <div class="text-xs" style="margin-top:24px;color:var(--text-3);">${meta.collectedAt} · 数据来源:快手评论采集 · Generated by OpenClaw VOC System</div>
- </div>
- </section>
- <!-- Ch1: 核心问题 -->
- <section class="report-section" data-slide-num="01" data-tone="amber">
- <div class="section-inner">
- <div class="section-head">
- <div class="section-eyebrow">CHAPTER 01</div>
- <h2 class="text-h1">蓝领求职:最担心什么?</h2>
- <p class="section-sub">基于4,948条真实评论的情感分析与洞察</p>
- </div>
- <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:32px;">
- <div class="card" style="border-top:3px solid var(--rose);text-align:center;padding:24px;">
- <div style="font-size:2.5rem;margin-bottom:12px;">⚠️</div>
- <div style="font-weight:700;color:var(--rose);margin-bottom:8px;font-size:1.1rem;">求职被骗焦虑</div>
- <div style="font-size:2rem;font-weight:800;color:var(--rose);font-family:var(--font-head);">${byHypothesis.H6?.length||0}</div>
- <div class="text-xs" style="margin-top:6px;">条相关评论</div>
- </div>
- <div class="card" style="border-top:3px solid var(--red);text-align:center;padding:24px;">
- <div style="font-size:2.5rem;margin-bottom:12px;">🏴</div>
- <div style="font-weight:700;color:var(--red);margin-bottom:8px;font-size:1.1rem;">黑中介痛点</div>
- <div style="font-size:2rem;font-weight:800;color:var(--red);font-family:var(--font-head);">${byHypothesis.H7?.length||0}</div>
- <div class="text-xs" style="margin-top:6px;">条相关评论</div>
- </div>
- <div class="card" style="border-top:3px solid var(--green);text-align:center;padding:24px;">
- <div style="font-size:2.5rem;margin-bottom:12px;">💰</div>
- <div style="font-weight:700;color:var(--green);margin-bottom:8px;font-size:1.1rem;">薪资不透明</div>
- <div style="font-size:2rem;font-weight:800;color:var(--green);font-family:var(--font-head);">${byHypothesis.H3?.length||0}</div>
- <div class="text-xs" style="margin-top:6px;">条相关评论</div>
- </div>
- </div>
- <div class="card card-accent" style="padding:24px 28px;margin-bottom:24px;background:linear-gradient(135deg,rgba(255,77,141,0.06),transparent);">
- <div style="display:flex;align-items:center;gap:12px;margin-bottom:14px;">
- <span style="font-size:1.8rem;">💡</span>
- <span style="font-weight:700;font-size:1.1rem;">核心洞察</span>
- </div>
- <p class="text-body">蓝领求职者最担心的是一个从<strong style="color:var(--rose);">"虚假信息"</strong>到<strong style="color:var(--red);">"财产欺诈"</strong>再到<strong style="color:var(--text-1);">"权益落空"</strong>的<strong style="color:var(--amber);">完整风险链条</strong>。他们最看重的是一套基于<strong style="color:var(--green);">"可视化真实"</strong>和<strong style="color:var(--green);">"熟人信任"</strong>,能够降低风险、简化流程、实现快速入职的解决方案。</p>
- </div>
- <div style="display:grid;grid-template-columns:repeat(2,1fr);gap:16px;">
- <div style="padding:20px 22px;background:rgba(255,77,141,0.06);border:1px solid rgba(255,77,141,0.2);border-radius:var(--radius-md);">
- <div style="font-weight:600;margin-bottom:10px;color:var(--rose);">🚨 最担心:招聘信息虚假</div>
- <p class="text-sm" style="line-height:1.6;">"高薪诱惑""夸大福利""模糊劳动条件"——求职者入职后发现实际与招聘描述严重不符</p>
- </div>
- <div style="padding:20px 22px;background:rgba(239,68,68,0.06);border:1px solid rgba(239,68,68,0.2);border-radius:var(--radius-md);">
- <div style="font-weight:600;margin-bottom:10px;color:var(--red);">💸 最担心:财产诈骗押金陷阱</div>
- <p class="text-sm" style="line-height:1.6;">直播间高薪诱惑,缴纳"入职押金"或"培训费"后招工方失联</p>
- </div>
- <div style="padding:20px 22px;background:rgba(0,220,130,0.06);border:1px solid rgba(0,220,130,0.2);border-radius:var(--radius-md);">
- <div style="font-weight:600;margin-bottom:10px;color:var(--green);">✓ 最看重:眼见为实</div>
- <p class="text-sm" style="line-height:1.6;">直播展示车间、宿舍、食堂,消解信息不对称带来的不安全感</p>
- </div>
- <div style="padding:20px 22px;background:rgba(59,130,246,0.06);border:1px solid rgba(59,130,246,0.2);border-radius:var(--radius-md);">
- <div style="font-weight:600;margin-bottom:10px;color:var(--blue);">✓ 最看重:零门槛求职</div>
- <p class="text-sm" style="line-height:1.6;">留下联系方式即可求职,无需撰写简历、填写复杂表格</p>
- </div>
- </div>
- </div>
- </section>
- <!-- Ch2: 求职被骗焦虑 -->
- <section class="report-section" data-slide-num="02" data-tone="rose">
- <div class="section-inner">
- <div class="section-head">
- <div class="section-eyebrow" style="color:var(--rose);">CHAPTER 02</div>
- <h2 class="text-h1">求职被骗焦虑</h2>
- <p class="section-sub">H6 · ${byHypothesis.H6?.length||0}条评论揭示的普遍性恐惧</p>
- </div>
- <div class="grid grid-2" style="margin-bottom:28px;">
- ${insightBanner('01','虚假宣传与货不对版','求职者极度担心招聘信息中承诺的薪资、食宿条件、工作强度与入职后实际情况严重不符。承诺月薪近万,实际到手可能仅4000多元。','6276','最高点赞', '#FF4D8D')}
- ${insightBanner('02','诈骗风险与押金陷阱','直播间看到高薪日结岗位,缴纳"入职押金"或"培训费"后招工方失联。前科主播利用虚假人设和"官方合作"名义行骗。','422','次高点赞', '#EF4444')}
- </div>
- <div style="margin-bottom:24px;">
- <div class="section-eyebrow" style="color:var(--rose);margin-bottom:14px;">⚠️ 高风险焦虑类 VOC 样本</div>
- <div class="grid grid-2">
- ${highRiskVOC.slice(0,6).map(v=>vocCard(v, true)).join('')}
- </div>
- </div>
- <div class="card" style="padding:20px 24px;border-left:3px solid var(--rose);">
- <div style="font-weight:700;margin-bottom:10px;color:var(--rose);">📊 评论区典型声音</div>
- <p class="text-body">"地铁安检我知道,找中介还不如直接去地铁口问招不招人" —— 折射出求职者对中介渠道的深度不信任</p>
- <p class="text-body" style="margin-top:10px;">"我说老实话,我没工作也不找中介,全中国中介最黑" —— 对中介生态的系统性质疑</p>
- </div>
- </div>
- </section>
- <!-- Ch3: 黑中介痛点 -->
- <section class="report-section" data-slide-num="03" data-tone="red">
- <div class="section-inner">
- <div class="section-head">
- <div class="section-eyebrow" style="color:var(--red);">CHAPTER 03</div>
- <h2 class="text-h1">黑中介是核心痛点</h2>
- <p class="section-sub">H7 · ${byHypothesis.H7?.length||0}条评论 · 最集中的负面情绪</p>
- </div>
- ${barChart([
- {label:'押金不退',value:115,color:'#EF4444'},
- {label:'黑中介套路',value:157,color:'#F97316'},
- {label:'入职被坑',value:109,color:'#FF4D8D'},
- {label:'求职被骗',value:31,color:'#8B5CF6'},
- ],'#EF4444')}
- <div style="margin-top:28px;margin-bottom:24px;">
- <div class="section-eyebrow" style="color:var(--red);margin-bottom:14px;">🏴 黑中介类 VOC 高赞精选</div>
- <div class="grid grid-2">
- ${highRiskVOC.filter(v=>['黑中介','押金不退'].includes(v.keyword)).slice(0,6).map(v=>vocCard(v, true)).join('')}
- </div>
- </div>
- <div style="display:grid;grid-template-columns:repeat(2,1fr);gap:16px;">
- <div class="card" style="padding:20px 22px;border-top:3px solid var(--red);">
- <div style="font-weight:700;margin-bottom:10px;color:var(--red);">🔴 押金不退</div>
- <p class="text-sm" style="line-height:1.6;margin-bottom:12px;">租房押金、入职押金被扣押或不退还,是评论区最高频的投诉类型之一</p>
- <div style="padding:10px 14px;background:rgba(239,68,68,0.08);border-radius:6px;">
- <span style="font-size:1.2rem;font-weight:800;color:var(--red);">2209</span>
- <span class="text-xs" style="margin-left:8px;">最高点赞</span>
- </div>
- </div>
- <div class="card" style="padding:20px 22px;border-top:3px solid var(--orange);">
- <div style="font-weight:700;margin-bottom:10px;color:var(--orange);">🟠 中介套路</div>
- <p class="text-sm" style="line-height:1.6;margin-bottom:12px;">收身份证、扣押证件、高额中介费、承诺不兑现等套路层出不穷</p>
- <div style="padding:10px 14px;background:rgba(249,115,22,0.08);border-radius:6px;">
- <span style="font-size:1.2rem;font-weight:800;color:var(--orange);">491</span>
- <span class="text-xs" style="margin-left:8px;">相关最高点赞</span>
- </div>
- </div>
- </div>
- </div>
- </section>
- <!-- Ch4: 薪资透明度 -->
- <section class="report-section" data-slide-num="04" data-tone="green">
- <div class="section-inner">
- <div class="section-head">
- <div class="section-eyebrow" style="color:var(--green);">CHAPTER 04</div>
- <h2 class="text-h1">薪资透明度是核心关切</h2>
- <p class="section-sub">H3 · ${byHypothesis.H3?.length||0}条评论 · 贯穿求职决策全链路</p>
- </div>
- <div style="display:grid;grid-template-columns:repeat(2,1fr);gap:16px;margin-bottom:28px;">
- ${insightBanner('01','承诺月薪vs到手工资','求职者担心实际到手薪资与招聘承诺差距巨大。评论区出现大量"7天不给工资""领导说话难听"的控诉。','86','最高点赞', '#00DC82')}
- ${insightBanner('02','加班费计算不透明','蓝领岗位薪资结构复杂,加班费、绩效、扣款等明细不清晰,导致实际收入与预期不符','51','次高点赞', '#3B82F6')}
- </div>
- <div style="margin-bottom:24px;">
- <div class="section-eyebrow" style="color:var(--green);margin-bottom:14px;">💰 薪资焦虑类 VOC 精选</div>
- <div class="grid grid-2">
- ${topLiked.filter(v=>['工资靠谱','真实薪资'].includes(v.keyword)).slice(0,6).map(v=>vocCard(v, true)).join('')}
- </div>
- </div>
- <div class="card" style="padding:20px 24px;border-left:3px solid var(--green);">
- <div style="font-weight:700;margin-bottom:10px;color:var(--green);">📈 薪资公平性讨论</div>
- <p class="text-body">"6000倍不止,恒大夏总月工资几千万,老农民月二百" —— 折射出蓝领群体对薪资差距的社会情绪</p>
- <p class="text-body" style="margin-top:10px;">"农村扫大街每天十元还有赊账" —— 底层劳动者收入微薄,对薪资保障的强烈渴望</p>
- </div>
- </div>
- </section>
- <!-- Ch5: 快聘平台优势 -->
- <section class="report-section" data-slide-num="05" data-tone="blue">
- <div class="section-inner">
- <div class="section-head">
- <div class="section-eyebrow" style="color:var(--blue);">CHAPTER 05</div>
- <h2 class="text-h1">"10个蓝领,9个都用快手"</h2>
- <p class="section-sub">快手快聘的平台战略优势与差异化定位</p>
- </div>
- <div class="grid grid-4" style="margin-bottom:32px;">
- <div class="metric"><div class="metric-label">蓝领月活</div><div class="metric-value" style="color:var(--amber);">2.5亿</div><div class="metric-sub">去重MAU</div></div>
- <div class="metric"><div class="metric-label">带岗主播</div><div class="metric-value" style="color:var(--green);">40万+</div><div class="metric-sub">专职主播</div></div>
- <div class="metric"><div class="metric-label">入驻企业</div><div class="metric-value" style="color:var(--blue);">24万</div><div class="metric-sub">用人单位</div></div>
- <div class="metric"><div class="metric-label">年求职线索</div><div class="metric-value" style="color:var(--purple);">3.47亿</div><div class="metric-sub">2024全年</div></div>
- </div>
- <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:28px;">
- <div class="card" style="border-top:3px solid var(--amber);text-align:center;">
- <div style="font-size:2.2rem;margin-bottom:12px;">👁️</div>
- <div style="font-weight:700;color:var(--amber);margin-bottom:8px;">"眼见为实"</div>
- <p class="text-sm" style="line-height:1.6;">直播走进车间、宿舍、食堂,展示真实工作环境</p>
- </div>
- <div class="card" style="border-top:3px solid var(--green);text-align:center;">
- <div style="font-size:2.2rem;margin-bottom:12px;">🤝</div>
- <div style="font-weight:700;color:var(--green);margin-bottom:8px;">"老铁信任"</div>
- <p class="text-sm" style="line-height:1.6;">主播与粉丝长期建立熟人推荐式信任关系</p>
- </div>
- <div class="card" style="border-top:3px solid var(--blue);text-align:center;">
- <div style="font-size:2.2rem;margin-bottom:12px;">⚡</div>
- <div style="font-weight:700;color:var(--blue);margin-bottom:8px;">"零门槛"</div>
- <p class="text-sm" style="line-height:1.6;">留联系方式即可求职,无需简历复杂填报</p>
- </div>
- </div>
- <div class="card" style="padding:24px 28px;background:linear-gradient(135deg,rgba(59,130,246,0.06),transparent);">
- <div style="font-weight:700;margin-bottom:12px;">💡 快聘战略地位</div>
- <p class="text-body" style="margin-bottom:12px;">快聘在快手内部被视为<strong style="color:var(--amber);">仅次于电商的第二大战略业务板块</strong>。日活简历投递量达数十万级,2025年Q1日均投递用户数同比增长超110%。</p>
- <p class="text-body">CEO程一笑披露:快招工板块去重月活跃用户规模已达到2.5亿,蓝领招聘线上渗透率到2025-2026年可达30%,市场规模有望达到千亿人民币。</p>
- </div>
- </div>
- </section>
- <!-- Ch6: 假设验证 -->
- <section class="report-section" data-slide-num="06" data-tone="purple">
- <div class="section-inner">
- <div class="section-head">
- <div class="section-eyebrow" style="color:var(--purple);">CHAPTER 06</div>
- <h2 class="text-h1">H1-H8 假设验证</h2>
- <p class="section-sub">基于${meta.comments.toLocaleString()}条VOC的假设覆盖分析</p>
- </div>
- ${barChart(hypos.map(h=>({label:h.h+' '+h.title.slice(0,6),value:h.count,color:h.color})),'#8B5CF6')}
- <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-top:24px;">
- ${hypos.map(h=>`<div class="card" style="padding:16px 18px;border-top:2px solid ${h.color};">
- <div style="font-family:var(--font-mono);font-size:0.68rem;color:${h.color};margin-bottom:6px;font-weight:600;">${h.h}</div>
- <div style="font-size:0.85rem;line-height:1.4;margin-bottom:8px;">${h.title}</div>
- <div><span style="font-size:1.4rem;font-weight:800;color:${h.color};font-family:var(--font-head);">${h.count}</span><span class="text-xs" style="margin-left:4px;">条</span></div>
- </div>`).join('')}
- </div>
- <div class="grid grid-2" style="margin-top:24px;">
- <div class="card" style="padding:20px 22px;border-left:3px solid var(--green);">
- <div style="font-weight:700;color:var(--green);margin-bottom:10px;">✓ H1+H2 验证:快聘是主阵地</div>
- <p class="text-sm" style="line-height:1.6;">${byHypothesis.H1?.length||0}条评论覆盖。蓝领求职者确实将快手作为主要求职渠道,"10个蓝领9个用快手"得到验证。</p>
- </div>
- <div class="card" style="padding:20px 22px;border-left:3px solid var(--purple);">
- <div style="font-weight:700;color:var(--purple);margin-bottom:10px;">✓ H3+H4+H8 验证:薪资与权益是核心关切</div>
- <p class="text-sm" style="line-height:1.6;">${(byHypothesis.H3?.length||0)+(byHypothesis.H4?.length||0)+(byHypothesis.H8?.length||0)}条评论覆盖。薪资透明度、食宿条件、结算方式是求职决策的关键因素。</p>
- </div>
- </div>
- </div>
- </section>
- <!-- Ch7: 关键词分析 -->
- <section class="report-section" data-slide-num="07" data-tone="orange">
- <div class="section-inner">
- <div class="section-head">
- <div class="section-eyebrow" style="color:var(--orange);">CHAPTER 07</div>
- <h2 class="text-h1">关键词VOC覆盖</h2>
- <p class="section-sub">12个关键词的有效评论分布与情感倾向</p>
- </div>
- <div class="grid grid-3" style="margin-bottom:28px;">
- ${byKeyword.slice(0,6).map(kw=>`<div class="card" style="border-left:3px solid ${kw.items[0]?.likes > 100 ? 'var(--rose)' : 'var(--amber)'};">
- <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
- <div style="font-weight:700;">${kw.keyword}</div>
- <span class="tag orange">${kw.total}条</span>
- </div>
- ${kw.items.slice(0,3).map(v=>`<div style="font-size:0.8rem;color:var(--text-2);line-height:1.5;margin-bottom:8px;padding:8px 10px;background:var(--bg-2);border-radius:4px;">
- <span style="color:var(--amber);font-weight:600;font-family:var(--font-mono);font-size:0.72rem;">♥${fmtLikes(v.likes)}</span>
- "${truncate(v.content||'',50)}"
- </div>`).join('')}
- </div>`).join('')}
- </div>
- <div class="card" style="padding:20px 24px;border-left:3px solid var(--rose);">
- <div style="font-weight:700;margin-bottom:10px;color:var(--rose);">⚠️ 风险类关键词占比最高</div>
- <p class="text-body">"黑中介(157条)"、"押金不退(115条)"、"入职被坑(109条)" —— 风险与痛点类关键词的有效评论占比显著高于正面需求类关键词,反映出蓝领求职生态中信任危机的普遍性。</p>
- </div>
- </div>
- </section>
- <!-- Ch8: 高赞评论 -->
- <section class="report-section" data-slide-num="08" data-tone="green">
- <div class="section-inner">
- <div class="section-head">
- <div class="section-eyebrow" style="color:var(--green);">CHAPTER 08</div>
- <h2 class="text-h1">高赞评论 TOP30</h2>
- <p class="section-sub">真实用户声音,点赞最高的评论</p>
- </div>
- <div class="grid grid-2">
- ${topLiked.slice(0,14).map(v=>vocCard(v, true)).join('')}
- </div>
- </div>
- </section>
- <!-- Ch9: 策略建议 -->
- <section class="report-section" data-slide-num="09" data-tone="amber">
- <div class="section-inner">
- <div class="section-head">
- <div class="section-eyebrow">CHAPTER 09</div>
- <h2 class="text-h1">信任重建策略</h2>
- <p class="section-sub">基于VOC洞察的平台与品牌建议</p>
- </div>
- <div class="grid grid-2" style="margin-bottom:28px;">
- <div class="card" style="border-top:3px solid var(--red);">
- <div style="font-size:1.8rem;margin-bottom:12px;">🚨</div>
- <div style="font-weight:700;color:var(--red);margin-bottom:10px;">平台信任危机</div>
- <p class="text-sm" style="line-height:1.6;margin-bottom:14px;">快手对主播宣传的招聘信息基本零审核,"甚至不如被诟病多年的58同城"。有前科主播借"官方合作"名义行骗事件已发生。</p>
- <span class="tag red">监管风险加剧</span>
- </div>
- <div class="card" style="border-top:3px solid var(--orange);">
- <div style="font-size:1.8rem;margin-bottom:12px;">📉</div>
- <div style="font-weight:700;color:var(--orange);margin-bottom:10px;">B端直招占比低</div>
- <p class="text-sm" style="line-height:1.6;margin-bottom:14px;">直播间以劳务中介为主,企业自招较少,对求职者直接吸引力有限。</p>
- <span class="tag orange">结构性问题</span>
- </div>
- </div>
- <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:24px;">
- <div class="card" style="padding:18px 16px;border-left:3px solid var(--green);text-align:center;">
- <div style="font-size:1.4rem;margin-bottom:8px;">✓</div>
- <div style="font-weight:700;margin-bottom:6px;font-size:0.9rem;">零押金承诺</div>
- <p class="text-xs" style="line-height:1.5;">主动公示"不收押金"政策</p>
- </div>
- <div class="card" style="padding:18px 16px;border-left:3px solid var(--blue);text-align:center;">
- <div style="font-size:1.4rem;margin-bottom:8px;">✓</div>
- <div style="font-weight:700;margin-bottom:6px;font-size:0.9rem;">企业直招</div>
- <p class="text-xs" style="line-height:1.5;">提高B端企业直招占比</p>
- </div>
- <div class="card" style="padding:18px 16px;border-left:3px solid var(--purple);text-align:center;">
- <div style="font-size:1.4rem;margin-bottom:8px;">✓</div>
- <div style="font-weight:700;margin-bottom:6px;font-size:0.9rem;">眼见为实</div>
- <p class="text-xs" style="line-height:1.5;">直播间展示真实工作环境</p>
- </div>
- <div class="card" style="padding:18px 16px;border-left:3px solid var(--amber);text-align:center;">
- <div style="font-size:1.4rem;margin-bottom:8px;">✓</div>
- <div style="font-weight:700;margin-bottom:6px;font-size:0.9rem;">老铁背书</div>
- <p class="text-xs" style="line-height:1.5;">入职老员工真实体验分享</p>
- </div>
- </div>
- <div class="card card-accent" style="padding:20px 24px;">
- <div style="font-weight:700;margin-bottom:10px;">⚠️ 监管动向</div>
- <p class="text-body">2026年4月,人力资源社会保障部等五部门对快手等平台开展行政指导,要求做到"五个到位":资质审核到位、信息明示到位、内容审核到位、风险防范到位、处置管控到位。</p>
- </div>
- </div>
- </section>
- </main>
- <footer class="footer">
- <div>快手快聘 · 蓝领求职洞察报告</div>
- <div style="margin-top:8px;">数据来源:快手评论采集 · ${meta.comments.toLocaleString()} 条VOC · Generated by OpenClaw</div>
- <div style="margin-top:4px;">${new Date().toLocaleDateString('zh-CN')}</div>
- </footer>
- <script>
- (function(){
- const sections=document.querySelectorAll('section.report-section');
- const total=sections.length;
- const progressLine=document.getElementById('progressLine');
- const slideNow=document.getElementById('slideNow');
- const slideBar=document.getElementById('slideBar');
- const navRail=document.getElementById('navRail');
- const kbdHint=document.querySelector('.kbd-hint');
- const navDots=[];
- let currentSlide=0;
- document.getElementById('slideTotal').textContent=String(total).padStart(2,'0');
- sections.forEach((sec,i)=>{
- const dot=document.createElement('div');
- dot.className='nav-dot';
- dot.dataset.tip=sec.querySelector('.text-h1')?.textContent||'0'+(i+1);
- dot.addEventListener('click',()=>sections[i].scrollIntoView({behavior:'smooth'}));
- navRail.appendChild(dot);
- navDots.push(dot);
- });
- const observer=new IntersectionObserver((entries)=>{
- entries.forEach(entry=>{
- if(entry.isIntersecting){
- entry.target.classList.add('in-view');
- const idx=Array.from(sections).indexOf(entry.target);
- currentSlide=idx;
- updateUI(idx);
- }
- });
- },{threshold:0.5});
- sections.forEach(sec=>observer.observe(sec));
- function updateUI(idx){
- const pct=((idx+1)/total)*100;
- progressLine.style.width=pct+'%';
- slideNow.textContent=String(idx+1).padStart(2,'0');
- slideBar.style.width=pct+'%';
- navDots.forEach((dot,i)=>dot.classList.toggle('active',i===idx));
- }
- setTimeout(()=>{kbdHint.classList.add('fade');},6000);
- let ticking=false;
- window.addEventListener('scroll',()=>{
- if(!ticking){
- requestAnimationFrame(()=>{
- const scrollTop=window.scrollY;
- const docHeight=document.documentElement.scrollHeight-window.innerHeight;
- const scrollPct=(scrollTop/docHeight)*100;
- progressLine.style.width=scrollPct+'%';
- ticking=false;
- });
- ticking=true;
- }
- });
- document.querySelectorAll('.card').forEach(c=>{
- c.addEventListener('mouseenter',()=>{
- document.body.style.setProperty('--amb-x',(Math.random()*30+10)+'%');
- document.body.style.setProperty('--amb-y',(Math.random()*30+10)+'%');
- });
- });
- })(document);
- </script>
- </body>
- </html>`;
- if (!fs.existsSync(OUT_DIR)) {
- fs.mkdirSync(OUT_DIR, { recursive: true });
- }
- fs.writeFileSync(OUT_FILE, html, 'utf8');
- console.log('✅ 快手快聘 VOC 报告已生成: ' + OUT_FILE);
- console.log(' 有效VOC数据: ' + meta.comments.toLocaleString() + ' 条');
- console.log(' H假设覆盖: ' + hypos.map(h=>h.h+':'+h.count).join(', '));
|