Files
digital-psychology/shuzi.html
T

674 lines
53 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>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-LVVXH3TL04"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-LVVXH3TL04');
</script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>愈心谷数字解构</title>
<style>
@font-face { font-family:'TriangleDigits'; src:url(data:font/woff2;base64,d09GMgABAAAAAAUAAA4AAAAACHwAAASsAAIZmQAAAAAAAAAAAAAAAAAAAAAAAAAAGhYbbBxIBmAANBEQCocshhEBNgIkAxoLGAAEIAWDIgcgG9QGKC4G7Ib6hm2MRajDYhGiDhrol2EQYF1VSXrYswJPkJb83g+eA7l2QeKDmZzBKY+S2Y6GNNvdREZSoL/sv5IIQxUu06If+FX4/z+X49/WsztrTAw5kRt099ubOm5NXEAFHuBcGvAGSjDAgLDn2bZk6fIVBBISV5n1GLNAADYApcVbCydXozYtkTdtbu8OvEOS0PEgPgIdEQfiY0OwiSCOBmAPsl4AYswwdCJQA1FoSBQqZkProGuMIFPAPhuoa8oSVYX8YAQSAZpDCmDZcIkm/ZAjI0LR3A1KzY56XmlDxUYMYNhtcBARzR51kKE7KkxKozJobFeXdNJlKY3czMCYMrUMa/83F2mmEHEHkFJnDXn9YBwBCSjAHYUA3NEIBjQ0BFDLHki2t3+KqVZYkbggAFQ26ho8RWcQ3tl/htql/UbHN70BAoXUbXpAnK4F+eoWL5vNxzpnKT0L1CrUld9zyZWVebLzdRVOGASMYohloBiiuziLHrm5uQI5VmbV7EqrcnVlszArq2tWV6c5C0+s7O5L1+3WqS7Q2737TCeTufqRH9o1O3uOtCpHMUc36sxupMOcNaesYEbpnGdwwlHmrs8VKBTmstgNaLvfBrx5PQ/wj1yzJd01+3LOm+/CzOY4zhHWtXYr5PbIyREYwJnHeFm4pXu2IcxByHzZVWJ3Er3bMQkX9snibM6Y1aTyc3rkXNUJPXpz8SR3SFeH84FFWYV9bzibJvHlL0bRde6KYc9cmiIKk5+FN+NThqtvc8aBGfnF6WzIqLk1ON06sNXy3bLFuIJ8DQT/QGhPY9JrsRk3RddPID33rzz9cLGnXZjvNNQR4659v7m7f0qW1qex/MqwciHDfdsqBnOLCispr6nWU0/DmAXZBdjkTA0M/4LXawb7VDhbjduWNPaWsM25jxyH1ENRUmejPPOk33dOKZ+v4BRLNZQeriawC/Nzxb0nr7/lPdzfGvGf3kgW0N6/tXYq1Si9RA/v58kV3DTY5DgaxwV1Uw5++lzxouLrgNYX82rdHtlWXSn61Di0UAxfhc2HeamcDnfrnVra3xecFNc61xtZhSxqUlFZFQ62rTQ+w3YS4S9Z4bNHHUB7y/fxoxt9pVAyqdOZ66cPKs7Oz8sYj5f2lIpvQPQfX3t4++1V80/rnFtRkIspHBjC5WXnpReTvuTiMVkJsZFp5SVhxARkdDKQhx19XV78vjqr1UAXlvCfnhUiz41CK/6P8dI6eIab2nlH17ap48+X3P/67iJUpWdlq6vNFAQABCB9dmU3fPxwgFPdb2YhMwAvzT++ByhOmZz+3/9vizVMBYAZOVthCvnfDK9OI6rfpSMQ1O8ljbVAg/Zm6S2UNDN4K6A9UySALjrjrgTjPKoUNdG7bdIswFkQgyCYswaJI28NikwKujXQYMBXOC8yEihiaSpGlAKsZbII4YSJENhVwgyBgJQEXSDaUphohpCxTCWZFJKhBY+AiHgRfBMjhobUGOI+OYREilhp4gmpjs63SFuCvHUricIo0nYoVERiSqyLCF+MnFdHwYlnbI0JjLBYonBsPGESCHYCTx5NXJ+7DhJpNTCDOrOPjGrLzlAAAAA) format('woff2'); }
* { box-sizing: border-box; margin: 0; padding: 0; }
body { background-color: #faf7f2; font-family: 'Georgia','Times New Roman','Noto Serif SC',serif; display:flex; justify-content:center; align-items:center; min-height:100vh; color:#6b5b4e; padding:10px 10px 20px; -webkit-user-select:none; user-select:none; -webkit-touch-callout:none; }
.container { position:relative; width:600px; max-width:95%; padding:12px 40px 40px; display:flex; flex-direction:column; align-items:center; }
.input-row { display:flex; gap:5px; align-items:center; margin-bottom:24px; font-family:sans-serif; }
.input-row input { width:56px; padding:6px 4px; border:1px solid #d9ccb6; border-radius:3px; font-size:14px; text-align:center; color:#6b5b4e; background:#fff; outline:none; }
.input-row input:focus { border-color:#a89580; }
.input-row .lbl { font-size:0.75em; color:#9b8a78; }
.btn-gen { padding:6px 12px; background:#8b7a68; color:#fff; border:none; border-radius:3px; font-size:0.75em; cursor:pointer; margin-left:2px; }
.btn-gen:active { opacity:0.8; }
.top-numbers { display:flex; flex-direction:column; align-items:center; margin-bottom:-20px; z-index:2; font-family:'TriangleDigits','Georgia','Times New Roman',serif; }
.top-numbers .num-top { font-size:2.2rem; font-weight:normal; }
.top-numbers .num-mid-row { display:flex; gap:60px; font-size:2.2rem; font-weight:normal; }
.triangle-wrapper { position:relative; width:300px; height:260px; margin:20px 0; display:flex; justify-content:center; align-items:center; overflow:visible; }
.triangle-svg { position:absolute; top:0; left:0; width:100%; height:100%; z-index:0; }
.triangle-path { fill:#f2ebdd; stroke:#d9ccb6; stroke-width:2; }
.divider-line { stroke:#d9ccb6; stroke-width:2; }
.inner-number { position:absolute; z-index:1; font-size:2.2rem; font-weight:bold; cursor:pointer; font-family:'TriangleDigits','Georgia','Times New Roman',serif; color:#5a4636; }
.red-num { color:#c47a78; top:25%; }
.mid-left { top:55%; left:30%; } .mid-right { top:55%; right:30%; }
.bot-1 { bottom:10%; left:18%; } .bot-2 { bottom:10%; left:38%; }
.bot-3 { bottom:10%; right:38%; } .bot-4 { bottom:10%; right:18%; }
.side-decorations { position:absolute; width:100%; height:100%; top:0; left:0; font-family:'TriangleDigits','Georgia','Times New Roman',serif; }
.side-num { position:absolute; font-size:2.2rem; opacity:0.65; cursor:pointer; font-family:'TriangleDigits','Georgia','Times New Roman',serif; font-weight:normal; color:#8b7e6e; }
.left-group { top:30%; left:-40px; text-align:right; line-height:1.5; }
.right-group { top:30%; right:-40px; text-align:left; line-height:1.5; }
.footer-date { margin-top:0; display:flex; gap:40px; font-size:1.8rem; letter-spacing:2px; color:#5a4636; font-family:'TriangleDigits','Georgia','Times New Roman',serif; }
.sections { width:100%; max-width:360px; margin-top:24px; font-family:sans-serif; font-size:1em; color:#6b5b4e; }
.divider { border:none; border-top:1px solid #e0d5c4; margin:12px 0; opacity:0.6; }
.codes .r { display:flex; justify-content:space-between; border-bottom:1px dotted rgba(168,144,112,0.15); padding:2px 4px; }
.codes .k { color:#9b8a78; } .codes .v { color:#6b5b4e; }
.joint-age { font-size:0.9em; color:#a89070; font-weight:600; text-align:center; margin:8px 0 2px; border-bottom:1px solid rgba(168,144,112,0.2); padding-bottom:2px; }
.joint-grid { display:grid; grid-template-columns:repeat(2,1fr); gap:2px 10px; }
.joint-grid .jc { font-weight:700; color:#5a4636; } .joint-grid .jm { color:#9b8a78; }
.tooltip { position:fixed; padding:5px 10px; background:#6b5b4e; color:#fff; border-radius:4px; font-size:0.7em; pointer-events:none; opacity:0; transition:opacity 0.12s; z-index:999; max-width:200px; line-height:1.5; font-family:sans-serif; }
.tooltip.on { opacity:1; }
.footer { text-align:center; font-size:0.6em; color:#9b8a78; margin-top:10px; }
.scene-3d { position:relative; display:flex; justify-content:center; margin:8px 0; cursor:grab; }
.scene-3d:active { cursor:grabbing; }
.scene-3d canvas { display:block; touch-action:none; }
.scene-hint { position:absolute; bottom:2px; left:50%; transform:translateX(-50%); font-size:0.55em; color:#b8a898; pointer-events:none; opacity:0.7; }
.freq-label { text-align:center; font-size:0.7em; color:#6b5b4e; margin-top:2px; line-height:1.8; }
.tabs-nav { display:flex; flex-wrap:wrap; gap:4px; margin-bottom:18px; justify-content:center; padding:0 4px; }
.tab-btn { padding:5px 10px; border:1px solid #d9ccb6; border-radius:3px; background:#fff; color:#9b8a78; font-size:0.7em; cursor:pointer; font-family:sans-serif; transition:all 0.15s; white-space:nowrap; }
.tab-btn:hover { border-color:#c47a78; color:#c47a78; }
.tab-btn.active { background:#c47a78; color:#fff; border-color:#c47a78; }
.tab-panel { display:none; }
.tab-panel.active { display:block; }
.tab-panel .module-title { font-size:0.82em; font-weight:600; color:#5a4636; text-align:center; margin-bottom:8px; }
.tab-panel .module-desc { font-size:0.68em; color:#9b8a78; text-align:center; margin-bottom:10px; line-height:1.6; }
.tab-panel .module-section { font-size:0.72em; color:#6b5b4e; line-height:1.75; padding:0 4px; margin-bottom:10px; }
.tab-panel .module-section b { color:#5a4636; }
.bagua-grid { display:grid; grid-template-columns:repeat(4,1fr); gap:6px; text-align:center; margin:8px 0; }
.bagua-cell { padding:6px 4px; border-radius:4px; font-size:0.68em; line-height:1.5; }
@media (max-width:600px) {
.triangle-wrapper { width:220px; height:190px; margin:10px auto 0; }
.triangle-wrapper svg { width:220px; height:190px; }
.inner-number { font-size:1.6rem; }
.red-num { top:22%; }
.mid-left { top:52%; left:28%; } .mid-right { top:52%; right:28%; }
.bot-1 { bottom:10%; left:14%; } .bot-2 { bottom:10%; left:35%; }
.bot-3 { bottom:10%; right:35%; } .bot-4 { bottom:10%; right:14%; }
.side-num { font-size:1.6rem; }
.left-group { left:-32px; top:26%; } .right-group { right:-32px; top:26%; }
.top-numbers .num-top { font-size:1.6rem; }
.top-numbers .num-mid-row { font-size:1.6rem; gap:40px; }
.footer-date { gap:14px; font-size:1.2rem; letter-spacing:0; }
}
</style>
</head>
<body>
<div class="container">
<div style="text-align:center;margin-bottom:10px;">
<h1 style="font-size:1.5em;font-weight:400;letter-spacing:0.2em;color:#5a4636;margin:0 0 6px;">愈心谷数字解构</h1>
<div style="font-size:0.65em;color:#9b8a78;letter-spacing:0.12em;margin-top:2px;">✦ 输入公历出生年月日 ✦</div>
</div>
<div class="input-row">
<input type="number" id="inY" value="1986"><span class="lbl"></span>
<input type="number" id="inM" value="2"><span class="lbl"></span>
<input type="number" id="inD" value="17"><span class="lbl"></span>
<button class="btn-gen" id="goBtn">生成</button>
</div>
<div class="top-numbers">
<div class="num-top" id="valR">3</div>
<div class="num-mid-row"><span id="valQ">4</span><span id="valP">8</span></div>
</div>
<div class="triangle-wrapper">
<svg class="triangle-svg" viewBox="0 0 300 260">
<polygon points="150,10 290,250 10,250" class="triangle-path"/>
<line x1="85" y1="130" x2="215" y2="130" class="divider-line"/>
<line x1="55" y1="190" x2="245" y2="190" class="divider-line"/>
<line x1="150" y1="130" x2="150" y2="250" class="divider-line"/>
</svg>
<div class="inner-number red-num" id="valO" style="left:50%;transform:translateX(-50%)">7</div>
<div class="inner-number mid-left" id="valM">1</div>
<div class="inner-number mid-right" id="valN">6</div>
<div class="inner-number bot-1" id="valI">8</div>
<div class="inner-number bot-2" id="valJ">2</div>
<div class="inner-number bot-3" id="valK">1</div>
<div class="inner-number bot-4" id="valL">5</div>
<div class="side-decorations">
<div class="side-num left-group" style="display:flex;flex-direction:column;align-items:center;">
<div id="valU">3</div>
<div style="display:flex;gap:8px"><span id="valT">9</span><span id="valS">3</span></div>
</div>
<div class="side-num right-group" style="display:flex;flex-direction:column;align-items:center;">
<div id="valX">9</div>
<div style="display:flex;gap:8px"><span id="valV">7</span><span id="valW">2</span></div>
</div>
</div>
</div>
<div class="footer-date">
<span id="dateD">17</span><span id="dateM">02</span><span id="dateY">1986</span>
</div>
<div class="sections">
<div class="tabs-nav">
<button class="tab-btn active" data-tab="shuzi">数字心理学</button>
<button class="tab-btn" data-tab="meihua">梅花易数</button>
<button class="tab-btn" data-tab="xiaoliuren">小六壬</button>
<button class="tab-btn" data-tab="daliuren">大六壬</button>
<button class="tab-btn" data-tab="qimen">奇门遁甲</button>
<button class="tab-btn" data-tab="xingzuo">星座</button>
<button class="tab-btn" data-tab="wuxing">五行八卦</button>
</div>
<div class="tab-panel active" id="shuzi-panel">
<div class="missing" id="missingBlock"></div>
<div class="missing-short" id="missingMsg"></div>
<hr class="divider">
<div class="codes" id="codesBlock"></div>
<div class="joint" id="jointBlock"></div>
</div>
<div class="tab-panel" id="meihua-panel"></div>
<div class="tab-panel" id="xiaoliuren-panel"></div>
<div class="tab-panel" id="daliuren-panel"></div>
<div class="tab-panel" id="qimen-panel"></div>
<div class="tab-panel" id="xingzuo-panel"></div>
<div class="tab-panel" id="wuxing-panel"></div>
<div class="footer">内在探索 · 心灵成长</div>
</div>
</div>
<div class="tooltip" id="tip"></div>
<script>
function s1(n){while(n>=10)n=String(n).split('').reduce((a,b)=>a+ +b,0);return n}
function digs(n,l){return String(n).padStart(l,'0').split('').map(Number)}
function calc(y,m,d){
const dd=digs(d,2),mm=digs(m,2),yy=digs(y,4);
const A=dd[0],B=dd[1],C=mm[0],D=mm[1],E=yy[0],F=yy[1],G=yy[2],H=yy[3];
const v={AB:[A,B],CD:[C,D],EF:[E,F],GH:[G,H]};
v.I=s1(A+B);v.J=s1(C+D);v.K=s1(E+F);v.L=s1(G+H);
v.M=s1(v.I+v.J);v.N=s1(v.K+v.L);v.O=s1(v.M+v.N);
v.Q=s1(v.N+v.O);v.P=s1(v.M+v.O);v.R=s1(v.Q+v.P);
v.T=s1(v.I+v.M);v.S=s1(v.J+v.M);v.U=s1(v.T+v.S);
v.V=s1(v.K+v.N);v.W=s1(v.L+v.N);v.X=s1(v.V+v.W);
return v;
}
const tips={
O:v=>`${v.O}=${v.M}+${v.N}`,M:v=>`${v.M}=${v.I}+${v.J}`,N:v=>`${v.N}=${v.K}+${v.L}`,
I:v=>`${v.I}=${v.AB[0]}+${v.AB[1]}`,J:v=>`${v.J}=${v.CD[0]}+${v.CD[1]}`,
K:v=>`${v.K}=${v.EF[0]}+${v.EF[1]}`,L:v=>`${v.L}=${v.GH[0]}+${v.GH[1]}`,
R:v=>`${v.R}=${v.Q}+${v.P}`,Q:v=>`${v.Q}=${v.N}+${v.O}`,P:v=>`${v.P}=${v.M}+${v.O}`,
T:v=>`${v.T}=${v.I}+${v.M}`,S:v=>`${v.S}=${v.J}+${v.M}`,U:v=>`${v.U}=${v.T}+${v.S}`,
V:v=>`${v.V}=${v.K}+${v.N}`,W:v=>`${v.W}=${v.L}+${v.N}`,X:v=>`${v.X}=${v.V}+${v.W}`,
};
const NUM={
1:{title:'创造·领导',pos:'自信、独立、开创力、领导天赋',neg:'自我中心、孤独感、固执己见',job:'创业者、管理者、艺术家、设计师',elem:'金',desc:'1号人是天生的领导者,具有强烈的开创精神和独立意识。你目标明确,行动力强,能够独自完成许多事情。但你需要注意不要过于自我,学会倾听他人意见。'},
2:{title:'沟通·温柔',pos:'善于沟通、温柔体贴、合作能力强',neg:'依赖他人、优柔寡断、情绪化',job:'公关、客服、教育、心理咨询',elem:'水',desc:'2号人天生具有细腻的情感和出色的沟通能力。你善解人意,重视人际关系,是团队中的润滑剂。需要学会独立决断,避免过度依赖他人的认可。'},
3:{title:'行动·创意',pos:'行动力强、创意无限、表达力出众',neg:'急躁冲动、三分钟热度、缺乏耐心',job:'演员、讲师、销售、创意行业',elem:'木',desc:'3号人是天生的行动派,想到就做,充满创意和热情。你的表达能力和感染力极强,总能带动周围人的情绪。需要培养耐心,把创意落地为成果。'},
4:{title:'规划·稳定',pos:'善于规划、踏实稳重、注重细节',neg:'过于保守、缺乏弹性、安全感缺失',job:'工程师、会计、策划、项目管理',elem:'木',desc:'4号人是最可靠的建设者,做事有条不紊,追求安全与稳定。你擅长把复杂的事情拆解成清晰的步骤。需要学会接受变化,适当放松对完美的执念。'},
5:{title:'自由·方向',pos:'热爱自由、方向感强、幽默风趣',neg:'难以约束、逃避责任、缺乏定性',job:'旅行家、作家、自由职业、营销',elem:'土',desc:'5号人向往自由,喜欢冒险和新鲜事物。你天生的方向感让你总能在迷茫中找到出路。需要学会在自由与责任之间找到平衡。'},
6:{title:'智慧·财富',pos:'聪明睿智、财富直觉、追求完美',neg:'挑剔苛刻、浪费资源、过分焦虑',job:'金融、投资、咨询、医疗、法律',elem:'金',desc:'6号人是天生的智者,对财富和品质有敏锐的直觉。你追求完美,注重价值,具有强大的分析判断能力。需要学会放松标准,接纳不完美。'},
7:{title:'分析·真理',pos:'深入钻研、追求真理、洞察力强',neg:'冷漠孤僻、多疑猜忌、不善社交',job:'科学家、侦探、程序员、学者',elem:'水',desc:'7号人是天生的研究者,喜欢刨根问底,追求事物的本质和真相。你的洞察力和分析能力超群,但也容易陷入自己的世界。需要多与人交流,打开心扉。'},
8:{title:'责任·商业',pos:'责任心强、商业头脑、野心勃勃',neg:'压力过大、控制欲强、过度功利',job:'企业家、管理者、投资人、政治家',elem:'土',desc:'8号人天生具有强大的责任感和商业头脑,渴望成功并愿意为之付出努力。你有掌控大局的能力,但需注意不要让事业压力压垮自己。'},
9:{title:'博爱·成功',pos:'慈悲博爱、机会多多、容易成功',neg:'贪多嚼不烂、缺乏专注、过于理想化',job:'慈善家、演员、艺术家、宗教/灵修',elem:'火',desc:'9号人拥有广阔的胸怀和强大的亲和力,容易获得他人的信任和机会。你天生带有成功的气场,但需要学会聚焦,把精力集中到最重要的事情上。'},
};
const NUM_CLR={
1:{top:[232,160,160],front:[196,122,120],right:[168,96,96]},
2:{top:[240,200,160],front:[232,168,124],right:[208,144,96]},
3:{top:[238,208,128],front:[224,184,88],right:[200,152,64]},
4:{top:[160,216,112],front:[112,173,71],right:[88,136,48]},
5:{top:[144,200,240],front:[91,155,213],right:[64,120,176]},
6:{top:[240,168,176],front:[212,135,142],right:[176,104,112]},
7:{top:[184,168,216],front:[139,122,181],right:[104,88,152]},
8:{top:[160,144,128],front:[107,91,78],right:[80,64,48]},
9:{top:[244,236,224],front:[232,220,200],right:[208,192,168]},
};
const JOINT={
'112':'做事独立有主见','123':'讲师码,善于表达传授','134':'创意执行者,想法落地',
'145':'规划型领导','156':'五方求财,到处有机会','167':'白手起家,靠自己打拼',
'178':'成就他人,贵人相助','189':'工作狂,停不下来','191':'独立开创型',
'213':'讲师号,口才出众','224':'心软码,容易心软','235':'善于沟通表达',
'246':'贵人码,销售口才','257':'凭感觉做事','268':'重情重义',
'279':'异性缘佳','281':'大单销售高手','292':'军师码,运筹帷幄',
'314':'创意执行力','325':'感性沟通','336':'连接码,资源整合',
'347':'专业钻研型','358':'行动派领袖','369':'万花筒,多才多艺',
'415':'规划执行','426':'智慧销售','437':'学术研究型',
'448':'责任码,可靠担当','459':'规划码,策划高手','461':'稳扎稳打',
'472':'精准分析','483':'专业码,技术大牛','494':'完美规划',
'516':'方向感+智慧','527':'感性直觉','538':'领导力强',
'549':'规划型成功者','551':'自由方向感','562':'学会花钱',
'573':'贵人相助型','584':'责任+规划','595':'大梦想家',
'617':'白手起家码','628':'财富+沟通','639':'多才多艺',
'641':'务实经营','652':'财富直觉','663':'完美财富',
'674':'天生傲骨,不甘平凡','685':'商业责任','696':'追求极致',
'718':'钻研+责任','729':'异性缘,桃花旺','731':'创新领导',
'742':'分析谋划','753':'凭直觉行动','764':'精打细算',
'775':'领袖码,天生王者','786':'商业责任','797':'极致钻研',
'819':'亲力亲为,事必躬亲','821':'大单销售高手','832':'行动沟通',
'843':'专业技能型','854':'规划+自由','865':'财富责任',
'876':'商业王者','887':'强势责任','898':'大事业格局',
'911':'博爱独立','922':'温柔善良','933':'手艺码,巧手匠心',
'944':'稳妥计划','955':'自由博爱','966':'完美智慧',
'977':'深入博爱','988':'商业帝国','999':'极致成功',
};
const MISS_MSG={
1:'缺乏自信与领导力,需要培养独立决断的能力',2:'沟通表达不足,需要打开心扉多与人交流',
3:'缺乏行动力与创意,需要勇敢迈出第一步',4:'缺乏规划与安全感,需要建立稳定的生活节奏',
5:'缺乏方向感与自由,需要找到真正热爱的事物',6:'缺乏智慧与财富意识,需要培养理财能力',
7:'缺乏深入钻研的精神,需要培养专注与耐心',8:'缺乏责任感与事业心,需要找到值得奋斗的目标',
9:'缺乏博爱与认同感,需要学会接纳自己与他人',
};
const MISS_STRONG={
1:'自信心爆棚,但需注意不要过于自我中心',2:'沟通能力过强,需注意避免情绪化依赖',
3:'行动力过剩,需注意避免冲动急躁',4:'过于求稳,需注意避免保守固执',
5:'过度自由,需注意避免放纵逃避',6:'完美主义过强,需注意避免挑剔焦虑',
7:'钻研过度,需注意避免孤僻多疑',8:'责任感过重,需注意避免压力过大',
9:'博爱过度,需注意避免贪多不精',
};
// ===== Dimetric 投影 + Z 轴旋转 —— 底座天然水平 =====
let rotZ = -0.55; // Z 轴旋转角(弧度)
let dragActive=false, dragPX=0;
let currentFreq={};
function proj(x,y,z,rz) {
// Z 轴旋转 + 45° dimetric 投影
const cr=Math.cos(rz), sr=Math.sin(rz);
const xr=x*cr-y*sr, yr=x*sr+y*cr;
return { sx:yr-xr, sy:-(xr+yr)+z*0.7, depth:-(xr+yr)+z };
}
function faceVis(face, rz) {
const cr=Math.cos(rz), sr=Math.sin(rz);
switch(face) {
case 'right': return cr+sr>0;
case 'left': return cr+sr<0;
case 'front': return cr-sr>0;
case 'back': return cr-sr<0;
case 'top': return true;
case 'bottom':return false;
}
}
function faceCorns(cx,cy,cz,hs,face) {
const h=hs;
switch(face) {
case 'top': return [[cx-h,cy-h,cz+h],[cx+h,cy-h,cz+h],[cx+h,cy+h,cz+h],[cx-h,cy+h,cz+h]];
case 'bottom': return [[cx-h,cy-h,cz-h],[cx+h,cy-h,cz-h],[cx+h,cy+h,cz-h],[cx-h,cy+h,cz-h]];
case 'front': return [[cx-h,cy+h,cz-h],[cx+h,cy+h,cz-h],[cx+h,cy+h,cz+h],[cx-h,cy+h,cz+h]];
case 'back': return [[cx-h,cy-h,cz-h],[cx+h,cy-h,cz-h],[cx+h,cy-h,cz+h],[cx-h,cy-h,cz+h]];
case 'right': return [[cx+h,cy-h,cz-h],[cx+h,cy+h,cz-h],[cx+h,cy+h,cz+h],[cx+h,cy-h,cz+h]];
case 'left': return [[cx-h,cy-h,cz-h],[cx-h,cy+h,cz-h],[cx-h,cy+h,cz+h],[cx-h,cy-h,cz+h]];
}
}
function renderScene(canvas, freq, rz) {
const dpr=window.devicePixelRatio||1;
const mob=window.innerWidth<=600;
const CS=mob?20:26;
const STEP=CS*2+(mob?2:4);
const DH=CS*2+(mob?1:2);
const PAD=mob?30:40;
const cols={};
for(let n=1;n<=9;n++){
const row=2-Math.floor((n-1)/3), col=(n-1)%3;
cols[n]={wx:(col-1)*STEP,wy:(row-1)*STEP};
}
// 计算包围盒
let mnX=Infinity,mxX=-Infinity,mnY=Infinity,mxY=-Infinity;
for(let n=1;n<=9;n++){
const {wx,wy}=cols[n];
const layers=Math.max(1,freq[n]||1);
for(let l=0;l<layers;l++){
const wz=l*DH;
const cs=[[wx-CS,wy-CS,wz],[wx+CS,wy-CS,wz],[wx+CS,wy+CS,wz],[wx-CS,wy+CS,wz],
[wx-CS,wy-CS,wz+CS*2],[wx+CS,wy-CS,wz+CS*2],[wx+CS,wy+CS,wz+CS*2],[wx-CS,wy+CS,wz+CS*2]];
cs.forEach(c=>{const p=proj(c[0],c[1],c[2],rz);mnX=Math.min(mnX,p.sx);mxX=Math.max(mxX,p.sx);mnY=Math.min(mnY,p.sy);mxY=Math.max(mxY,p.sy);});
}
}
// 底座平台包围盒
const bw=STEP*2+CS*2+16, bz=-CS-3;
[[-bw,-bw,bz],[bw,-bw,bz],[bw,bw,bz],[-bw,bw,bz]].forEach(c=>{
const p=proj(c[0],c[1],c[2],rz);mnX=Math.min(mnX,p.sx);mxX=Math.max(mxX,p.sx);mnY=Math.min(mnY,p.sy);mxY=Math.max(mxY,p.sy);
});
const viewW=Math.max(mxX-mnX+PAD*2,mob?300:400);
const viewH=Math.max(mxY-mnY+PAD*2,mob?320:420);
canvas.width=Math.ceil(viewW*dpr);canvas.height=Math.ceil(viewH*dpr);
canvas.style.width=Math.ceil(viewW)+'px';canvas.style.height=Math.ceil(viewH)+'px';
const ctx=canvas.getContext('2d');ctx.scale(dpr,dpr);ctx.clearRect(0,0,viewW,viewH);
const centerX=(mxX+mnX)/2, ox=viewW/2-centerX, oy=viewH-PAD-mxY;
const faces=[];
const AF=['top','bottom','front','back','right','left'];
// 底座平台(厚块)
(()=>{
const bt=mob?4:5, bzTop=-CS-2, bzBot=bzTop-bt;
const bclr=[170,155,135];
[
{t:'top', c:[[-bw,-bw,bzTop],[bw,-bw,bzTop],[bw,bw,bzTop],[-bw,bw,bzTop]],clr:bclr},
{t:'front', c:[[-bw,bw,bzBot],[bw,bw,bzBot],[bw,bw,bzTop],[-bw,bw,bzTop]],clr:bclr.map(v=>Math.floor(v*0.85))},
{t:'right', c:[[bw,-bw,bzBot],[bw,bw,bzBot],[bw,bw,bzTop],[bw,-bw,bzTop]],clr:bclr.map(v=>Math.floor(v*0.7))},
].forEach(fb=>{
const pts=fb.c.map(c=>proj(c[0],c[1],c[2],rz));
const avgZ=pts.reduce((s,p)=>s+p.depth,0)/4;
const projPts=pts.map(p=>[ox+p.sx,oy-p.sy]);
faces.push({z:avgZ,proj:projPts,color:fb.clr,isTop:fb.t==='top',num:0});
});
})();
// 方块面
for(let n=1;n<=9;n++){
const {wx,wy}=cols[n];
const layers=Math.max(1,freq[n]||1);
const clr=NUM_CLR[n];
const fc={top:clr.top,bottom:clr.top,front:clr.front,back:clr.front,right:clr.right,left:clr.right};
for(let l=0;l<layers;l++){
const wz=l*DH;
for(const face of AF){
if(!faceVis(face,rz))continue;
const crns=faceCorns(wx,wy,wz,CS,face);
const pts=crns.map(c=>proj(c[0],c[1],c[2],rz));
const avgZ=pts.reduce((s,p)=>s+p.depth,0)/4;
const projPts=pts.map(p=>[ox+p.sx,oy-p.sy]);
const cnt=proj(wx,wy,wz+CS,rz);
faces.push({z:avgZ,proj:projPts,color:fc[face],isTop:face==='top',num:n,cx:ox+cnt.sx,cy:oy-cnt.sy});
}
}
}
faces.sort((a,b)=>a.z-b.z);
const alpha=0.82;
for(const f of faces){
const [r,g,b]=f.color;
ctx.fillStyle=`rgba(${r},${g},${b},${alpha})`;
ctx.beginPath();ctx.moveTo(f.proj[0][0],f.proj[0][1]);
for(let i=1;i<4;i++)ctx.lineTo(f.proj[i][0],f.proj[i][1]);
ctx.closePath();ctx.fill();
if(f.isTop&&f.num){
ctx.fillStyle='rgba(255,255,255,0.92)';
const fs=mob?11:14;ctx.font=`bold ${fs}px Georgia,"Noto Serif SC",serif`;
ctx.textAlign='center';ctx.textBaseline='middle';
ctx.shadowColor='rgba(0,0,0,0.25)';ctx.shadowBlur=2;
ctx.fillText(f.num,f.cx,f.cy);
ctx.shadowColor='transparent';ctx.shadowBlur=0;
}
}
// 底部 2D 横条
(()=>{
const bh=mob?18:22,by=viewH-bh;
const grad=ctx.createLinearGradient(0,by,0,viewH);
grad.addColorStop(0,'rgba(180,165,145,0.5)');
grad.addColorStop(0.3,'rgba(160,145,125,0.35)');
grad.addColorStop(1,'rgba(140,125,105,0.1)');
ctx.fillStyle=grad;ctx.fillRect(0,by,viewW,bh);
ctx.strokeStyle='rgba(140,125,105,0.45)';ctx.lineWidth=1;
ctx.beginPath();ctx.moveTo(0,by);ctx.lineTo(viewW,by);ctx.stroke();
})();
}
function drawScene(){
const canvas=document.querySelector('#scene3d canvas');
if(!canvas)return;
renderScene(canvas,currentFreq,rotZ);
}
function setupRotation(){
const el=document.querySelector('#scene3d');if(!el)return;
function getX(e){return e.touches&&e.touches.length?e.touches[0].clientX:e.clientX}
function onStart(e){dragActive=true;dragPX=getX(e);e.preventDefault()}
function onMove(e){
if(!dragActive)return;
const cx=getX(e),dx=cx-dragPX;dragPX=cx;
rotZ+=dx*0.008;drawScene();e.preventDefault();
}
function onEnd(){dragActive=false}
el.addEventListener('mousedown',onStart);
el.addEventListener('touchstart',onStart,{passive:false});
window.addEventListener('mousemove',onMove);
window.addEventListener('touchmove',onMove,{passive:false});
window.addEventListener('mouseup',onEnd);
window.addEventListener('touchend',onEnd);
}
// ===== 解读模块生成器 =====
const GUA64=['','乾为天','天泽履','天火同人','天雷无妄','天风姤','天水讼','天山遁','天地否','泽天夬','兑为泽','泽火革','泽雷随','泽风大过','泽水困','泽山咸','泽地萃','火天大有','火泽睽','离为火','火雷噬嗑','火风鼎','火水未济','火山旅','火地晋','雷天大壮','雷泽归妹','雷火丰','震为雷','雷风恒','雷水解','雷山小过','雷地豫','风天小畜','风泽中孚','风火家人','风雷益','巽为风','风水涣','风山渐','风地观','水天需','水泽节','水火既济','水雷屯','水风井','坎为水','水山蹇','水地比','山天大畜','山泽损','山火贲','山雷颐','山风蛊','山水蒙','艮为山','山地剥','地天泰','地泽临','地火明夷','地雷复','地风升','地水师','地山谦','坤为地'];
const GUA64_DESC={'乾为天':'刚健中正,纯阳之卦。运势旺盛,宜主动进取。','坤为地':'柔顺包容,厚德载物。耐心守成,终得善果。','水雷屯':'万事起头难。创业维艰,宜稳扎稳打。','山水蒙':'蒙昧初开。宜虚心求教,不可自作聪明。','水天需':'等待时机。耐心守候,时机未到不可强求。','天水讼':'争执诉讼之象。退一步海阔天空。','地水师':'统兵出征。纪律严明,以正制邪。','水地比':'亲附和合。广结善缘,必得助力。','地天泰':'天地交泰。万事亨通,上下和合。','天地否':'闭塞不通。宜隐忍守正,静待时机。','天火同人':'志同道合。同心协力可成大事。','火天大有':'丰收大有。顺天应时,财源广进。','雷天大壮':'强盛壮大。力量充沛但切忌恃强凌弱。','火地晋':'旭日东升。逐步晋升,光明在前。','地火明夷':'光明受损。韬光养晦,等待天明。','风火家人':'家庭和乐。修身齐家,家和万事兴。','火泽睽':'乖离不合。求同存异,小事可成。','水山蹇':'艰难险阻。退守求稳,不可强闯。','雷水解':'困难解除。柳暗花明,危机化解。','山泽损':'损下益上。有舍有得,吃亏是福。','风雷益':'增益有利。抓住机遇,积极作为。','泽天夬':'决断果断。当断则断,不受其乱。','天风姤':'不期而遇。随缘而处,不可强求。','泽地萃':'聚集荟萃。人气旺盛,利于合作。','地风升':'步步高升。循序渐进,终达目标。','泽水困':'困顿之象。坚守正道,终可脱困。','水风井':'修德养民。滋养根本,源远流长。','泽火革':'变革之时。顺势而变,除旧布新。','火风鼎':'鼎新革故。稳固根基,创新求变。','震为雷':'震动警醒。临危不乱,化险为夷。','艮为山':'知止不殆。适可而止,安守本分。','风山渐':'循序渐进。按部就班,水到渠成。','雷泽归妹':'婚嫁之象。以诚相待,终成眷属。','雷火丰':'丰盛之时。月满则亏,知足常乐。','火山旅':'行旅之象。随遇而安,莫问归期。','巽为风':'柔顺渗透。以柔克刚,润物无声。','兑为泽':'喜悦沟通。以和为贵,广结善缘。','风水涣':'涣散离散。聚拢人心,凝聚力量。','水泽节':'节制有度。合理规划,量力而行。','风泽中孚':'诚信感召。以诚待人,金石为开。','雷山小过':'小有过失。宜下不宜上,宜小不宜大。','水火既济':'事已成就。居安思危,防微杜渐。','火水未济':'未竟之业。持之以恒,终将成功。','地山谦':'谦逊受益。虚怀若谷,众望所归。','雷地豫':'安乐愉悦。居安思危,不可懈怠。','泽雷随':'随顺时势。灵活应变,顺势而为。','山风蛊':'蛊坏整治。拨乱反正,振弊起衰。','地泽临':'居高临下。亲近下属,恩威并施。','风地观':'观览体察。审时度势,明察秋毫。','火雷噬嗑':'咬合刑罚。明断是非,刚正不阿。','山火贲':'文饰美化。返璞归真,内在为重。','山地剥':'剥落凋零。守正待时,顺势而为。','地雷复':'一阳来复。否极泰来,新生在望。','天雷无妄':'真实无妄。顺其自然,不妄作为。','山天大畜':'蓄积力量。厚积薄发,大器晚成。','山雷颐':'颐养之道。养生养德,自求口实。','泽风大过':'过度之象。刚柔相济,中庸为贵。','坎为水':'重重险难。坚守诚信,终可出险。','离为火':'光明依附。柔顺中正,照亮四方。'};
function meihuaHTML(y,m,d){
const dz=['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥'];
const dzNum={:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12};
const tg=['甲','乙','丙','丁','戊','己','庚','辛','壬','癸'];
const guaName=['','乾 ☰','兑 ☱','离 ☲','震 ☳','巽 ☴','坎 ☵','艮 ☶','坤 ☷'];
const guaEle=['','金','金','火','木','木','水','土','土'];
const ndz=dz[(y-4)%12],ntg=tg[(y-4)%10],nDZ=dzNum[ndz];
const upNum=nDZ%8||8,downNum=(m+d)%8||8,dongY=(nDZ+m+d)%6||6;
const benGuaIdx=(upNum-1)*8+downNum;
const benName=GUA64[benGuaIdx]||(guaName[upNum]+'+'+guaName[downNum]);
const varUp=dongY<=3?upNum:((upNum^5)||8),varDown=dongY<=3?((downNum^5)||8):downNum;
const varIdx=(varUp-1)*8+varDown;
const varName=GUA64[varIdx]||(guaName[varUp]+'+'+guaName[varDown]);
const desc=GUA64_DESC[benName]||'卦象已显,静心体悟其中玄机。';
const dongYaoNames=['初爻','二爻','三爻','四爻','五爻','上爻'];
const ue=guaEle[upNum],de=guaEle[downNum];
const shengKe={'金':'木','木':'土','土':'水','水':'火','火':'金'};
let tiYong;
if(upNum===downNum)tiYong='体用比和,万事顺遂';
else if(shengKe[ue]===de)tiYong='体克用,事可成但需费心力';
else if(shengKe[de]===ue)tiYong='用克体,宜守不宜攻,等待时机';
else tiYong='体用相生,遇贵人之象,万事可成';
return `<div class="module-title">✦ ${benName} ✦</div>
<div class="module-desc">${ntg}${ndz}年 · 上卦${guaName[upNum]} 下卦${guaName[downNum]} · 动在${dongYaoNames[dongY-1]}</div>
<div class="module-section"><b>▸ 本卦:${benName}</b><br><span style="color:#9b8a78">${desc}</span><br><br><b>▸ 变卦:${varName}</b><br><span style="color:#9b8a78">${GUA64_DESC[varName]||'变动已生,观其变化而知吉凶。'}</span><br><br><b>▸ 体用生克</b><br>上卦属${ue}·下卦属${de}${tiYong}</div>`;
}
const XLR_NAMES=['','大安','留连','速喜','赤口','小吉','空亡'];
const XLR_DESC={'大安':'大吉。光明正大,平安顺遂。求财向东南,凡事安稳。','留连':'凶。事难成就,去者未归。宜静不宜动,急则生变。','速喜':'大吉。喜事将至,向南吉利,行人有信至。','赤口':'凶。口舌是非,宜守不宜攻,失物难寻。','小吉':'大吉。好事将近,路遇贵人,向西南吉利。','空亡':'大凶。谋事落空,宜静待时机,强求反遭祸。'};
function xiaoLiuRenHTML(y,m,d){
const mo=m>12?m-12:m,shi=7;let pos=1;
for(let i=1;i<mo;i++)pos=pos%6+1;
for(let i=1;i<d;i++)pos=pos%6+1;
for(let i=1;i<shi;i++)pos=pos%6+1;
const name=XLR_NAMES[pos],isGood=name==='大安'||name==='速喜'||name==='小吉';
return `<div class="module-title">✦ 小六壬 掌诀:${name} ✦</div>
<div class="module-desc">月上起日,日上起时(午时)→ 最终落位</div>
<div class="module-section"><span style="font-size:1.6em;font-weight:700;color:${isGood?'#70ad47':'#c47a78'}">${name}</span><br><span style="color:#9b8a78">${XLR_DESC[name]}</span><br><br><b>▸ 六掌速查</b><br><span style="color:#70ad47">大安</span> · <span style="color:#c47a78">留连</span> · <span style="color:#70ad47">速喜</span> · <span style="color:#c47a78">赤口</span> · <span style="color:#70ad47">小吉</span> · <span style="color:#c47a78">空亡</span></div>`;
}
function daLiuRenHTML(y,m,d){
const dz=['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥'];
const ydz=dz[(y-4)%12],yueJiangMap={1:'子',2:'亥',3:'戌',4:'酉',5:'申',6:'未',7:'午',8:'巳',9:'辰',10:'卯',11:'寅',12:'丑'};
return `<div class="module-title">✦ 大六壬 课式概要 ✦</div>
<div class="module-desc">${y}年(${ydz}年)· ${m}月 月将${yueJiangMap[m]||'午'} · 占时午</div>
<div class="module-section"><b>▸ 简介</b><br><span style="color:#9b8a78">六壬为三式之首,以月将加占时起天地盘,排四课发三传断吉凶。演算极精(12天将+12神煞+遁干),此处展示基础课式。</span><br><br><b>▸ 天地盘</b><br><span style="color:#9b8a78">地盘:子丑寅卯辰巳午未申酉戌亥(固定)<br>天盘:月将加临占时之上,顺布十二辰</span><br><br><b>▸ 四课</b><br><span style="color:#9b8a78">第一课日干阳神 · 第二课日干阴神 · 第三课日支阳神 · 第四课日支阴神</span><br><br><b>▸ 三传</b><br><span style="color:#9b8a78">初传(发用·起始)→ 中传(移易·过程)→ 末传(归计·结局)</span><br><br><b>▸ 九宗门</b><br><span style="color:#9b8a78">贼克·比用·涉害·遥克·昴星·别责·八专·伏吟·反吟</span><br><br><span style="color:#b8a898;font-size:0.95em">※ 完整排盘需配合具体时辰与日干支,建议请六壬师详断。</span></div>`;
}
function qiMenHTML(y,m,d){
const dz=['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥'];
const tg=['甲','乙','丙','丁','戊','己','庚','辛','壬','癸'];
const mingGongMap={1:'丑',2:'寅',3:'卯',4:'辰',5:'巳',6:'午',7:'未',8:'申',9:'酉',10:'戌',11:'亥',12:'子'};
return `<div class="module-title">✦ 奇门遁甲 命盘概要 ✦</div>
<div class="module-desc">${tg[(y-4)%10]}${dz[(y-4)%12]}年 · 命宫:${mingGongMap[m]||'午'}</div>
<div class="module-section"><b>▸ 简介</b><br><span style="color:#9b8a78">奇门合天(九星)、地(九宫)、人(八门)、神(八神)四层于一体。排盘需节气+时辰+用局,极为精密。</span><br><br><b>▸ 地盘九宫</b><br><span style="color:#9b8a78">戴九履一·左三右七·二四为肩·六八为足·五居中央<br>坎一水·坤二土·震三木·巽四木·中五土·乾六金·兑七金·艮八土·离九火</span><br><br><b>▸ 八门(人事)</b><br><span style="color:#9b8a78">开门(吉)·休门(吉)·生门(吉)·伤门(凶)·杜门(平)·景门(平)·死门(凶)·惊门(凶)</span><br><br><b>▸ 九星(天时)</b><br><span style="color:#9b8a78">天蓬·天任·天冲·天辅·天英·天芮·天柱·天心·天禽</span><br><br><span style="color:#b8a898;font-size:0.95em">※ 全面排盘需根据具体时辰和节气确定阳遁/阴遁几局,建议请奇门师详断。</span></div>`;
}
const ZODIAC=[
{name:'摩羯座',emoji:'♑',elem:'土',from:[12,22],to:[1,19],trait:'坚韧务实,目标明确,大器晚成',lucky:'深绿·黑'},
{name:'水瓶座',emoji:'♒',elem:'风',from:[1,20],to:[2,18],trait:'独立创新,思维超前,人道主义',lucky:'蓝·银'},
{name:'双鱼座',emoji:'♓',elem:'水',from:[2,19],to:[3,20],trait:'浪漫敏感,富有同情心,艺术天赋',lucky:'紫·海蓝'},
{name:'白羊座',emoji:'♈',elem:'火',from:[3,21],to:[4,19],trait:'热情勇敢,行动力强,开拓先锋',lucky:'红·金'},
{name:'金牛座',emoji:'♉',elem:'土',from:[4,20],to:[5,20],trait:'稳健可靠,审美出众,坚定执着',lucky:'粉·绿'},
{name:'双子座',emoji:'♊',elem:'风',from:[5,21],to:[6,21],trait:'机智灵活,善于沟通,双面魅力',lucky:'黄·银'},
{name:'巨蟹座',emoji:'♋',elem:'水',from:[6,22],to:[7,22],trait:'温柔顾家,情感丰富,保护欲强',lucky:'白·银'},
{name:'狮子座',emoji:'♌',elem:'火',from:[7,23],to:[8,22],trait:'自信大方,领导力强,光芒四射',lucky:'金·橙'},
{name:'处女座',emoji:'♍',elem:'土',from:[8,23],to:[9,22],trait:'细致严谨,追求完美,服务精神',lucky:'灰·米'},
{name:'天秤座',emoji:'♎',elem:'风',from:[9,23],to:[10,23],trait:'优雅公正,善于平衡,社交达人',lucky:'粉·蓝'},
{name:'天蝎座',emoji:'♏',elem:'水',from:[10,24],to:[11,22],trait:'深沉敏锐,意志坚定,极致深情',lucky:'深红·黑'},
{name:'射手座',emoji:'♐',elem:'火',from:[11,23],to:[12,21],trait:'乐观自由,探索精神,哲学思维',lucky:'紫·深蓝'},
];
function xingZuoHTML(y,m,d){
let z=ZODIAC.find(x=>(m===x.from[0]&&d>=x.from[1])||(m===x.to[0]&&d<=x.to[1]));
if(!z){if((m===12&&d>=22)||(m===1&&d<=19))z=ZODIAC[0];else if(m===1)z=ZODIAC[1];else z=ZODIAC.find(x=>m===x.from[0]&&d<x.from[1])||ZODIAC[0];}
const et={:'热情主动,充满生命力,敢于冒险',:'踏实稳重,注重现实,可靠可信',:'思维敏捷,善于交流,适应力强',:'情感深邃,直觉敏锐,富有创造力'};
const ec={:'#c47a78',:'#8b7a68',:'#91a3b0',:'#6b9eb3'};
return `<div class="module-title">✦ ${z.emoji} ${z.name} ✦</div>
<div class="module-desc">${z.elem}象星座 · 幸运色:${z.lucky}</div>
<div class="module-section"><span style="font-size:2em">${z.emoji}</span><br><b>▸ 性格特质</b><br><span style="color:#9b8a78">${z.trait}</span><br><br><b>▸ 元素能量</b><br><span style="color:#9b8a78">${et[z.elem]}</span><br><br><b>▸ 十二星座</b><br>${ZODIAC.map(x=>`<span style="color:${ec[x.elem]}">${x.emoji}</span>`).join(' ')}</div>`;
}
const BAGUA=[
{name:'乾 ☰',xiang:'天',elem:'金',clr:'#d4c5a0',txt:'#8b7355',desc:'刚健·创造'},
{name:'兑 ☱',xiang:'泽',elem:'金',clr:'#e8d5c8',txt:'#a08070',desc:'喜悦·沟通'},
{name:'离 ☲',xiang:'火',elem:'火',clr:'#e8c8c0',txt:'#b06050',desc:'光明·智慧'},
{name:'震 ☳',xiang:'雷',elem:'木',clr:'#c8d8b0',txt:'#5a7a3a',desc:'行动·震动'},
{name:'巽 ☴',xiang:'风',elem:'木',clr:'#b8d0b8',txt:'#4a7a4a',desc:'渗透·柔顺'},
{name:'坎 ☵',xiang:'水',elem:'水',clr:'#a8c8d8',txt:'#3a6a8a',desc:'险陷·智慧'},
{name:'艮 ☶',xiang:'山',elem:'土',clr:'#d0c8b0',txt:'#7a6a4a',desc:'静止·坚守'},
{name:'坤 ☷',xiang:'地',elem:'土',clr:'#e0d8c0',txt:'#8a7a5a',desc:'柔顺·包容'},
];
function wuXingHTML(y,m,d){
const yElem=['金','水','木','火','土'][Math.floor(((y-4)%10)/2)];
const mElem=['木','木','土','火','火','土','金','金','土','水','水','土'][m-1];
const dElem=['木','火','土','金','水'][d%5];
const ec={:'#d4c5a0',:'#a8c8d8',:'#b8d0b8',:'#e8c8c0',:'#e0d8c0'};
return `<div class="module-title">✦ 五行八卦 能量图谱 ✦</div>
<div class="module-desc">年柱${yElem} · 月柱${mElem} · 日柱${dElem}</div>
<div class="module-section"><b>▸ 五行</b><br>
<div style="display:flex;gap:4px;margin:6px 0">${['金','水','木','火','土'].map(e=>`<span style="flex:1;text-align:center;padding:4px;background:${ec[e]};color:#5a4636;border-radius:3px;font-size:0.95em"><b>${e}</b></span>`).join('')}</div>
<span style="color:#9b8a78">金(义)·水(智)·木(仁)·火(礼)·土(信)<br>相生:金→水→木→火→土→金<br>相克:金→木→土→水→火→金</span><br><br><b>▸ 八卦</b><br>
<div class="bagua-grid">${BAGUA.map(b=>`<div class="bagua-cell" style="background:${b.clr};color:${b.txt}"><b>${b.name}</b><br><span style="font-size:0.92em">${b.elem}·${b.xiang}<br>${b.desc}</span></div>`).join('')}</div>
<span style="color:#9b8a78">八卦歌诀:乾三连·坤六断·震仰盂·艮覆碗·离中虚·坎中满·兑上缺·巽下断</span></div>`;
}
// ===== Tab 切换 =====
function initTabs(){
const nav=document.querySelector('.tabs-nav');
if(!nav)return;
nav.addEventListener('click',e=>{
const btn=e.target.closest('.tab-btn');
if(!btn)return;
const tab=btn.dataset.tab;
nav.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('.tab-panel').forEach(p=>p.classList.remove('active'));
const panel=document.getElementById(tab+'-panel');
if(panel)panel.classList.add('active');
});
}
function update(v,y,m,d){
document.getElementById('valR').textContent=v.R;
document.getElementById('valQ').textContent=v.Q;
document.getElementById('valP').textContent=v.P;
document.getElementById('valO').textContent=v.O;
document.getElementById('valM').textContent=v.M;
document.getElementById('valN').textContent=v.N;
document.getElementById('valI').textContent=v.I;
document.getElementById('valJ').textContent=v.J;
document.getElementById('valK').textContent=v.K;
document.getElementById('valL').textContent=v.L;
document.getElementById('valU').textContent=v.U;
document.getElementById('valT').textContent=v.T;
document.getElementById('valS').textContent=v.S;
document.getElementById('valX').textContent=v.X;
document.getElementById('valV').textContent=v.V;
document.getElementById('valW').textContent=v.W;
document.getElementById('dateD').textContent=String(d).padStart(2,'0');
document.getElementById('dateM').textContent=String(m).padStart(2,'0');
document.getElementById('dateY').textContent=y;
const allNums=[0,1,2,3,4,5,6,7,8,9];
const inner=new Set([v.O,v.M,v.N,v.I,v.J,v.K,v.L]);
const present=new Set([...inner,v.Q,v.P,v.R,v.T,v.S,v.U,v.V,v.W,v.X,v.AB[0],v.AB[1],v.CD[0],v.CD[1],v.EF[0],v.EF[1],v.GH[0],v.GH[1]]);
const miss={inner:allNums.filter(n=>!inner.has(n)),outer:allNums.filter(n=>![v.Q,v.P,v.R,v.T,v.S,v.U,v.V,v.W,v.X].includes(n)),both:allNums.filter(n=>!present.has(n))};
const n=NUM[v.O]||{};
const freq={};
for(let i=1;i<=9;i++)freq[i]=0;
const allVals=[v.O,v.M,v.N,v.I,v.J,v.K,v.L,v.Q,v.P,v.R,v.T,v.S,v.U,v.V,v.W,v.X,
v.AB[0],v.AB[1],v.CD[0],v.CD[1],v.EF[0],v.EF[1],v.GH[0],v.GH[1]];
allVals.forEach(x=>{if(x>=1&&x<=9)freq[x]++;});
currentFreq=freq;
const freqArr=Object.entries(freq).sort((a,b)=>b[1]-a[1]);
const most=freqArr[0],least=freqArr.filter(([,c])=>c===freqArr[freqArr.length-1][1]);
let html=`<div style="text-align:center;margin-bottom:18px;">`;
html+=`<div style="font-size:2.4em;font-weight:700;color:#c47a78;line-height:1;margin-bottom:4px;">${v.O}号人</div>`;
html+=`<div style="font-size:0.85em;font-weight:600;color:#5a4636;margin-bottom:6px;">${n.title||''}</div>`;
html+=`<div style="font-size:0.75em;color:#6b5b4e;line-height:1.7;max-width:340px;margin:0 auto;text-align:left;">${n.desc||''}</div>`;
html+=`<div style="font-size:0.7em;color:#9b8a78;margin-top:8px;line-height:1.7;text-align:left;max-width:340px;margin-left:auto;margin-right:auto;">`;
html+=`<b>✦ 天赋优势</b>${n.pos||''}<br><b>✦ 人生课题</b>${n.neg||''}<br><b>✦ 五行属性</b>${n.elem||''}<br><b>✦ 适合职业</b>${n.job||''}</div></div>`;
html+=`<hr class="divider">`;
html+=`<div style="font-size:0.82em;font-weight:600;color:#5a4636;text-align:center;margin-bottom:8px;">✦ 数字能量分布 ✦</div>`;
html+=`<div style="font-size:0.7em;color:#6b5b4e;text-align:center;margin-bottom:0;">你的生命三角中共有 <b>${allVals.filter(x=>x>=1).length}</b> 个有效数字</div>`;
html+=`<div class="scene-3d" id="scene3d"><canvas></canvas><div class="scene-hint">↻ 左右旋转</div></div>`;
html+=`<div class="freq-label">✦ 能量最强:<b>${most[0]}</b>(出现 ${most[1]} 次)— 该数字特质在你生命中最为突出</div>`;
if(least.length>0)html+=`<div class="freq-label" style="margin-top:0;">✦ 能量最弱:${least.map(([n])=>`<b>${n}</b>`).join('、')}(仅 ${least[0][1]} 次)— 需刻意培养相关特质</div>`;
html+=`<hr class="divider">`;
html+=`<div style="font-size:0.82em;font-weight:600;color:#5a4636;text-align:center;margin-bottom:6px;">✦ 三角内外含义 ✦</div>`;
html+=`<div style="font-size:0.7em;line-height:1.7;color:#6b5b4e;padding:0 4px;">`;
html+=`<div><b>▸ 三角内部</b>:代表你内在真实的自我——潜意识的驱动、与生俱来的性格特质、不为人知的内心世界。</div>`;
html+=`<div style="margin-top:3px;"><b>▸ 三角外部</b>:代表外界对你的认知——你在工作、家庭、社交中呈现出的样子,以及他人眼中的你。</div>`;
html+=`<div style="margin-top:3px;"><b>▸ 下方基因</b>(父母遗传):代表来自父亲和母亲的先天遗传基因,是你性格的底层土壤。</div></div>`;
html+=`<hr class="divider">`;
html+=`<div style="font-size:0.82em;font-weight:600;color:#5a4636;text-align:center;margin-bottom:6px;">✦ 性格编码解读 ✦</div>`;
html+=`<div style="font-size:0.7em;line-height:1.8;color:#6b5b4e;padding:0 4px;">`;
html+=`<div style="margin-bottom:4px;"><b>潜意识码:${v.I}${v.J}${v.K}${v.L}</b></div>`;
html+=`<div style="color:#9b8a78;margin-bottom:8px;">这是你内心的真实驱动力,代表你最本能的反应模式。四个数字分别对应你的思维方式、情感表达、行动模式和人际风格。</div>`;
html+=`<div style="margin-bottom:4px;"><b>内心码:${v.M}${v.N}</b></div>`;
html+=`<div style="color:#9b8a78;margin-bottom:8px;">揭示你深层情感模式和核心价值观。两个数字分别主宰理性行动和感性人际,两者的平衡决定你如何面对压力。</div>`;
html+=`<div style="margin-bottom:4px;"><b>坐镇码:${v.I}${v.M}${v.O}</b></div>`;
html+=`<div style="color:#9b8a78;margin-bottom:8px;">性格核心轴线,由潜意识→内心→主性格串联而成,代表你从内在驱动到最终呈现的完整性格链条。是你最稳定、最不易改变的性格底色。</div>`;
html+=`<div style="margin-bottom:4px;"><b>父亲基因:${v.EF.join('')} ${v.GH.join('')}</b> · <b>母亲基因:${v.AB.join('')} ${v.CD.join('')}</b></div>`;
html+=`<div style="color:#9b8a78;">父亲基因(年份 ${v.EF.join('')}${v.GH.join('')})承载家族传承和事业基因,母亲基因(月${v.CD.join('')}${v.AB.join('')})影响情感模式和人际关系基础。</div></div>`;
html+=`<hr class="divider">`;
html+=`<div style="font-size:0.82em;font-weight:600;color:#5a4636;text-align:center;margin-bottom:6px;">✦ 数字缺失与过剩 ✦</div>`;
html+=`<div style="font-size:0.7em;line-height:1.7;color:#6b5b4e;padding:0 4px;">`;
if(miss.both.length>0){html+=`<div style="margin-bottom:4px;"><b>⚠ 缺失数字</b></div>`;miss.both.forEach(n=>{html+=`<div style="margin-bottom:3px;">· <b>缺${n}</b>${MISS_MSG[n]||''}</div>`;});}
else html+=`<div style="margin-bottom:4px;color:#9b8a78;">✦ 你的数字分布完整,能量均衡。</div>`;
const over=[];for(let i=1;i<=9;i++){if(freq[i]>=4&&!miss.both.includes(i))over.push(i);}
if(over.length>0){html+=`<div style="margin-top:6px;margin-bottom:4px;"><b>⚡ 能量过剩</b></div>`;over.forEach(n=>{html+=`<div style="margin-bottom:3px;">· <b>多${n}</b>(×${freq[n]}):${MISS_STRONG[n]||''}</div>`;});}
html+=`</div>`;
const joints=[['I','J'],['J','M'],['M','I'],['K','L'],['L','N'],['N','K'],['M','O'],['O','N'],['M','N'],['Q','P'],['Q','O'],['P','O']].map(([a,b])=>({code:''+v[a]+v[b],label:JOINT[''+v[a]+v[b]]||'—'}));
html+=`<hr class="divider">`;
html+=`<div style="font-size:0.82em;font-weight:600;color:#5a4636;text-align:center;margin-bottom:6px;">✦ 12组联合码详解 ✦</div>`;
html+=`<div style="font-size:0.68em;color:#9b8a78;text-align:center;margin-bottom:8px;">联合码由相邻两个数字组成,揭示你在不同人生阶段的行为模式</div>`;
const ages=[
{label:'21—40岁 · 工作和朋友',codes:joints.slice(0,4),desc:'由潜意识码主导,反映你在职场上升期和社交圈中的表现模式。'+(v.I+v.J+v.M>=10?'能量较强,事业心旺盛,社交活跃。':'能量内敛,更注重深度而非广度。')},
{label:'41—60岁 · 儿女和下属',codes:joints.slice(4,8),desc:'由内心码和主性格主导,体现你对下一代和下级的培养方式及中年价值观。'+(v.K+v.L+v.N>=10?'有较强的责任感和支配欲。':'倾向于给予空间,放手让他人成长。')},
{label:'61岁至晚年 · 晚年和家庭',codes:joints.slice(8,12),desc:'由外心码主导,展现你晚年的生活智慧和家庭关系的最终呈现。'+(v.M+v.N+v.O>=10?'晚年活跃,持续发挥影响力。':'晚年宁静,享受内在平和。')},
];
ages.forEach(ag=>{
html+=`<div class="joint-age">${ag.label}</div>`;
html+=`<div style="font-size:0.65em;color:#9b8a78;text-align:center;margin:-2px 0 6px;line-height:1.5;">${ag.desc}</div>`;
html+=`<div class="joint-grid">`;
ag.codes.forEach(jc=>{html+=`<div><span class="jc">${jc.code}</span> <span class="jm">${jc.label}</span></div>`;});
html+=`</div>`;
});
document.getElementById('missingBlock').innerHTML=html;
setTimeout(()=>{
const canvas=document.querySelector('#scene3d canvas');
if(canvas){renderScene(canvas,freq,rotZ);setupRotation();}
},30);
document.getElementById('missingMsg').textContent='';
document.getElementById('codesBlock').innerHTML='';
document.getElementById('jointBlock').innerHTML='';
const tipEl=document.getElementById('tip');
['valR','valQ','valP','valO','valM','valN','valI','valJ','valK','valL','valU','valT','valS','valX','valV','valW'].forEach(id=>{
const el=document.getElementById(id);if(!el)return;el.style.cursor='pointer';
const k=id.replace('val','');
el.onpointerenter=()=>{const f=tips[k]?tips[k](v):'';tipEl.innerHTML=f||k;tipEl.classList.add('on')};
el.onpointermove=e=>{tipEl.style.left=(e.clientX+14)+'px';tipEl.style.top=(e.clientY-10)+'px'};
});
// 填充其他解读面板
document.getElementById('meihua-panel').innerHTML=meihuaHTML(y,m,d);
document.getElementById('xiaoliuren-panel').innerHTML=xiaoLiuRenHTML(y,m,d);
document.getElementById('daliuren-panel').innerHTML=daLiuRenHTML(y,m,d);
document.getElementById('qimen-panel').innerHTML=qiMenHTML(y,m,d);
document.getElementById('xingzuo-panel').innerHTML=xingZuoHTML(y,m,d);
document.getElementById('wuxing-panel').innerHTML=wuXingHTML(y,m,d);
}
function go(){const y=+document.getElementById('inY').value,m=+document.getElementById('inM').value,d=+document.getElementById('inD').value;if(!y||!m||!d)return;update(calc(y,m,d),y,m,d)}
document.getElementById('goBtn').addEventListener('click',go);
document.querySelectorAll('.input-row input').forEach(i=>i.addEventListener('keydown',e=>{if(e.key==='Enter')go()}));
setTimeout(go,150);
initTabs();
</script>
</body>
</html>