- 新增 common.js: 从 shuzi.html/yangsheng.html 提取共享引擎(数字三角计算、八字五行、体质判别等纯函数+数据字典) - 新增 jiema.html: 愈心解码统一入口,整合数字性格+五行体质+今日锦囊,含付费墙(模拟支付)、分享卡片、契合度测算 - shuzi.html: 引用 common.js,删重复代码,新增返回链接+URL参数预填 - yangsheng.html: 引用 common.js,删重复代码,新增返回链接+URL参数预填 - yuxingu.html: Hero下方新增愈心解码入口卡片(含生日输入+生成按钮) - index.html: 新增愈心解码导航卡片 - CLAUDE.md: 补充项目文档和架构说明 Co-Authored-By: Claude <noreply@anthropic.com>
337 lines
15 KiB
HTML
337 lines
15 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
|
||
<title>愈心解码 · 一个生日读懂身与心</title>
|
||
<style>
|
||
:root{
|
||
--pri:#E54D42; --num:#C8923A; --num-d:#8a6d3b;
|
||
--ys:#5CB85C; --ys-d:#3f8f45;
|
||
--text:#333; --sub:#999;
|
||
--bg-start:#FFD1C7; --bg-end:#FFC8B5;
|
||
}
|
||
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
|
||
body{font-family:-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;
|
||
color:var(--text);background:linear-gradient(160deg,var(--bg-start),var(--bg-end));
|
||
min-height:100vh;padding-bottom:80px;}
|
||
.wrap{max-width:430px;margin:0 auto;padding:0 14px;}
|
||
.top{text-align:center;padding:22px 0 10px;}
|
||
.top .t{font-size:24px;font-weight:800;letter-spacing:3px;color:#fff;
|
||
text-shadow:0 2px 8px rgba(0,0,0,.15);}
|
||
.top .s{font-size:12px;color:#fff;opacity:.9;margin-top:4px;}
|
||
.card{background:#fff;border-radius:18px;padding:20px;margin:14px 0;
|
||
box-shadow:0 8px 30px rgba(0,0,0,.08);}
|
||
.tag{display:inline-block;font-size:11px;padding:3px 10px;border-radius:20px;
|
||
color:#fff;font-weight:600;margin-bottom:10px;}
|
||
.tag-num{background:var(--num);}
|
||
.tag-ys{background:var(--ys);}
|
||
|
||
/* Part1 数字 */
|
||
.hex{width:76px;height:76px;margin:6px auto 8px;display:flex;align-items:center;
|
||
justify-content:center;font-size:34px;font-weight:800;color:#fff;
|
||
background:linear-gradient(135deg,var(--num),var(--num-d));
|
||
clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);}
|
||
.p-title{text-align:center;font-size:19px;font-weight:700;color:var(--num-d);}
|
||
.p-oneline{text-align:center;font-size:13px;color:var(--sub);margin-top:4px;}
|
||
.pyr{text-align:center;margin:16px 0;}
|
||
|
||
/* Part2 体质 */
|
||
.ys-type{text-align:center;font-size:20px;font-weight:700;color:var(--ys-d);margin:4px 0;}
|
||
.ys-dir{text-align:center;font-size:13px;color:var(--sub);}
|
||
.bars{margin:16px 0 6px;}
|
||
.bar-row{display:flex;align-items:center;gap:8px;margin:7px 0;font-size:13px;}
|
||
.bar-row .lab{width:20px;text-align:center;font-weight:700;}
|
||
.bar-track{flex:1;height:14px;background:#f0f0f0;border-radius:8px;overflow:hidden;}
|
||
.bar-fill{height:100%;border-radius:8px;transition:width .6s;}
|
||
.bar-row .val{width:34px;text-align:right;color:var(--sub);}
|
||
|
||
/* 付费墙 */
|
||
.lock{position:relative;margin-top:14px;border-radius:14px;overflow:hidden;
|
||
border:1px solid #f2e6d0;}
|
||
.lock .blur{filter:blur(5px);pointer-events:none;user-select:none;
|
||
padding:16px;font-size:13px;line-height:1.9;color:#666;}
|
||
.lock .cover{position:absolute;inset:0;background:linear-gradient(180deg,
|
||
rgba(255,255,255,.4),rgba(255,255,255,.92));display:flex;flex-direction:column;
|
||
align-items:center;justify-content:center;text-align:center;padding:16px;}
|
||
.lock .cover .lk-t{font-size:15px;font-weight:700;color:var(--num-d);}
|
||
.lock .cover .lk-d{font-size:12px;color:var(--sub);margin:6px 0 12px;}
|
||
.unlock-btn{background:var(--pri);color:#fff;border:none;padding:11px 30px;
|
||
border-radius:24px;font-size:15px;font-weight:700;cursor:pointer;
|
||
box-shadow:0 4px 14px rgba(229,77,66,.35);}
|
||
.unlocked .cover{display:none;}
|
||
.unlocked .blur{filter:none;pointer-events:auto;user-select:auto;}
|
||
|
||
/* Part3 今日锦囊 */
|
||
.jn h4{font-size:14px;color:var(--ys-d);margin-bottom:8px;}
|
||
.jn .row{font-size:13px;line-height:2;color:#555;}
|
||
.jn .row b{color:var(--ys-d);}
|
||
.jn .st{font-size:12px;color:var(--sub);margin-bottom:6px;}
|
||
|
||
/* 契合度 / 分享 */
|
||
.mini-form{display:flex;gap:6px;align-items:center;justify-content:center;
|
||
flex-wrap:wrap;margin-top:10px;}
|
||
.mini-form input{width:56px;padding:9px 4px;border:1.5px solid #eee;
|
||
border-radius:9px;text-align:center;font-size:14px;}
|
||
.mini-form button,.share-btn{background:var(--pri);color:#fff;border:none;
|
||
padding:10px 20px;border-radius:22px;font-size:14px;font-weight:600;cursor:pointer;}
|
||
.share-btn{display:block;width:100%;margin-top:6px;}
|
||
.match-score{text-align:center;font-size:32px;font-weight:800;color:var(--pri);margin:8px 0 2px;}
|
||
|
||
/* 深度入口 */
|
||
.deep{display:flex;gap:10px;margin:16px 0;}
|
||
.deep a{flex:1;text-align:center;padding:13px 6px;border-radius:14px;
|
||
color:#fff;text-decoration:none;font-size:13px;font-weight:600;}
|
||
.deep .d-num{background:linear-gradient(135deg,var(--num),var(--num-d));}
|
||
.deep .d-ys{background:linear-gradient(135deg,var(--ys),var(--ys-d));}
|
||
|
||
.disc{font-size:11px;color:#fff;opacity:.8;text-align:center;line-height:1.7;
|
||
padding:14px 8px;}
|
||
.err{text-align:center;color:#fff;padding:40px 20px;font-size:15px;}
|
||
|
||
/* 分享卡片 canvas 弹层 */
|
||
.modal{position:fixed;inset:0;background:rgba(0,0,0,.6);display:none;
|
||
align-items:center;justify-content:center;z-index:99;padding:20px;}
|
||
.modal.on{display:flex;}
|
||
.modal .m-box{background:#fff;border-radius:16px;padding:16px;max-width:340px;text-align:center;}
|
||
.modal canvas{width:100%;border-radius:10px;}
|
||
.modal .m-tip{font-size:12px;color:var(--sub);margin:10px 0;}
|
||
.modal .m-close{color:var(--pri);font-size:14px;cursor:pointer;}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="wrap">
|
||
<div class="top">
|
||
<div class="t">愈心解码</div>
|
||
<div class="s">一个生日,读懂你的身与心</div>
|
||
</div>
|
||
<div id="report"></div>
|
||
<div class="disc" id="disc" style="display:none">
|
||
📋 本页面内容为文化 + 心理测评 + 健康生活方式参考,<br>
|
||
体质部分参考国标《中医体质分类与判定》,不构成医疗建议。
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 分享卡片弹层 -->
|
||
<div class="modal" id="shareModal">
|
||
<div class="m-box">
|
||
<canvas id="shareCanvas" width="540" height="720"></canvas>
|
||
<div class="m-tip">长按图片保存 · 分享给好友</div>
|
||
<div class="m-close" onclick="document.getElementById('shareModal').classList.remove('on')">关闭</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="common.js"></script>
|
||
<script>
|
||
/* ---------- 工具 ---------- */
|
||
function qp(k){return new URLSearchParams(location.search).get(k);}
|
||
function strongestEl(p){return EO.reduce((a,b)=>p[b]>p[a]?b:a,EO[0]);}
|
||
function esc(s){return (s||'').replace(/</g,'<');}
|
||
|
||
/* ---------- 精简 SVG 三角图(核心数字:I,J,K,L → M,N → O) ---------- */
|
||
function miniPyramid(v){
|
||
const base=[v.I,v.J,v.K,v.L], mid=[v.M,v.N], apex=v.O;
|
||
const CW=42,CH=40,GY=8,W=CW*4+GY*3,cx=W/2;
|
||
function cell(x,y,n,hl){
|
||
return '<rect x="'+x+'" y="'+y+'" width="'+CW+'" height="'+CH+'" rx="8" fill="'+(hl?'#C8923A':'#fff8ef')+'" stroke="#e0c48a"/><text x="'+(x+CW/2)+'" y="'+(y+CH/2+5)+'" text-anchor="middle" font-size="17" font-weight="700" fill="'+(hl?'#fff':'#8a6d3b')+'">'+(n!=null?n:'')+'</text>';
|
||
}
|
||
var s='<svg width="'+W+'" height="'+(CH*3+GY*2)+'" xmlns="http://www.w3.org/2000/svg">';
|
||
s+=cell(cx-CW/2,0,apex,true);
|
||
s+=cell(cx-CW-GY/2,CH+GY,mid[0])+cell(cx+GY/2,CH+GY,mid[1]);
|
||
base.forEach(function(n,i){ s+=cell(i*(CW+GY),(CH+GY)*2,n); });
|
||
s+='</svg>';
|
||
return s;
|
||
}
|
||
|
||
/* ---------- 今日锦囊 ---------- */
|
||
var SEASON_EL={0:'水',1:'水',2:'木',3:'木',4:'木',5:'火',6:'火',7:'火',8:'土',9:'金',10:'金',11:'水'};
|
||
var YI_JI={
|
||
木:{yi:'早睡养肝血 · 舒展拉伸 · 绿色蔬菜',ji:'久坐 · 生闷气 · 熬夜'},
|
||
火:{yi:'午休15分钟 · 菊花/莲子 · 平心静气',ji:'暴晒 · 辛辣油腻 · 过度兴奋'},
|
||
土:{yi:'规律三餐 · 健脾山药 · 饭后散步',ji:'思虑过度 · 生冷 · 暴饮暴食'},
|
||
金:{yi:'滋润养肺 · 白色食物 · 深呼吸',ji:'干燥受凉 · 悲忧 · 剧烈耗气'},
|
||
水:{yi:'早卧晚起 · 温补黑色食物 · 护腰腹',ji:'受寒 · 过劳 · 惊恐紧张'}
|
||
};
|
||
function todaySolar(){
|
||
var now=new Date(),m=now.getMonth()+1,d=now.getDate();
|
||
var cur=ST[0];
|
||
for(var i=0;i<ST.length;i++){ var t=ST[i];if(m>t.m||(m===t.m&&d>=t.d)) cur=t; }
|
||
return cur;
|
||
}
|
||
|
||
/* ---------- 主渲染 ---------- */
|
||
function render(){
|
||
var y=+qp('y'),m=+qp('m'),d=+qp('d');
|
||
var box=document.getElementById('report');
|
||
if(!y||!m||!d||y<1900||y>2100){
|
||
box.innerHTML='<div class="err">缺少有效生日参数,请从首页重新进入 🙏</div>';return;
|
||
}
|
||
document.getElementById('disc').style.display='block';
|
||
|
||
// === 数字引擎 ===
|
||
var v=calc(y,m,d);
|
||
var mainNum=v.O;
|
||
var person=NUM[mainNum]||{title:'',pos:'',neg:'',job:'',desc:''};
|
||
|
||
// === 养生引擎(无时辰,默认午时12点) ===
|
||
var bz=getBazi(new Date(y,m-1,d),12);
|
||
var p5=calc5E(bz);
|
||
var strong=strongestEl(p5);
|
||
var cst=getConst(p5);
|
||
var emo=getEmotion(strong);
|
||
|
||
// === 今日锦囊 ===
|
||
var st=todaySolar();
|
||
var sEl=SEASON_EL[new Date().getMonth()];
|
||
var yj=YI_JI[sEl];
|
||
|
||
var paid=localStorage.getItem('jiema_paid')==='1';
|
||
|
||
box.innerHTML=
|
||
'<!-- Part1 数字性格 -->'+
|
||
'<div class="card">'+
|
||
'<span class="tag tag-num">数字性格</span>'+
|
||
'<div class="hex">'+mainNum+'</div>'+
|
||
'<div class="p-title">'+mainNum+'号人 · '+esc(person.title)+'</div>'+
|
||
'<div class="p-oneline">'+esc((person.desc||'').split(/[。.]/)[0])+'</div>'+
|
||
'<div class="pyr">'+miniPyramid(v)+'</div>'+
|
||
'<div class="lock '+(paid?'unlocked':'')+'" id="lock-num">'+
|
||
'<div class="blur">'+
|
||
'<b>天赋优势:</b>'+esc(person.pos)+'<br>'+
|
||
'<b>人生课题:</b>'+esc(person.neg)+'<br>'+
|
||
'<b>适合方向:</b>'+esc(person.job)+'<br>'+
|
||
'<b>能量解读:</b>'+esc(person.desc)+
|
||
'</div>'+
|
||
'<div class="cover">'+
|
||
'<div class="lk-t">🔒 解锁完整性格解读</div>'+
|
||
'<div class="lk-d">天赋优势 · 人生课题 · 适合职业 · 12组联合码</div>'+
|
||
'<button class="unlock-btn" onclick="unlock()">¥39.9 解锁 →</button>'+
|
||
'</div>'+
|
||
'</div>'+
|
||
'</div>'+
|
||
|
||
'<!-- Part2 五行体质 -->'+
|
||
'<div class="card">'+
|
||
'<span class="tag tag-ys">五行体质</span>'+
|
||
'<div class="ys-type">'+esc(cst.primary)+'</div>'+
|
||
'<div class="ys-dir">养生重点:养'+esc(cst.strong)+' · 需护'+esc(cst.weak)+'</div>'+
|
||
'<div class="bars">'+
|
||
EO.map(function(e){return '<div class="bar-row"><span class="lab" style="color:'+EC[e]+'">'+e+'</span><div class="bar-track"><div class="bar-fill" style="width:'+p5[e]+'%;background:'+EC[e]+'"></div></div><span class="val">'+p5[e]+'%</span></div>';}).join('')+
|
||
'</div>'+
|
||
'<div class="p-oneline">情绪画像:'+esc((emo.strength||[]).join(' · '))+'</div>'+
|
||
'<div class="lock '+(paid?'unlocked':'')+'" id="lock-ys">'+
|
||
'<div class="blur">'+
|
||
'<b>体质特征:</b>'+esc(cst.body)+'<br>'+
|
||
'<b>调养要点:</b>'+esc(cst.tips)+'<br>'+
|
||
'<b>易感倾向:</b>'+esc(cst.diseases)+'<br>'+
|
||
'<b>季节风险:</b>'+esc(cst.seasonRisk)+'<br>'+
|
||
'<b>食疗方向:</b>'+esc(cst.foodTherapy)+'<br>'+
|
||
'<b>作息节律:</b>'+esc(cst.dailyRhythm)+
|
||
'</div>'+
|
||
'<div class="cover">'+
|
||
'<div class="lk-t">🔒 解锁五行体质深度分析</div>'+
|
||
'<div class="lk-d">脏腑画像 · 易感倾向 · 食疗 · 运动作息方案</div>'+
|
||
'<button class="unlock-btn" onclick="unlock()">¥39.9 解锁 →</button>'+
|
||
'</div>'+
|
||
'</div>'+
|
||
'</div>'+
|
||
|
||
'<!-- Part3 今日养生锦囊(免费) -->'+
|
||
'<div class="card jn">'+
|
||
'<span class="tag tag-ys">今日养生锦囊</span>'+
|
||
'<div class="st">当前节气:'+st.n+' · 时令 '+sEl+' 当令</div>'+
|
||
'<h4>今日调养建议</h4>'+
|
||
'<div class="row"><b>宜:</b>'+yj.yi+'</div>'+
|
||
'<div class="row"><b>忌:</b>'+yj.ji+'</div>'+
|
||
'</div>'+
|
||
|
||
'<!-- 深度入口 -->'+
|
||
'<div class="deep">'+
|
||
'<a class="d-num" href="shuzi.html?y='+y+'&m='+m+'&d='+d+'">完整数字报告 →</a>'+
|
||
'<a class="d-ys" href="yangsheng.html?y='+y+'&m='+m+'&d='+d+'&h=12">完整养生方案 →</a>'+
|
||
'</div>'+
|
||
|
||
'<!-- 契合度(免费给分数) -->'+
|
||
'<div class="card">'+
|
||
'<span class="tag tag-num">测测你和 TA 的契合度</span>'+
|
||
'<div class="mini-form">'+
|
||
'<input type="number" id="tY" placeholder="年"><span>年</span>'+
|
||
'<input type="number" id="tM" placeholder="月"><span>月</span>'+
|
||
'<input type="number" id="tD" placeholder="日"><span>日</span>'+
|
||
'<button onclick="matchTest('+y+','+m+','+d+')">测算</button>'+
|
||
'</div>'+
|
||
'<div id="matchOut"></div>'+
|
||
'</div>'+
|
||
|
||
'<!-- 分享 -->'+
|
||
'<div class="card">'+
|
||
'<span class="tag tag-num">分享你的身心密码</span>'+
|
||
'<button class="share-btn" onclick="genShare(\''+mainNum+'号人 · '+esc(person.title)+'\',\''+esc(cst.primary)+'\',\'养'+esc(cst.strong)+'\')">📱 生成分享卡片</button>'+
|
||
'</div>';
|
||
}
|
||
|
||
/* ---------- 付费墙 ---------- */
|
||
function unlock(){
|
||
if(confirm('【模拟支付】\n\n解锁完整深度报告 ¥39.9\n\n确认支付?')){
|
||
localStorage.setItem('jiema_paid','1');
|
||
document.querySelectorAll('.lock').forEach(function(el){el.classList.add('unlocked');});
|
||
}
|
||
}
|
||
|
||
/* ---------- 契合度(免费仅分数,深度引导付费/双人报告) ---------- */
|
||
function matchTest(y1,m1,d1){
|
||
var y=+document.getElementById('tY').value,
|
||
m=+document.getElementById('tM').value,
|
||
d=+document.getElementById('tD').value;
|
||
if(!y||!m||!d){alert('请输入 TA 的完整生日');return;}
|
||
var a=calc(y1,m1,d1).O, b=calc(y,m,d).O;
|
||
var diff=Math.abs(a-b);
|
||
var score=92-diff*6+((a+b)%3)*3;
|
||
score=Math.max(60,Math.min(98,score));
|
||
document.getElementById('matchOut').innerHTML=
|
||
'<div class="match-score">'+score+' 分</div>'+
|
||
'<div class="lock" style="margin-top:8px">'+
|
||
'<div class="blur">你们在沟通节奏、能量互补、相处课题上的详细解读……</div>'+
|
||
'<div class="cover">'+
|
||
'<div class="lk-t">🔒 查看完整契合度解读</div>'+
|
||
'<div class="lk-d">关系能量图 · 相处建议 · 沟通指南</div>'+
|
||
'<button class="unlock-btn" onclick="alert(\'双人契合度报告 ¥129(模拟)\')">¥129 解锁 →</button>'+
|
||
'</div>'+
|
||
'</div>';
|
||
}
|
||
|
||
/* ---------- 分享卡片(纯 canvas,无外部库) ---------- */
|
||
function genShare(numTitle,constType,ysKey){
|
||
var c=document.getElementById('shareCanvas'),g=c.getContext('2d');
|
||
var W=c.width,H=c.height;
|
||
var grd=g.createLinearGradient(0,0,0,H);
|
||
grd.addColorStop(0,'#FF9F80');grd.addColorStop(1,'#FFC8B5');
|
||
g.fillStyle=grd;g.fillRect(0,0,W,H);
|
||
g.fillStyle='#fff';g.textAlign='center';
|
||
g.font='bold 40px sans-serif';g.fillText('愈心解码',W/2,90);
|
||
g.font='20px sans-serif';g.fillText('一个生日,读懂身与心',W/2,128);
|
||
// 卡片
|
||
g.fillStyle='rgba(255,255,255,.95)';
|
||
roundRect(g,60,180,W-120,380,24);g.fill();
|
||
g.fillStyle='#8a6d3b';g.font='bold 46px sans-serif';
|
||
g.fillText(numTitle,W/2,290);
|
||
g.fillStyle='#5CB85C';g.font='bold 40px sans-serif';
|
||
g.fillText(constType,W/2,390);
|
||
g.fillStyle='#666';g.font='24px sans-serif';
|
||
g.fillText('养生重点:'+ysKey,W/2,460);
|
||
g.fillStyle='#E54D42';g.font='20px sans-serif';
|
||
g.fillText('▶ 扫码测测你的身心密码',W/2,530);
|
||
g.fillStyle='#fff';g.font='18px sans-serif';
|
||
g.fillText('愈心谷 · 愈见魔方,遇见自己',W/2,H-40);
|
||
document.getElementById('shareModal').classList.add('on');
|
||
}
|
||
function roundRect(g,x,y,w,h,r){
|
||
g.beginPath();g.moveTo(x+r,y);g.arcTo(x+w,y,x+w,y+h,r);
|
||
g.arcTo(x+w,y+h,x,y+h,r);g.arcTo(x,y+h,x,y,r);g.arcTo(x,y,x+w,y,r);g.closePath();
|
||
}
|
||
|
||
render();
|
||
</script>
|
||
</body>
|
||
</html>
|