697 lines
54 KiB
HTML
697 lines
54 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<!-- 11-04 UGC 总开关关着时本页不展示,直接回首页(js/ugc.js) -->
|
||
<script src="../../js/ugc.js?v=26110432" 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}
|
||
.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}
|
||
.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>
|
||
</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>
|
||
<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>
|
||
<button class="btn sec again" id="againBtn"><svg class="ic"><use href="#i-refresh"/></svg>重新测试</button>
|
||
</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=26110432"></script>
|
||
<script src="meta.js?v=26110432"></script>
|
||
<script src="tests.js?v=26110432"></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 { '&': '&', '<': '<', '>': '>', '"': '"' }[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: '测测你是哪类育儿采购玩家', 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);
|
||
$('#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: '指数 ' + 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] + '%' : '指数 ' + 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 ? '离「' + esc(nx.title) + '」不远了,下面的小建议挑一条试试。' : '已经是最高一档啦,继续保持。') + '</p>';
|
||
}
|
||
$('#rRead').innerHTML = html;
|
||
/* 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>
|
||
</body>
|
||
</html>
|