Files
mama-box/guangchang/ceshi/index.html
deploy d5c552590e v26110803 孕期百宝箱内容核查修改(百问 / 计算器 / 测一测)
- 育儿补贴:2025 年前出生的满 3 周岁当月计入(2022-01 出生可领 1 个月)
- 心理类测试 t13/t14/t17:结果页加「不是诊断」+ 12356 热线,最低档加危机提示;t14、t17 移出「刚测出」滚动;t14 补觉计分、t17 胎动题替换
- 孕期压力:倒数第二档加求助提示,最高档改为尽快就医 + 12356
- 百问:钙铁按 DRIs 2023、叶酸持续整个孕期、胎动 28 周起数、首检血糖、筛查/确诊、生育津贴直发个人账户、对乙酰氨基酚口径等;预置评论人设穿帮修正
- 计算器:生育津贴拆国家/本省、陕西 +10 天、新生儿医保 90 天、糖耐可补做、身高去掉无依据加减、花费幼儿园大班免保教费等
- hot.json 答案摘要同步;核查清单见 research/audit-1108

Co-Authored-By: AI 助手 <noreply@local>
2026-11-08 02:53:30 +00:00

716 lines
57 KiB
HTML
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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<!-- 11-04 UGC 总开关关着时本页不展示,直接回首页(js/ugc.js) -->
<script src="../../js/ugc.js?v=26110702" data-guard></script>
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
<meta name="format-detection" content="telephone=no">
<title>测一测 · 孕妈广场</title>
<!-- 孕妈广场 · 测一测(30 个测试共用这一页,?id=t01…t30)
11-02 v1:列表 + 简版答题。
11-02 v2 用户:「每一个测一测页面都要有设计感,要做插图放进去,跟『你是什么样的妈妈』那个一样;『只在本机算,不上传』删掉」
→ 照 topic/ceshi(妈妈类型卡)重做三屏:
① 开始:大标题 + 插画主图 + 「N 种结果」小卡(每种结果一张插画);
② 答题:一题一屏、左右滑入、小脚印进度;知识题选完当场判对错 + 解析,再点「下一题」;
③ 结果:结果卡(插画 + 称号 + 标签 + 雷达 / 等级条)+ 保存结果卡 + 解读 + 小建议 + 其他结果 / 错题解析 + 再测一个。
· 插画:img/<id>_0.webp 主图,img/<id>_<k>.webp 第 k 个结果(顺序同 tests.js results),img/<id>_s.webp 小图(广场卡片 / 推荐用)。
AI 生成(同 topic/ceshi/img 的水彩画风),统一 600×600。
· 题库 tests.js(window.GC_TESTS);广场列表只引轻量的 meta.js。
· 主色按分组:常识小测(11-02 由「知识考卷」改名)珊瑚橙 / 趣味心理紫 / 闯关青绿。
· 记录:localStorage「mmbox.gcts.v1」(按 openid 分开),只用来显示「上次结果」。
· 不造数字:没有「已有 N 人测过」。
· 无 id 打开:回孕妈广场「测一测」分类。返回:带 ?c=ceshi 进来的回该分类,否则回广场。 -->
<style>
:root{--c:#7C5CFC;--cbg:#F1EDFF;--c06:rgba(124,92,252,.06);--c10:rgba(124,92,252,.10);--c20:rgba(124,92,252,.20);--c2:#E4DDFD;--ink:#1F2329;--txt:#4E5969;--sub:#86909C;--line:#EEF0F3;--soft:#F7F8FA}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%;overflow:hidden;background:#fff;color:var(--txt);font:15px/1.75 -apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif}
#scroll{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none;padding-bottom:calc(24px + env(safe-area-inset-bottom))}
#scroll::-webkit-scrollbar{display:none}
img{display:block;max-width:100%}
button{font:inherit;border:0;background:none;color:inherit;cursor:pointer;text-align:inherit}
.ic{width:20px;height:20px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.hide{position:absolute;width:0;height:0;overflow:hidden}
[hidden]{display:none !important}
.num{font-variant-numeric:tabular-nums}
mark{background:linear-gradient(transparent 62%,var(--c20) 0);color:inherit;padding:0 1px;-webkit-box-decoration-break:clone;box-decoration-break:clone}
/* 顶栏 */
.bar{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:4px;height:48px;padding:0 8px;padding-top:env(safe-area-inset-top);background:transparent;border-bottom:1px solid transparent;transition:background .2s,border-color .2s}
.bar.sh{background:#fff;border-bottom-color:var(--line)}
.bar .back{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;color:var(--ink)}
.bar .back .ic{width:22px;height:22px}
.bar .t{font-weight:600;font-size:16px;color:var(--ink)}
.view{display:none}
.view.on{display:block;animation:vin .35s ease both}
@keyframes vin{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.wrap{padding:0 20px}
.btn{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;height:46px;border-radius:99px;font-size:16px;font-weight:700;transition:transform .15s,opacity .15s;text-align:center}
.btn.pri{background:var(--c);color:#fff;box-shadow:0 6px 16px var(--c20)}
.btn.sec{background:#fff;color:var(--c);border:1px solid var(--c)}
.btn:active,.tap:active{transform:scale(.98)}
.sh2{display:flex;align-items:baseline;gap:8px;margin-bottom:14px}
.sh2 i{font-style:normal;font-size:13px;font-weight:800;color:var(--c);letter-spacing:.5px}
.sh2 b{font-size:18px;font-weight:800;color:var(--ink);line-height:1.4}
.sh2 span{margin-left:auto;font-size:12.5px;color:var(--sub)}
/* ---------- ① 开始 ---------- */
/* 11-03 用户发参考图(依恋型人格测试):「每个测试的首页内容不要太多,简明清晰」→ 全部居中、一屏放下:
顶部分组小胶囊 → 插画(圆形 + 身后两团柔光 + 小圆点)→ 大标题 → 「N 道题 · M 分钟」+ 一句话 → 两三个小标签 → 大号胶囊按钮 → 底部一行小字。
原来的「简介段落」「N 种结果插画宫格」撤掉(结果插画在结果页「其他结果」里照样能看到)。 */
#vStart{margin-top:-48px}
#vStart.on{display:flex;flex-direction:column;align-items:center;min-height:100vh;min-height:100dvh;padding:calc(58px + env(safe-area-inset-top)) 28px calc(18px + env(safe-area-inset-bottom));text-align:center;
background:radial-gradient(120% 60% at 50% 0%,var(--cbg) 0%,rgba(255,255,255,0) 70%),linear-gradient(180deg,#FFFBF8,#fff 70%)}
.s-pill{display:inline-flex;align-items:center;gap:8px;height:30px;padding:0 16px;border-radius:99px;background:var(--c06);color:var(--c);font-size:13px;font-weight:700;letter-spacing:2px}
.s-pill i{width:3px;height:3px;border-radius:50%;background:currentColor;opacity:.6}
.s-art{position:relative;width:min(64vw,250px);aspect-ratio:1;margin:clamp(14px,4vh,34px) 0 0}
.s-art .g1,.s-art .g2{position:absolute;border-radius:50%;filter:blur(2px)}
.s-art .g1{left:-14%;top:-6%;width:72%;height:72%;background:radial-gradient(circle at 40% 40%,var(--c2),var(--c06) 70%)}
.s-art .g2{right:-16%;bottom:-8%;width:66%;height:66%;background:radial-gradient(circle at 55% 55%,#E3EEDD,rgba(227,238,221,.25) 70%)}
.s-art .dt{position:absolute;width:8px;height:8px;border-radius:50%;background:var(--c20)}
.s-art .d1{right:-4%;top:6%}.s-art .d2{left:-10%;bottom:16%;width:7px;height:7px}.s-art .d3{right:18%;bottom:-6%;width:6px;height:6px}
.s-art img{position:relative;width:100%;height:100%;border-radius:50%;object-fit:cover;object-position:center 32%;border:5px solid #fff;box-shadow:0 14px 34px -10px var(--c20);background:var(--cbg)}
.s-art .hb{position:absolute;right:2%;bottom:6%;display:grid;place-items:center;width:46px;height:46px;border-radius:50%;background:#fff;color:var(--c);box-shadow:0 6px 16px -4px var(--c20)}
.s-art .hb .ic{width:24px;height:24px;stroke-width:2}
#sTitle{margin-top:clamp(18px,4.2vh,36px);font-size:clamp(25px,7.4vw,30px);font-weight:900;line-height:1.3;color:var(--ink);letter-spacing:2px;text-wrap:balance}
.s-meta{margin-top:10px;font-size:15px;color:var(--sub);letter-spacing:.5px}
.s-meta b{font-weight:600;color:var(--txt)}
.s-line{margin-top:4px;font-size:15.5px;color:var(--txt);letter-spacing:.5px}
.s-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:10px;margin-top:clamp(14px,3vh,26px)}
.s-chips span{display:inline-flex;align-items:center;gap:4px;height:32px;padding:0 15px;border-radius:99px;background:#fff;border:1px solid var(--line);box-shadow:0 3px 10px -4px rgba(0,0,0,.08);font-size:13px;color:var(--txt)}
.s-chips .hot{color:#F0704F;font-weight:700}
.s-chips .hot svg{width:13px;height:13px}
.s-go{width:100%;margin-top:auto;padding-top:clamp(18px,4vh,40px)}
#startBtn{height:56px;font-size:18px;letter-spacing:4px;background:linear-gradient(90deg,var(--c),color-mix(in srgb,var(--c) 78%,#fff));box-shadow:0 12px 26px -10px var(--c)}
#startBtn .ic{display:none}
.s-note{margin-top:14px;font-size:12.5px;color:#A9AEB8;letter-spacing:1px}
.lastr{display:inline-flex;align-items:center;gap:8px;margin-top:12px;padding:5px 12px 5px 5px;border-radius:99px;background:var(--c06);font-size:12.5px;color:var(--ink)}
.lastr img{width:24px;height:24px;border-radius:50%;object-fit:cover;border:2px solid #fff}
.lastr b{color:var(--c)}
@media (max-height:700px){.s-art{width:min(48vw,180px)}#sTitle{font-size:23px}.s-line{font-size:14.5px}.s-chips span{height:29px}}
/* ---------- ② 答题 ---------- */
#vQuiz{padding-top:4px}
.qtop{display:flex;align-items:center;justify-content:space-between;height:34px}
.qtop button{display:inline-flex;align-items:center;gap:2px;font-size:13.5px;color:var(--sub);padding:4px 8px 4px 0}
.qtop button .ic{width:16px;height:16px}
.qtop button:disabled{visibility:hidden}
.qtop .no{font-size:13px;color:var(--sub)}
.qtop .no b{font-size:18px;color:var(--c);font-weight:800}
.qtop .sc{margin-left:10px;padding:0 8px;border-radius:99px;background:var(--cbg);color:var(--c);font-size:12px;font-weight:700;line-height:22px}
.feet{display:flex;justify-content:space-between;align-items:center;height:30px;margin-top:4px;padding:0 2px}
.feet svg{width:15px;height:15px;fill:var(--c2);transition:fill .3s,transform .3s}
.feet svg:nth-child(odd){transform:translateY(-4px) rotate(-12deg)}
.feet svg:nth-child(even){transform:translateY(4px) rotate(12deg) scaleX(-1)}
.feet svg.done,.feet svg.cur{fill:var(--c)}
.feet svg.cur:nth-child(odd){transform:translateY(-4px) rotate(-12deg) scale(1.35)}
.feet svg.cur:nth-child(even){transform:translateY(4px) rotate(12deg) scaleX(-1) scale(1.35)}
.stage{margin-top:14px;transition:opacity .22s ease,transform .22s ease}
.stage.outL{opacity:0;transform:translateX(-36px)}
.stage.outR{opacity:0;transform:translateX(36px)}
.stage.inR{opacity:0;transform:translateX(36px);transition:none}
.stage.inL{opacity:0;transform:translateX(-36px);transition:none}
.qcard{position:relative;overflow:hidden;padding:20px 20px 18px;border-radius:24px;background:linear-gradient(160deg,var(--cbg),#fff 78%);box-shadow:0 8px 24px var(--c10)}
.qcard:after{content:"";position:absolute;width:120px;height:120px;right:-40px;top:-40px;border-radius:50%;background:var(--c10)}
.qcard .hd{position:relative;display:flex;align-items:center;justify-content:space-between}
.qcard .qi{width:56px;height:56px;border-radius:18px;overflow:hidden;display:grid;place-items:center;background:#fff;box-shadow:0 4px 12px var(--c10)}
.qcard .qi img{width:100%;height:100%;object-fit:cover;object-position:center 28%}
.qcard .cat{position:relative;z-index:1;height:24px;padding:0 10px;border-radius:99px;background:#fff;color:var(--c);font-size:12px;font-weight:700;line-height:24px}
.qcard h2{position:relative;margin-top:16px;font-size:20px;font-weight:800;line-height:1.5;color:var(--ink);min-height:60px;text-wrap:pretty}
.opts{display:flex;flex-direction:column;gap:10px;margin-top:16px}
.opt{position:relative;display:flex;align-items:center;gap:12px;width:100%;min-height:56px;padding:11px 46px 11px 14px;border-radius:18px;background:#fff;border:1.5px solid var(--line);text-align:left;font-size:15.5px;line-height:1.45;color:var(--ink);transition:border-color .2s,background .2s,transform .15s}
.opt:active{transform:scale(.98)}
.opt .l{flex:none;width:26px;height:26px;border-radius:9px;display:grid;place-items:center;background:var(--soft);color:var(--sub);font-size:13px;font-weight:800;transition:background .2s,color .2s}
.opt .ck{position:absolute;right:14px;top:50%;width:22px;height:22px;margin-top:-11px;border-radius:50%;background:var(--c);color:#fff;display:grid;place-items:center;transform:scale(0);transition:transform .25s cubic-bezier(.3,1.6,.5,1)}
.opt .ck .ic{width:14px;height:14px;stroke-width:2.6}
.opt.sel{border-color:var(--c);background:var(--c06);font-weight:600}
.opt.sel .l{background:var(--c);color:#fff}
.opt.sel .ck{transform:scale(1)}
/* 知识题判分 */
.opts.lock .opt{pointer-events:none}
.opt.ok{border-color:#2DB37D;background:#EFFAF4;font-weight:600}.opt.ok .l{background:#2DB37D;color:#fff}.opt.ok .ck{background:#2DB37D;transform:scale(1)}
.opt.no{border-color:#F29A9A;background:#FFF4F4}.opt.no .l{background:#EE7070;color:#fff}.opt.no .ck{background:#EE7070;transform:scale(1)}
.exp{margin-top:12px;padding:14px 16px;border-radius:18px;background:var(--soft);font-size:14px;line-height:1.75;color:var(--txt);animation:vin .3s ease both}
.exp b{display:flex;align-items:center;gap:6px;font-size:14.5px;margin-bottom:2px}
.exp.y b{color:#1E9A68}.exp.n b{color:#D9534F}
.nextb{margin-top:14px;animation:vin .3s ease both}
.qtip{margin-top:16px;text-align:center;font-size:12.5px;color:var(--sub)}
/* ---------- ③ 结果 ---------- */
#vResult{padding-top:6px}
.rcard{position:relative;overflow:hidden;padding:22px 20px 18px;border-radius:28px;background:linear-gradient(170deg,var(--c2) 0%,var(--cbg) 44%,#fff 100%);box-shadow:0 8px 24px var(--c10);text-align:center}
.rcard .o1,.rcard .o2{position:absolute;border-radius:50%;pointer-events:none}
.rcard .o1{width:220px;height:220px;right:-80px;top:-60px;background:rgba(255,255,255,.55)}
.rcard .o2{width:140px;height:140px;left:-50px;top:150px;background:var(--c06)}
.rcard .top{position:relative;display:flex;justify-content:space-between;align-items:center;font-size:12px;line-height:24px}
.rcard .top b{padding:0 10px;border-radius:99px;background:#fff;color:var(--c);font-weight:700}
.rcard .top span{color:var(--sub)}
.rcard .ava{position:relative;width:180px;height:180px;margin:14px auto 0;border-radius:32px;overflow:hidden;border:5px solid #fff;box-shadow:0 8px 24px var(--c10);background:var(--cbg)}
.rcard .ava img{width:100%;height:100%;object-fit:cover;object-position:center 30%}
.rcard .you{position:relative;margin-top:14px;font-size:13px;color:var(--sub);letter-spacing:2px}
.rcard h1{position:relative;font-size:27px;font-weight:800;line-height:1.3;color:var(--ink)}
.rcard .slo{position:relative;margin-top:6px;font-size:14.5px;color:var(--txt);line-height:1.6}
.rtags{position:relative;display:flex;justify-content:center;flex-wrap:wrap;gap:8px;margin-top:14px}
.rtags span{height:30px;padding:0 12px;border-radius:99px;background:#fff;color:var(--c);font-size:13.5px;font-weight:700;line-height:30px;white-space:nowrap;box-shadow:0 2px 8px var(--c10)}
.dims{position:relative;display:flex;align-items:center;gap:12px;margin-top:18px;padding:14px 14px 14px 8px;border-radius:20px;background:rgba(255,255,255,.85);text-align:left}
.dims>svg{flex:none;width:146px;height:128px}
.dl{flex:1;min-width:0;display:flex;flex-direction:column;gap:9px}
.dl.wide{padding-left:8px;display:grid;grid-template-columns:1fr 1fr;column-gap:16px;row-gap:10px}
.dr{display:grid;grid-template-columns:1fr auto;align-items:center;row-gap:3px;font-size:12.5px;color:var(--txt);line-height:1.3}
.dr span:first-child{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.dr .p{font-weight:700;color:var(--ink)}
.dr .tr{grid-column:1/3;height:5px;border-radius:5px;background:var(--cbg);overflow:hidden}
.dr .tr i{display:block;height:100%;width:0;border-radius:5px;background:var(--c20);transition:width .8s cubic-bezier(.3,.7,.2,1)}
.dr.me{color:var(--c);font-weight:700}.dr.me .p{color:var(--c)}.dr.me .tr i{background:var(--c)}
/* 计分 / 知识题:环 + 等级条 */
.ring{flex:none;position:relative;width:108px;height:108px;margin-left:4px}
.ring svg{width:100%;height:100%;transform:rotate(-90deg)}
.ring circle{fill:none;stroke-width:10;stroke-linecap:round}
.ring .bgc{stroke:var(--cbg)}
.ring .fg{stroke:var(--c);transition:stroke-dashoffset 1.1s cubic-bezier(.2,.7,.3,1)}
.ring .v{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center}
.ring .v b{font-size:30px;font-weight:800;line-height:1;color:var(--c)}
.ring .v b small{font-size:14px;color:var(--sub);font-weight:700}
.ring .v span{margin-top:4px;font-size:11.5px;color:var(--sub);line-height:1.3}
.lvl{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}
.lv{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:12px;font-size:12.5px;color:var(--sub);line-height:1.3}
.lv img{flex:none;width:26px;height:26px;border-radius:50%;object-fit:cover;object-position:center 26%;opacity:.55;filter:grayscale(.4)}
.lv span{flex:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.lv em{font-style:normal;font-size:11px}
.lv.me{background:var(--cbg);color:var(--c);font-weight:800}
.lv.me img{opacity:1;filter:none;box-shadow:0 0 0 2px #fff,0 0 0 3.5px var(--c)}
.rcard .brand{position:relative;margin-top:14px;font-size:11.5px;color:var(--sub);letter-spacing:.5px}
.racts{display:flex;gap:10px;margin-top:16px}
.racts .btn{flex:1;font-size:15px}
.blk{margin-top:36px}
.read{padding:18px;border-radius:24px;background:var(--soft)}
.read p{font-size:15px;line-height:1.8;color:var(--txt)}
.read p+p{margin-top:10px}
.read b{color:var(--ink)}
.read q{quotes:"「" "」";color:var(--c);font-weight:700}
.tips{display:flex;flex-direction:column;gap:10px}
.care{margin:14px 0 0;padding:14px 16px;border-radius:16px;background:#fff;border-left:4px solid var(--c);font-size:14px;line-height:1.7;color:#4E5969}
.care b{display:block;color:#1D2129;font-size:15px;margin-bottom:4px}.care p{margin:0}.care p+p{margin-top:6px}.care a{color:var(--c);font-weight:700;text-decoration:none}
.tp{display:flex;gap:14px;align-items:flex-start;padding:14px 16px;border-radius:18px;background:#fff;border:1px solid var(--line)}
.tp .n{flex:none;width:30px;font-size:30px;font-weight:800;line-height:1;color:transparent;-webkit-text-stroke:1.4px var(--c);font-variant-numeric:tabular-nums}
.tp p{font-size:14.5px;line-height:1.65;color:var(--ink)}
.others{display:flex;flex-direction:column;gap:10px}
.oth{display:flex;align-items:center;gap:14px;padding:12px 14px;border-radius:22px;background:linear-gradient(110deg,var(--cbg),#fff 80%)}
.oth img{flex:none;width:58px;height:58px;border-radius:50%;object-fit:cover;object-position:center 26%;border:3px solid #fff;box-shadow:0 4px 12px var(--c10)}
.oth b{display:block;font-size:15.5px;color:var(--ink);line-height:1.4}
.oth small{display:inline-block;margin-left:6px;padding:0 7px;border-radius:99px;background:#fff;color:var(--c);font-size:11.5px;font-weight:700;line-height:19px;vertical-align:2px}
.oth p{margin-top:2px;font-size:13px;color:var(--txt);line-height:1.55;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.rv{border-radius:22px;background:var(--soft);overflow:hidden}
.rv summary{list-style:none;display:flex;align-items:center;gap:8px;padding:15px 18px;font-size:15px;font-weight:800;color:var(--ink);cursor:pointer}
.rv summary::-webkit-details-marker{display:none}
.rv summary small{font-size:12.5px;font-weight:600;color:var(--sub)}
.rv summary .ic{margin-left:auto;width:18px;height:18px;color:var(--sub);transition:transform .2s}
.rv[open] summary .ic{transform:rotate(180deg)}
.rv .it{margin:0 12px 10px;padding:12px 14px;border-radius:16px;background:#fff;font-size:13.5px;line-height:1.7;color:var(--txt)}
.rv .it b{display:block;color:var(--ink);font-size:14.5px;line-height:1.55}
.rv .it .an{display:block;margin:4px 0 2px;color:#1E9A68;font-weight:700}
.rv .it .mi{display:block;color:#D9534F;font-size:12.5px}
.recs{display:flex;flex-direction:column;gap:10px}
.rec{display:flex;align-items:center;gap:12px;width:100%;padding:10px 12px 10px 10px;border-radius:20px;background:#fff;border:1px solid var(--line);text-align:left}
.rec img{flex:none;width:64px;height:64px;border-radius:16px;object-fit:cover;object-position:center 30%;background:var(--soft)}
.rec span{flex:1;min-width:0}
.rec b{display:block;font-size:15px;color:var(--ink);line-height:1.4}
.rec small{display:block;font-size:12.5px;color:var(--sub);line-height:1.5}
.rec em{flex:none;font-style:normal;height:28px;padding:0 12px;border-radius:99px;font-size:12.5px;font-weight:700;line-height:28px}
.rec.g-quiz em{background:#FFEEE8;color:#E8643F}.rec.g-psy em{background:#F1EDFF;color:#7C5CFC}.rec.g-game em{background:#E2F6F1;color:#13917C}.rec.g-shop em{background:#FFEEF3;color:#E9557F}
.again{margin-top:24px}
.rend{display:flex;gap:10px;margin-top:24px}.rend .btn{flex:1;min-width:0}
.foot{margin:28px 20px 0;font-size:12px;color:var(--sub);text-align:center}
.toast{position:fixed;left:50%;bottom:calc(80px + env(safe-area-inset-bottom));transform:translate(-50%,8px);max-width:300px;padding:10px 16px;border-radius:12px;background:rgba(31,35,41,.88);color:#fff;font-size:13.5px;line-height:1.6;text-align:center;opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;z-index:60}
.toast.on{opacity:1;transform:translate(-50%,0)}
.mask{position:fixed;inset:0;z-index:50;display:none;flex-direction:column;align-items:center;justify-content:center;padding:24px 28px calc(24px + env(safe-area-inset-bottom));background:rgba(20,16,40,.82)}
.mask.on{display:flex;animation:vin .25s ease both}
.mask img{max-width:100%;max-height:calc(100% - 96px);border-radius:16px;box-shadow:0 12px 32px rgba(0,0,0,.25);-webkit-touch-callout:default;user-select:auto}
.mask p{margin-top:14px;color:#fff;font-size:14.5px;font-weight:600;display:flex;align-items:center;gap:6px}
.mask .row{display:flex;gap:16px;margin-top:10px}
.mask .row button,.mask .row a{height:34px;padding:0 18px;border-radius:99px;border:1px solid rgba(255,255,255,.6);color:#fff;font-size:13.5px;line-height:32px;text-decoration:none}
.fade{opacity:0;transform:translateY(12px);transition:opacity .45s ease,transform .45s ease}
.fade.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.fade,.stage,.view.on,.mask.on{opacity:1;transform:none;transition:none;animation:none}}
</style>
<link rel="stylesheet" href="../../topic/_shared/quiz-skin.css?v=26110643"><!-- 11-07 答题页底色 / 卡片 -->
</head>
<body>
<svg class="hide" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
<symbol id="i-user" viewBox="0 0 24 24"><path d="M16 19v-1a4 4 0 00-4-4H8a4 4 0 00-4 4v1M10 10a3 3 0 100-6 3 3 0 000 6zM20 19v-1a4 4 0 00-3-3.9M15 4.1a3 3 0 010 5.8"/></symbol>
<symbol id="i-back" viewBox="0 0 24 24"><path d="M15 5l-7 7 7 7"/></symbol>
<symbol id="i-arrow" viewBox="0 0 24 24"><path d="M5 12h13M13 6.5l5.5 5.5-5.5 5.5"/></symbol>
<symbol id="i-check" viewBox="0 0 24 24"><path d="M5 12.5l4.5 4.5L19 7.5"/></symbol>
<symbol id="i-x" viewBox="0 0 24 24"><path d="M7 7l10 10M17 7L7 17"/></symbol>
<symbol id="i-list" viewBox="0 0 24 24"><path d="M9 6.5h10M9 12h10M9 17.5h10M4.5 6.5h.01M4.5 12h.01M4.5 17.5h.01"/></symbol>
<symbol id="i-bulb" viewBox="0 0 24 24"><path d="M9 18h6M10 21h4M12 3a6 6 0 0 0-3.5 10.9c.6.5 1 1.2 1 2.1h5c0-.9.4-1.6 1-2.1A6 6 0 0 0 12 3z"/></symbol>
<symbol id="i-heart" viewBox="0 0 24 24"><path d="M12 20s-7.5-4.6-7.5-10A4.3 4.3 0 0 1 12 7.5 4.3 4.3 0 0 1 19.5 10c0 5.4-7.5 10-7.5 10z"/></symbol>
<symbol id="i-down" viewBox="0 0 24 24"><path d="M12 4v11M7.5 11l4.5 4.5 4.5-4.5M5 19.5h14"/></symbol>
<symbol id="i-chev" viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></symbol>
<symbol id="i-refresh" viewBox="0 0 24 24"><path d="M20 12a8 8 0 1 1-2.4-5.7M20 4v4.5h-4.5"/></symbol>
<symbol id="i-hand" viewBox="0 0 24 24"><path d="M9 11V5.5a1.5 1.5 0 0 1 3 0V10M12 9.5V4.5a1.5 1.5 0 0 1 3 0V10M15 9.5V6a1.5 1.5 0 0 1 3 0v8a6.5 6.5 0 0 1-6.5 6.5h-.6a6 6 0 0 1-4.6-2.2L4 15.5a1.6 1.6 0 0 1 2.4-2.1L9 15.5V11"/></symbol>
<symbol id="i-foot" viewBox="0 0 24 24"><path d="M12 9c3 0 4.6 2.7 4.6 6.3S14.8 22 12 22s-4.6-3.1-4.6-6.7S9 9 12 9z"/><circle cx="7.6" cy="6.6" r="1.6"/><circle cx="10.6" cy="4.4" r="1.75"/><circle cx="14" cy="4.6" r="1.6"/><circle cx="16.8" cy="6.8" r="1.35"/></symbol>
</svg>
<div id="scroll">
<header class="bar" id="bar">
<button class="back" id="back" aria-label="返回"><svg class="ic"><use href="#i-back"/></svg></button>
<span class="t">测一测</span>
</header>
<!-- ① 开始(11-03 参考图版:居中、一屏放下) -->
<main class="view" id="vStart">
<span class="s-pill" id="sEb"></span>
<div class="s-art fade"><i class="g1"></i><i class="g2"></i><i class="dt d1"></i><i class="dt d2"></i><i class="dt d3"></i><img id="sPic" src="" alt=""><span class="hb"><svg class="ic" id="sHb"><use href="#i-heart"/></svg></span></div>
<h1 id="sTitle"></h1>
<p class="s-meta"><b class="num" id="sN"></b> 道题 · <b class="num" id="sMin"></b> 分钟</p>
<p class="s-line" id="sLine"></p>
<div class="s-chips" id="sChips"></div>
<div class="s-go">
<button class="btn pri" id="startBtn">开始测试</button>
<div class="lastr" id="sLast" hidden></div>
<p class="s-note" id="sNote"></p>
</div>
</main>
<!-- ② 答题 -->
<main class="view wrap" id="vQuiz">
<div class="qtop">
<button id="prevBtn"><svg class="ic"><use href="#i-back"/></svg>上一题</button>
<span><span class="no num"><b id="qNo">1</b> / <span id="qTotal"></span></span><span class="sc num" id="qOk" hidden></span></span>
</div>
<div class="feet" id="feet" aria-hidden="true"></div>
<div class="stage" id="stage">
<div class="qcard">
<div class="hd"><span class="qi"><img id="qPic" src="" alt=""></span><span class="cat" id="qCat"></span></div>
<h2 id="qTitle"></h2>
</div>
<div class="opts" id="qOpts"></div>
<div id="qExp"></div>
</div>
<p class="qtip" id="qTip"></p>
</main>
<!-- ③ 结果 -->
<main class="view wrap" id="vResult">
<article class="rcard" id="rCard">
<i class="o1"></i><i class="o2"></i>
<div class="top"><b id="rLabel"></b><span id="rDate"></span></div>
<div class="ava"><img id="rImg" src="" alt=""></div>
<p class="you" id="rYou"></p>
<h1><mark id="rName"></mark></h1>
<p class="slo" id="rLine"></p>
<div class="rtags" id="rTags"></div>
<div class="dims" id="rDims"></div>
<p class="brand" id="rBrand"></p>
</article>
<div class="racts">
<button class="btn pri" id="saveBtn"><svg class="ic"><use href="#i-down"/></svg>保存结果卡</button>
<button class="btn sec" id="againTop"><svg class="ic"><use href="#i-refresh"/></svg>再测一次</button>
</div>
<section class="blk fade"><div class="sh2"><i>01</i><b id="rReadT"></b></div><div class="read" id="rRead"></div></section>
<!-- 11-08 内容核查:心理状态类测试(tests.js 里带 care:1 的 t13 / t14 / t17)结果页加「不是诊断」+ 求助提示;最低一档加 12356 和危机提示 -->
<div class="care fade" id="rCare" hidden></div>
<section class="blk fade" id="rTipsB"><div class="sh2"><i>02</i><b>给你的小建议</b></div><div class="tips" id="rTips"></div></section>
<section class="blk fade" id="rRvB"><div class="sh2"><i>03</i><b id="rRvT"></b></div><div id="rRv"></div></section>
<section class="blk fade"><div class="sh2"><i>04</i><b>再测一个</b><span>共 30 个测试</span></div><div class="recs" id="rRecs"></div></section>
<!-- 11-07 用户:「所有测一测的结果页要有一个『返回首页』按钮,返回到测试入口,也就是列表页」→ 孕妈广场「测一测」列表(guangchang/?c=ceshi) -->
<div class="rend">
<button class="btn sec" id="againBtn"><svg class="ic"><use href="#i-refresh"/></svg>重新测试</button>
<button class="btn pri" id="listBtn"><svg class="ic"><use href="#i-list" xlink:href="#i-list"/></svg>返回首页</button>
</div>
</main>
<p class="foot">趣味测试,仅供参考;身体相关问题以医生意见为准</p>
</div>
<div class="mask" id="mask">
<img id="maskImg" alt="我的测试结果卡">
<p><svg class="ic"><use href="#i-hand"/></svg>长按图片,保存到相册</p>
<div class="row"><a id="dlBtn" download="测试结果卡.png" hidden>下载图片</a><button id="maskClose">关闭</button></div>
</div>
<div class="toast" id="toast"></div>
<script src="../../js/share-card.js?v=26110464"></script>
<script src="meta.js?v=26110803"></script>
<script src="tests.js?v=26110803"></script>
<script>
(function () {
'use strict';
var $ = function (s) { return document.querySelector(s); };
var sc = $('#scroll');
var T = window.GC_TESTS || [], TBY = {};
T.forEach(function (t) { TBY[t.id] = t; });
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); }
function haptic() { if (navigator.vibrate) navigator.vibrate(8); }
var openid = (function () { var m = (location.hash + '&' + location.search).match(/[#?&]openid=([^&#]+)/); return m ? decodeURIComponent(m[1]) : ''; })();
/* 返回孕妈广场:带 c=ceshi 进来的回「测一测」分类;身份 hash 原样带回 */
function plazaURL() { var q = new URLSearchParams(location.search); q.delete('id'); var s = q.toString(); return '../' + (s ? '?' + s : '') + location.hash; }
var t = TBY[new URLSearchParams(location.search).get('id')];
if (!t) { var q0 = new URLSearchParams(location.search); q0.set('c', 'ceshi'); q0.delete('id'); location.replace('../?' + q0.toString() + location.hash); return; }
/* 11-04 微信转发图:每个测试一张 assets/share/c/<id>.jpg(短名大字 + logo),见 js/share-card.js */
if (window.mbShare) window.mbShare('../../assets/share/c/' + t.id + '.jpg', '测一测|' + t.title.replace(/^测一测|/, ''));
/* ---------- 分组主题 ---------- */
var GROUP = {
quiz: { name: '常识小测', en: 'QUIZ', c: '#F0714F', bg: '#FFEFE9', c2: '#FFD9CB', rgb: '240,113,79' },
psy: { name: '趣味心理测试', en: 'MIND TEST', c: '#7C5CFC', bg: '#F1EDFF', c2: '#E4DDFD', rgb: '124,92,252' },
game: { name: '趣味闯关', en: 'CHALLENGE', c: '#13A08A', bg: '#E4F6F1', c2: '#C4EBE1', rgb: '19,160,138' },
shop: { name: '花钱风格', en: 'SHOPPING TYPE', c: '#E9557F', bg: '#FFEEF3', c2: '#FFD3E0', rgb: '233,85,127' }
};
var G = GROUP[t.group] || GROUP.psy, R = t.results, N = t.questions.length, KS = 'ABCD';
var st = document.documentElement.style;
st.setProperty('--c', G.c); st.setProperty('--cbg', G.bg); st.setProperty('--c2', G.c2);
st.setProperty('--c06', 'rgba(' + G.rgb + ',.06)'); st.setProperty('--c10', 'rgba(' + G.rgb + ',.10)'); st.setProperty('--c20', 'rgba(' + G.rgb + ',.22)');
document.title = t.title + ' · 测一测';
var IMG = function (k) { return 'img/' + t.id + '_' + k + '.webp'; }; /* k=0 主图;k=i+1 第 i 个结果 */
var rImg = function (r) { return r.img || IMG(R.indexOf(r) + 1); }; /* 花钱风格组按类型共用插画:results[].img */
var optT = function (o) { return typeof o === 'string' ? o : o.t; };
var isQuiz = t.type === 'quiz', isType = t.type === 'type';
/* ---------- 记录 ---------- */
var KEY = 'mmbox.gcts.v1', UID = openid || '_guest';
function store() { try { return (JSON.parse(localStorage.getItem(KEY) || '{}')[UID]) || {}; } catch (e) { return {}; } }
function saveRec(rec) { try { var o = JSON.parse(localStorage.getItem(KEY) || '{}'); o[UID] = o[UID] || {}; o[UID][t.id] = rec; localStorage.setItem(KEY, JSON.stringify(o)); } catch (e) {} }
/* ---------- 视图 + 进场动画 ---------- */
var views = { start: $('#vStart'), quiz: $('#vQuiz'), result: $('#vResult') };
var io = 'IntersectionObserver' in window ? new IntersectionObserver(function (es) {
var n = 0;
es.forEach(function (e) { if (!e.isIntersecting) return; var el = e.target; io.unobserve(el); setTimeout(function () { el.classList.add('in'); }, 60 * n++); });
}, { root: sc, threshold: .08 }) : null;
/* 11-03 用户:「重新测试后退回首页,再进来还是结果页;应该以最后所在的页面,再进来呈现对应的页面」
→ 每个测试记住最后停在哪(开始 / 第几题 / 结果),按 openid + 测试 id 存 mmbox.gcts.pos.v1,再进来回到那里 */
var PKEY = 'mmbox.gcts.pos.v1';
function pos(v) {
if (v) pos.v = v;
try { var o = JSON.parse(localStorage.getItem(PKEY) || '{}'); o[UID] = o[UID] || {}; o[UID][t.id] = { v: pos.v, cur: cur, ans: ans }; localStorage.setItem(PKEY, JSON.stringify(o)); } catch (e) {}
}
function show(name) {
pos(name);
Object.keys(views).forEach(function (k) { views[k].classList.toggle('on', k === name); });
sc.scrollTop = 0;
[].forEach.call(views[name].querySelectorAll('.fade'), function (el) { el.classList.remove('in'); if (io) { io.unobserve(el); io.observe(el); } else el.classList.add('in'); });
}
$('#back').addEventListener('click', function () {
if (views.quiz.classList.contains('on') && cur > 0) { goPrev(); return; }
if (!views.start.classList.contains('on')) { renderStart(); show('start'); return; }
location.href = plazaURL();
});
sc.addEventListener('scroll', function () { $('#bar').classList.toggle('sh', sc.scrollTop > 4); }, { passive: true });
/* ================= ① 开始 ================= */
/* 开始页一句话(11-03,参考图那种一行说清「测出什么」;原 intro 段落不再上开始页) */
var LINE = { t01: '测测你的孕期常识能打几分', t02: '看看准爸爸到底有多靠谱', t03: '新手妈妈的带娃常识小考', t04: '冲奶换尿布,新手爸爸会几样', t05: '看看待产包准备齐了没有',
t06: '新生儿护理,你知道多少', t07: '月子里的那些事,你答对几个', t08: '宝宝辅食先吃啥、怎么加', t09: '宝宝睡觉的门道,你懂几分', t10: '哺乳期吃喝,避开这些误区',
t11: '测出你是哪一种带娃风格', t12: '给家里的带娃队友打个分', t13: '看看你多快进入爸妈角色', t14: '扫一扫最近的心情小天气', t15: '测出你最信哪一种育儿方式',
t16: '你们俩带娃配合有多默契', t17: '轻松看看最近的孕期心情', t18: '你是精细讲究派,还是随意派', t19: '两个娃的日常,你是哪一款', t20: '你是哪一种带娃的长辈',
t21: '准爸爸闯关,看你能过几关', t22: '那些带娃老经验,哪些是误区', t23: '当了妈妈,你给自己留了多少', t24: '猜猜宝宝会是什么小性格', t25: '测测你的孕期幸福感有多少',
t26: '测出你挑母婴用品最看重啥', t27: '测出你的母婴下单风格', t28: '囤货党,还是够用就好', t29: '8 种类型,看你怎么给娃花钱', t30: '一份清单,测出你怎么挑东西' };
var KIND = { quiz: '知识小测', psy: '心理向测试', game: '闯关小游戏', shop: '消费类型测试' };
var FIRE = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12.6 2.5c.4 3-1.6 4.6-3 6.2C8 10.4 7 12 7 14.3A5 5 0 0012 19.5a5 5 0 005-5.2c0-2-1-3.6-1.9-4.6-.2 1.3-.9 2.2-1.9 2.6.6-3.4-.2-7-.6-9.8z" fill="currentColor"/></svg>';
function renderStart() {
$('#sEb').innerHTML = esc(G.name) + '<i></i>' + esc(window.GC_SHORT && GC_SHORT[t.id] || t.title);
$('#sTitle').textContent = t.title;
$('#sN').textContent = N; $('#sMin').textContent = t.minutes || 3;
$('#sLine').textContent = LINE[t.id] || (t.sub || '').split('·').pop().trim();
$('#sPic').src = IMG(0); $('#sPic').alt = t.title;
$('#sHb').innerHTML = '<use href="#' + (isQuiz ? 'i-bulb' : 'i-heart') + '"/>';
var c = [(isType ? R.length + ' 种结果' : isQuiz ? R.length + ' 个称号' : R.length + ' 档状态'), KIND[t.group] || '趣味测试'];
$('#sChips').innerHTML = c.map(function (x) { return '<span>' + esc(x) + '</span>'; }).join('') +
(window.gcTestedText ? '<span class="hot">' + FIRE + gcTestedText(t.id) + '</span>' : '');
$('#sNote').textContent = isQuiz ? '每题选完 · 马上看解析' : '凭第一感觉选 · 没有对错之分';
var last = store()[t.id], lr = last && R.filter(function (r) { return r.title === last.title; })[0], el = $('#sLast');
if (lr) { el.hidden = false; el.innerHTML = '<img src="' + rImg(lr) + '" alt=""><span>上次结果:<b>' + esc(lr.title) + '</b>' + (last.score ? ' · <span class="num">' + esc(last.score) + '</span>' : '') + '</span>'; }
else el.hidden = true;
$('#startBtn').textContent = lr ? '再测一次' : '开始测试';
}
/* ================= ② 答题 ================= */
var cur = 0, ans = [], busy = false, stage = $('#stage');
$('#qTotal').textContent = N;
$('#feet').innerHTML = t.questions.map(function () { return '<svg viewBox="0 0 24 24"><use href="#i-foot"/></svg>'; }).join('');
var feet = document.querySelectorAll('#feet svg');
$('#qPic').src = IMG(0);
$('#qTip').textContent = isQuiz ? '选一个答案,马上看解析' : '选完自动进入下一题';
function okCount() { var n = 0; ans.forEach(function (a, i) { if (a === t.questions[i].a) n++; }); return n; }
function paint() {
var q = t.questions[cur];
$('#qNo').textContent = cur + 1;
[].forEach.call(feet, function (f, i) { f.setAttribute('class', i < cur ? 'done' : i === cur ? 'cur' : ''); });
$('#qCat').textContent = isQuiz ? '单选 · 有标准答案' : G.name;
$('#qTitle').textContent = q.q;
$('#qOpts').className = 'opts';
$('#qOpts').innerHTML = q.opts.map(function (o, i) {
return '<button class="opt" data-i="' + i + '"><span class="l">' + KS[i] + '</span><span>' + esc(optT(o)) + '</span><span class="ck"><svg class="ic"><use href="#i-check"/></svg></span></button>';
}).join('');
$('#qExp').innerHTML = '';
$('#prevBtn').disabled = cur === 0;
if (isQuiz) { var k = $('#qOk'); k.hidden = !ans.length; k.textContent = '答对 ' + okCount(); }
if (ans[cur] != null) mark(ans[cur], true);
if (pos.v === 'quiz') pos();
}
function mark(i, replay) {
var bs = $('#qOpts').querySelectorAll('.opt');
if (!isQuiz) { [].forEach.call(bs, function (x, k) { x.classList.toggle('sel', k === i); }); return; }
var q = t.questions[cur], ok = i === q.a;
$('#qOpts').classList.add('lock');
bs[q.a].classList.add('ok');
if (!ok) { bs[i].classList.add('no'); bs[i].querySelector('.ck').innerHTML = '<svg class="ic"><use href="#i-x"/></svg>'; }
$('#qExp').innerHTML = '<div class="exp ' + (ok ? 'y' : 'n') + '"><b>' + (ok ? '答对啦' : '差一点,正确答案是 ' + KS[q.a]) + '</b>' + esc(q.exp || '') + '</div>' +
'<button class="btn pri nextb" id="nextBtn">' + (cur === N - 1 ? '看我的结果' : '下一题') + '<svg class="ic"><use href="#i-arrow"/></svg></button>';
var k = $('#qOk'); k.hidden = false; k.textContent = '答对 ' + okCount();
if (!replay) setTimeout(function () { var r = $('#nextBtn').getBoundingClientRect(); if (r.bottom > innerHeight - 20) sc.scrollBy({ top: r.bottom - innerHeight + 40, behavior: 'smooth' }); }, 80);
}
function swap(dir, after) {
busy = true;
stage.classList.add(dir > 0 ? 'outL' : 'outR');
setTimeout(function () {
after(); sc.scrollTop = 0;
stage.classList.remove('outL', 'outR'); stage.classList.add(dir > 0 ? 'inR' : 'inL');
void stage.offsetWidth;
stage.classList.remove('inR', 'inL');
setTimeout(function () { busy = false; }, 220);
}, 220);
}
function goNext() { if (cur < N - 1) swap(1, function () { cur++; paint(); }); else { busy = false; finish(); } }
function goPrev() { if (busy || cur === 0) return; swap(-1, function () { cur--; paint(); }); }
$('#qOpts').addEventListener('click', function (e) {
var b = e.target.closest('.opt'); if (!b || busy || this.classList.contains('lock')) return;
haptic(); ans[cur] = +b.dataset.i; mark(ans[cur]);
if (!isQuiz) { busy = true; setTimeout(goNext, 380); }
});
$('#qExp').addEventListener('click', function (e) { if (e.target.closest('#nextBtn') && !busy) { haptic(); goNext(); } });
$('#prevBtn').addEventListener('click', goPrev);
function startQuiz() { cur = 0; ans = []; busy = false; stage.classList.remove('outL', 'outR', 'inL', 'inR'); paint(); show('quiz'); }
$('#startBtn').addEventListener('click', function () { haptic(); startQuiz(); });
$('#againBtn').addEventListener('click', startQuiz);
/* 11-07 结果页「返回首页」= 回测试列表(孕妈广场「测一测」分类),查询参数和身份 hash 原样带上 */
$('#listBtn').addEventListener('click', function () { var q = new URLSearchParams(location.search); ['id', 'c', 'n', 't'].forEach(function (k) { q.delete(k); }); q.set('c', 'ceshi'); location.href = '../?' + q.toString() + location.hash; });
$('#againTop').addEventListener('click', startQuiz);
/* ================= ③ 计分 ================= */
function band(v) { var r = R[0]; R.forEach(function (x) { if (x.min != null && v >= x.min) r = x; }); return r; }
var res = null;
function finish(old) { /* old = 上次的记录:回到结果页时按存下的答案重算、不重新落记录 */
var qs = t.questions;
if (isQuiz) {
var ok = okCount(); res = { r: band(ok), v: ok, p: ok / N, score: ok + '/' + N };
} else if (t.type === 'score') {
var s = 0, mx = 0;
qs.forEach(function (q, i) { s += (q.opts[ans[i]] || {}).s || 0; mx += Math.max.apply(null, q.opts.map(function (o) { return o.s || 0; })); });
var idx = Math.round(s / (mx || 1) * 100); res = { r: band(s), v: idx, p: idx / 100, score: (t.vlabel || '指数') + ' ' + idx };
} else {
var cnt = {}, last = {};
R.forEach(function (r) { cnt[r.k] = 0; last[r.k] = -1; });
qs.forEach(function (q, i) { var o = q.opts[ans[i]]; if (o) { cnt[o.k] = (cnt[o.k] || 0) + 1; last[o.k] = i; } });
var max = Math.max.apply(null, R.map(function (r) { return cnt[r.k]; }));
var tied = R.filter(function (r) { return cnt[r.k] === max; });
tied.sort(function (a, b) { return last[b.k] - last[a.k]; }); /* 并列:越靠后的题越接近真实状态 */
var pc = {}, rest = 100; R.forEach(function (r) { pc[r.k] = Math.round(cnt[r.k] / N * 100); rest -= pc[r.k]; }); pc[tied[0].k] += rest;
res = { r: tied[0], cnt: cnt, pc: pc, score: '' };
}
res.ans = ans.slice(); res.at = old ? old.at : Date.now();
if (!old) saveRec({ title: res.r.title, score: res.score, at: res.at, ans: res.ans });
renderResult();
}
/* ================= ③ 渲染结果 ================= */
function ringHTML(p, big, small) {
var C = 2 * Math.PI * 52;
return '<div class="ring"><svg viewBox="0 0 124 124"><circle class="bgc" cx="62" cy="62" r="52"/><circle class="fg" cx="62" cy="62" r="52" stroke-dasharray="' + C.toFixed(1) +
'" stroke-dashoffset="' + C.toFixed(1) + '" data-to="' + (C * (1 - Math.max(.03, Math.min(1, p)))).toFixed(1) + '"/></svg><div class="v"><b class="num">' + big + '</b><span>' + small + '</span></div></div>';
}
function radarSVG() {
var n = R.length, cx = 68, cy = 66, Rr = 44, M = 0, g = '';
R.forEach(function (r) { M = Math.max(M, res.pc[r.k]); }); M = Math.max(40, Math.ceil(M / 10) * 10);
var ang = function (i) { return -Math.PI / 2 + i * 2 * Math.PI / n; };
[1 / 3, 2 / 3, 1].forEach(function (f) {
g += '<polygon points="' + R.map(function (r, i) { return (cx + Math.cos(ang(i)) * Rr * f).toFixed(1) + ',' + (cy + Math.sin(ang(i)) * Rr * f).toFixed(1); }).join(' ') + '" fill="none" stroke="' + G.c2 + '" stroke-width="1"/>';
});
R.forEach(function (r, i) { g += '<line x1="' + cx + '" y1="' + cy + '" x2="' + (cx + Math.cos(ang(i)) * Rr).toFixed(1) + '" y2="' + (cy + Math.sin(ang(i)) * Rr).toFixed(1) + '" stroke="' + G.c2 + '"/>'; });
var pts = R.map(function (r, i) { var d = Math.max(res.pc[r.k] / M, .06) * Rr; return [cx + Math.cos(ang(i)) * d, cy + Math.sin(ang(i)) * d]; });
g += '<polygon points="' + pts.map(function (p) { return p[0].toFixed(1) + ',' + p[1].toFixed(1); }).join(' ') + '" fill="rgba(' + G.rgb + ',.18)" stroke="' + G.c + '" stroke-width="2" stroke-linejoin="round"/>';
pts.forEach(function (p, i) { g += '<circle cx="' + p[0].toFixed(1) + '" cy="' + p[1].toFixed(1) + '" r="' + (R[i] === res.r ? 4.5 : 3.2) + '" fill="' + G.c + '" stroke="#fff" stroke-width="1.5"/>'; });
R.forEach(function (r, i) {
var c = Math.cos(ang(i)), s = Math.sin(ang(i));
var x = cx + c * (Rr + 8), y = cy + s * (Rr + 8) + 4, a = Math.abs(c) < .2 ? 'middle' : c > 0 ? 'start' : 'end';
if (s < -.9) y -= 3; if (s > .9) y += 6;
g += '<text x="' + x.toFixed(1) + '" y="' + y.toFixed(1) + '" text-anchor="' + a + '" font-size="11" font-weight="' + (r === res.r ? 800 : 500) + '" fill="' + (r === res.r ? G.c : '#86909C') + '">' + esc(r.tag) + '</text>';
});
return '<svg viewBox="-16 -2 168 140" role="img" aria-label="各类型占比">' + g + '</svg>';
}
function renderResult() {
var r = res.r;
$('#rLabel').textContent = isType ? '我的类型卡' : isQuiz ? '我的考卷成绩单' : '我的测试结果卡';
var d = new Date(res.at); $('#rDate').textContent = (d.getMonth() + 1) + '月' + d.getDate() + '日';
$('#rImg').src = rImg(r); $('#rImg').alt = r.title;
$('#rYou').textContent = isType ? '你是' : isQuiz ? '你获得了称号' : '你的结果是';
$('#rName').textContent = r.title;
$('#rLine').textContent = r.line || t.title;
var tags = [r.tag, isQuiz ? '答对 ' + res.v + ' / ' + N : isType ? '占 ' + res.pc[r.k] + '%' : (t.vlabel || '指数') + ' ' + res.v];
$('#rTags').innerHTML = tags.map(function (x) { return '<span>' + esc(x) + '</span>'; }).join('');
if (isType) {
var sorted = R.slice().sort(function (a, b) { return (b === r) - (a === r) || res.pc[b.k] - res.pc[a.k]; });
$('#rDims').innerHTML = (R.length <= 5 ? radarSVG() : '') + '<div class="dl' + (R.length > 5 ? ' wide' : '') + '">' + sorted.map(function (x) {
return '<div class="dr' + (x === r ? ' me' : '') + '"><span>' + esc(x.title) + '</span><span class="p num">' + res.pc[x.k] + '%</span><span class="tr"><i data-w="' + res.pc[x.k] + '"></i></span></div>';
}).join('') + '</div>';
} else {
var ring = isQuiz ? ringHTML(res.p, res.v + '<small>/' + N + '</small>', '答对题数') : ringHTML(res.p, res.v, '满分 100');
$('#rDims').innerHTML = ring + '<div class="lvl">' + R.slice().reverse().map(function (x) {
return '<div class="lv' + (x === r ? ' me' : '') + '"><img src="' + rImg(x) + '" alt=""><span>' + esc(x.title) + '</span>' + '</div>';
}).join('') + '</div>';
}
$('#rBrand').textContent = '兜爸心选 · 孕妈广场 · 测一测';
/* 01 解读:先给结果原文,再结合本次作答说一句 */
$('#rReadT').textContent = isType ? '你是这样的人' : '结果解读';
var html = '<p>' + esc(r.text) + '</p>';
if (isType) {
var picks = []; t.questions.forEach(function (q, i) { var o = q.opts[res.ans[i]]; if (o && o.k === r.k) picks.push(i); });
var qi = picks[picks.length - 1], ex = t.questions[qi];
html += '<p>' + N + ' 道题里,你有 <b class="num">' + picks.length + '</b> 次选了「' + esc(r.title) + '」的答案' +
(ex ? ',比如「' + esc(ex.q.replace(/[??]$/, '')) + '」,你选了<q>' + esc(optT(ex.opts[res.ans[qi]])) + '</q>' : '') + '。</p>';
var sec = R.filter(function (x) { return x !== r && res.cnt[x.k] > 0; }).sort(function (a, b) { return res.cnt[b.k] - res.cnt[a.k]; })[0];
if (sec) html += '<p>你的另一面是<b>「' + esc(sec.title) + '」</b>(<span class="num">' + res.pc[sec.k] + '%</span>),' + esc(sec.tag) + '的那一面也常常冒出来。</p>';
} else if (isQuiz) {
html += '<p>' + N + ' 道题你答对了 <b class="num">' + res.v + '</b> 道' + (res.v === N ? ',一道没错,太厉害了。' : ',没答对的 ' + (N - res.v) + ' 道都在下面「错题解析」里,花一分钟看完就都会了。') + '</p>';
} else {
var full = 0; t.questions.forEach(function (q, i) { var o = q.opts[res.ans[i]], m = Math.max.apply(null, q.opts.map(function (x) { return x.s || 0; })); if (o && o.s === m) full++; });
var nx = R[R.indexOf(r) + 1];
html += '<p>' + N + ' 道题里,有 <b class="num">' + full + '</b> 道你的状态是满格的,综合指数 <b class="num">' + res.v + '</b>。' + (nx && !(t.care && R.indexOf(r) === 0) ? '离「' + esc(nx.title) + '」不远了,下面的小建议挑一条试试。' : nx ? '下面这几条建议,挑一条今天就做。' : '已经是最高一档啦,继续保持。') + '</p>';
}
$('#rRead').innerHTML = html;
var low = t.care && R.indexOf(r) === 0;
$('#rCare').hidden = !t.care;
if (t.care) $('#rCare').innerHTML = low
? '<b>这些感受值得认真对待</b><p>这个小测试只帮你了解最近的状态,不是医学诊断。如果低落、紧张、睡不好已经持续两周左右,别等下次产检或复查,尽快去医院产科、心理科说一说;也可以拨打 <a href="tel:12356">12356</a> 心理援助热线。</p><p>如果出现伤害自己或宝宝的念头,请马上告诉身边的人,并立即就医或拨打 <a href="tel:120">120</a>。</p>'
: '<p>这个小测试只帮你了解最近的状态,不是医学诊断。如果情绪不好持续两周以上,记得找医生聊聊,也可以拨打 <a href="tel:12356">12356</a> 心理援助热线。</p>';
/* 02 小建议 */
$('#rTips').innerHTML = (r.tips || []).map(function (x, i) { return '<div class="tp"><span class="n">' + (i + 1) + '</span><p>' + esc(x) + '</p></div>'; }).join('');
$('#rTipsB').hidden = !(r.tips || []).length;
/* 03 错题解析 / 其他结果 */
if (isQuiz) {
var all = t.questions.map(function (q, i) { return i; }), wrong = all.filter(function (i) { return res.ans[i] !== t.questions[i].a; });
$('#rRvT').textContent = wrong.length ? '错题解析' : '全部解析';
$('#rRv').innerHTML = '<details class="rv"' + (wrong.length && wrong.length <= 3 ? ' open' : '') + '><summary>' + (wrong.length ? '没答对的 ' + wrong.length + ' 道' : '全对!再看一遍解析') + '<small>点开看</small><svg class="ic"><use href="#i-chev"/></svg></summary>' +
(wrong.length ? wrong : all).map(function (i) {
var q = t.questions[i], a = res.ans[i];
return '<div class="it"><b>' + (i + 1) + '. ' + esc(q.q) + '</b><span class="an">正确答案:' + KS[q.a] + '. ' + esc(optT(q.opts[q.a])) + '</span>' +
(a !== q.a && a != null ? '<span class="mi">你选的:' + KS[a] + '. ' + esc(optT(q.opts[a])) + '</span>' : '') + esc(q.exp || '') + '</div>';
}).join('') + '</details>';
} else {
$('#rRvT').textContent = isType ? '其他几种类型' : '其他几档';
$('#rRv').innerHTML = '<div class="others">' + R.filter(function (x) { return x !== r; }).map(function (x) {
return '<div class="oth"><img src="' + rImg(x) + '" alt="" loading="lazy"><span><b>' + esc(x.title) + '<small>' + esc(x.tag) + '</small></b><p>' + esc(x.text) + '</p></span></div>';
}).join('') + '</div>';
}
/* 04 再测一个:没测过的优先,同组 2 个 + 别组 1 个,按 id 错开 */
var done = store(), seed = +t.id.slice(1);
var rk = function (x) { return (+x.id.slice(1) * 7 + seed) % 25; };
var pool = T.filter(function (x) { return x.id !== t.id; }).sort(function (a, b) { return (!!done[a.id] - !!done[b.id]) || rk(a) - rk(b); });
var pick = pool.filter(function (x) { return x.group === t.group; }).slice(0, 2).concat(pool.filter(function (x) { return x.group !== t.group; }).slice(0, 1));
$('#rRecs').innerHTML = pick.map(function (x) {
return '<button class="rec tap g-' + x.group + '" data-go="' + x.id + '"><img src="img/' + x.id + '_s.webp" alt="" loading="lazy"><span><b>' + esc(x.title) + '</b><small>' + x.questions.length + ' 题 · ' + GROUP[x.group].name + '</small></span><em>去测</em></button>';
}).join('');
show('result');
setTimeout(function () {
[].forEach.call(document.querySelectorAll('#rDims .tr i'), function (b) { b.style.width = b.dataset.w + '%'; });
var fg = $('#rDims .fg'); if (fg) fg.style.strokeDashoffset = fg.dataset.to;
}, 250);
}
$('#rRecs').addEventListener('click', function (e) {
var b = e.target.closest('[data-go]'); if (!b) return; haptic();
var q = new URLSearchParams(location.search); q.set('id', b.dataset.go);
location.href = location.pathname + '?' + q.toString() + location.hash;
});
/* ================= 保存结果卡:canvas → <img> 长按保存 ================= */
var FONT = '-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif';
function rr(ctx, x, y, w, h, r) { ctx.beginPath(); ctx.moveTo(x + r, y); ctx.arcTo(x + w, y, x + w, y + h, r); ctx.arcTo(x + w, y + h, x, y + h, r); ctx.arcTo(x, y + h, x, y, r); ctx.arcTo(x, y, x + w, y, r); ctx.closePath(); }
function loadImg(src) { return new Promise(function (ok, no) { var im = new Image(); im.onload = function () { ok(im); }; im.onerror = no; im.src = src; }); }
function wrapText(ctx, s, x, y, maxW, lh, maxL) {
var line = '', n = 0;
for (var i = 0; i < s.length; i++) {
var tt = line + s[i];
if (ctx.measureText(tt).width > maxW && line) {
if (++n === maxL) { ctx.fillText(line.slice(0, -1) + '…', x, y); return; }
ctx.fillText(line, x, y); y += lh; line = s[i];
} else line = tt;
}
if (line) ctx.fillText(line, x, y);
}
function drawCard(im) {
var r = res.r, W = 750, H = 1180, cv = document.createElement('canvas'); cv.width = W; cv.height = H;
var ctx = cv.getContext('2d');
var g = ctx.createLinearGradient(0, 0, W * .3, H); g.addColorStop(0, G.c2); g.addColorStop(.45, G.bg); g.addColorStop(1, '#FFFFFF');
ctx.fillStyle = g; ctx.fillRect(0, 0, W, H);
ctx.fillStyle = 'rgba(255,255,255,.55)'; ctx.beginPath(); ctx.arc(660, 90, 230, 0, 7); ctx.fill();
ctx.fillStyle = 'rgba(' + G.rgb + ',.06)'; ctx.beginPath(); ctx.arc(40, 470, 150, 0, 7); ctx.fill();
ctx.textAlign = 'center';
ctx.font = '700 24px ' + FONT;
var lb = $('#rLabel').textContent, lw = ctx.measureText(lb).width + 44;
ctx.fillStyle = '#fff'; rr(ctx, (W - lw) / 2, 52, lw, 48, 24); ctx.fill();
ctx.fillStyle = G.c; ctx.fillText(lb, W / 2, 84);
var S = 340, ix = (W - S) / 2, iy = 132;
ctx.save(); ctx.shadowColor = 'rgba(' + G.rgb + ',.18)'; ctx.shadowBlur = 36; ctx.shadowOffsetY = 12;
ctx.fillStyle = '#fff'; rr(ctx, ix - 10, iy - 10, S + 20, S + 20, 60); ctx.fill(); ctx.restore();
ctx.save(); rr(ctx, ix, iy, S, S, 52); ctx.clip();
var side = Math.min(im.naturalWidth, im.naturalHeight); ctx.drawImage(im, (im.naturalWidth - side) / 2, (im.naturalHeight - side) * .3, side, side, ix, iy, S, S); ctx.restore();
ctx.fillStyle = '#86909C'; ctx.font = '500 26px ' + FONT; ctx.fillText($('#rYou').textContent, W / 2, 540);
ctx.font = '800 60px ' + FONT;
var nw = ctx.measureText(r.title).width;
ctx.fillStyle = 'rgba(' + G.rgb + ',.22)'; ctx.fillRect((W - nw) / 2 - 6, 590, nw + 12, 22);
ctx.fillStyle = '#1F2329'; ctx.fillText(r.title, W / 2, 610);
ctx.fillStyle = '#4E5969'; ctx.font = '500 28px ' + FONT; ctx.fillText(t.title, W / 2, 662);
var tags = [].map.call(document.querySelectorAll('#rTags span'), function (s) { return s.textContent; });
ctx.font = '700 26px ' + FONT;
var ws = tags.map(function (s) { return ctx.measureText(s).width + 44; }), tw = ws.reduce(function (a, b) { return a + b; }, 0) + 16 * (tags.length - 1), x = (W - tw) / 2;
tags.forEach(function (s, i) { ctx.fillStyle = '#fff'; rr(ctx, x, 698, ws[i], 54, 27); ctx.fill(); ctx.fillStyle = G.c; ctx.fillText(s, x + ws[i] / 2, 735); x += ws[i] + 16; });
ctx.fillStyle = 'rgba(255,255,255,.9)'; rr(ctx, 60, 790, W - 120, 250, 32); ctx.fill();
ctx.textAlign = 'left'; ctx.fillStyle = '#4E5969'; ctx.font = '400 27px ' + FONT;
wrapText(ctx, r.text, 96, 846, W - 192, 44, 4);
ctx.textAlign = 'center'; ctx.fillStyle = '#86909C'; ctx.font = '500 22px ' + FONT;
ctx.fillText('兜爸心选 · 孕妈广场 · 测一测', W / 2, 1110);
return cv.toDataURL('image/png');
}
var busySave = false;
$('#saveBtn').addEventListener('click', function () {
if (!res || busySave) return; busySave = true;
loadImg($('#rImg').src).then(function (im) {
var url = drawCard(im); busySave = false;
$('#maskImg').src = url; $('#dlBtn').href = url;
$('#dlBtn').hidden = /MicroMessenger/i.test(navigator.userAgent);
$('#mask').classList.add('on');
}).catch(function () { busySave = false; toast('图片还没加载好,稍等再试一次'); });
});
$('#maskClose').addEventListener('click', function () { $('#mask').classList.remove('on'); });
$('#mask').addEventListener('click', function (e) { if (e.target === this) this.classList.remove('on'); });
var tt;
function toast(msg) { var el = $('#toast'); el.textContent = msg; el.classList.add('on'); clearTimeout(tt); tt = setTimeout(function () { el.classList.remove('on'); }, 2400); }
/* ---------- 禁止下拉回弹 ---------- */
var y0 = 0;
sc.addEventListener('touchstart', function (e) { y0 = e.touches[0].clientY; }, { passive: true });
sc.addEventListener('touchmove', function (e) {
var dy = e.touches[0].clientY - y0;
if ((sc.scrollTop <= 0 && dy > 0) || (sc.scrollTop + sc.clientHeight >= sc.scrollHeight - 1 && dy < 0)) { if (e.cancelable) e.preventDefault(); }
}, { passive: false });
document.addEventListener('touchmove', function (e) { if (!sc.contains(e.target) && !$('#mask').contains(e.target) && e.cancelable) e.preventDefault(); }, { passive: false });
renderStart();
(function () {
var p = null, rec = store()[t.id];
try { p = ((JSON.parse(localStorage.getItem(PKEY) || '{}'))[UID] || {})[t.id]; } catch (e) {}
if (p && p.v === 'quiz' && Array.isArray(p.ans)) { cur = Math.max(0, Math.min(+p.cur || 0, N - 1)); ans = p.ans.slice(0, N); paint(); show('quiz'); return; }
if (p && p.v === 'result' && rec && Array.isArray(rec.ans) && rec.ans.length === N) { ans = rec.ans.slice(); finish(rec); return; }
show('start'); /* 新进来 / 上次停在开始页 / 旧记录没存答案 */
})();
})();
</script>
<script src="../../js/last-sub.js?v=26110703"></script> <!-- 11-07 小程序刷新回到这一页(见 js/last-sub.js) -->
<script src="../../js/pv.js?v=26110653"></script> <!-- 11-07 页面访问记录(推送效果看板,见 js/pv.js) -->
</body>
</html>