Archive the differentiated YuXinGu product docs, AI engineering system, design contract, and Go/Vue scaffold. Next execution prioritizes Cece-parity over early innovation (see .ai/product/STRATEGY.md). Co-authored-by: Cursor <cursoragent@cursor.com>
1090 lines
114 KiB
JavaScript
1090 lines
114 KiB
JavaScript
// ═══════ DATA ═══════
|
||
var ZODIAC=[
|
||
{name:'摩羯座',dh:'羯',el:'土',trait:'坚韧·务实·野心',color:'#8B7355',range:[[1,1,1,19],[12,22,12,31]]},
|
||
{name:'水瓶座',dh:'瓶',el:'风',trait:'独立·创新·博爱',color:'#4A90E2',range:[[1,20,2,18]]},
|
||
{name:'双鱼座',dh:'鱼',el:'水',trait:'敏感·梦幻·共情',color:'#7B68EE',range:[[2,19,3,20]]},
|
||
{name:'白羊座',dh:'羊',el:'火',trait:'勇敢·冲动·开创',color:'#E54D42',range:[[3,21,4,19]]},
|
||
{name:'金牛座',dh:'牛',el:'土',trait:'稳重·固执·审美',color:'#5CB85C',range:[[4,20,5,20]]},
|
||
{name:'双子座',dh:'子',el:'风',trait:'多变·聪明·好奇',color:'#F5A623',range:[[5,21,6,21]]},
|
||
{name:'巨蟹座',dh:'蟹',el:'水',trait:'温柔·念旧·顾家',color:'#C0C0C0',range:[[6,22,7,22]]},
|
||
{name:'狮子座',dh:'狮',el:'火',trait:'自信·慷慨·领袖',color:'#FFD700',range:[[7,23,8,22]]},
|
||
{name:'处女座',dh:'女',el:'土',trait:'细致·完美·服务',color:'#8B8B83',range:[[8,23,9,22]]},
|
||
{name:'天秤座',dh:'秤',el:'风',trait:'优雅·平衡·犹豫',color:'#FF69B4',range:[[9,23,10,23]]},
|
||
{name:'天蝎座',dh:'蝎',el:'水',trait:'深刻·神秘·执着',color:'#8B0000',range:[[10,24,11,22]]},
|
||
{name:'射手座',dh:'射',el:'火',trait:'乐观·自由·冒险',color:'#FF6347',range:[[11,23,12,21]]}
|
||
];
|
||
var ZODIAC_ICON={"摩羯座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRjVFNkQzIiBzdHJva2U9IiNBMEE1NUIiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiNDNEE4N0MiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzZCNEYzQSIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPgo8cGF0aCBkPSJNMjAgMzhjMi00IDYtOCAxMi04czEwIDQgMTIgOCIvPgo8cGF0aCBkPSJNMjUgMzBjMS0yIDMtNCA3LTNjMyAxIDUgMyA1IDMiLz4KPHBhdGggZD0iTTE4IDQyYzIgNCA2IDggOCAxNGMxIDMgMCA1LTIgNiIvPgo8cGF0aCBkPSJNNDYgNDJjLTIgNC02IDgtOCAxNGMtMSAzIDAgNSAyIDYiLz4KPC9nPgo8Y2lyY2xlIGN4PSIzMiIgY3k9IjIyIiByPSIyIiBmaWxsPSIjNkI0RjNBIi8+Cjwvc3ZnPg==","水瓶座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRjBGNUY4IiBzdHJva2U9IiM1QjhGQTgiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiM3QkFGQzgiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzNBNjA3MCIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPgo8cGF0aCBkPSJNMjIgMTRjMCAyIDIgNCA1IDRoMTBjMyAwIDUtMiA1LTQiLz4KPHBhdGggZD0iTTI0IDE4djEwYzAgNi0yIDEwLTQgMTRjMiAyIDQgNCA2IDRoMTJjMiAwIDQtMiA2LTRjLTItNC00LTgtNC0xNFYxOCIvPgo8cGF0aCBkPSJNMjggMzBjMi0yIDQtNCA4LTNjMyAxIDQgMyA0IDNNMjcgMzZjMi0yIDUtMyA4LTJNMjUgNDJjMi0yIDUtMyA4LTIiLz4KPC9nPgo8L3N2Zz4=","双鱼座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRjJGMEY4IiBzdHJva2U9IiM2QjVCOTUiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiM4QjdCQjUiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzRBMzU3MCIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPgo8cGF0aCBkPSJNMjIgMjJjNi00IDE0LTIgMTYgNmMyIDgtNCAxNC0xMCAxNHMtMTAtNi04LTE0Ii8+CjxjaXJjbGUgY3g9IjIwIiBjeT0iMjAiIHI9IjEuNSIgZmlsbD0iIzRBMzU3MCIvPgo8cGF0aCBkPSJNNDIgNDJjLTYgNC0xNCAyLTE2LTZjLTItOCA0LTE0IDEwLTE0czEwIDYgOCAxNCIvPgo8Y2lyY2xlIGN4PSI0NCIgY3k9IjQ0IiByPSIxLjUiIGZpbGw9IiM0QTM1NzAiLz4KPHBhdGggZD0iTTMwIDM0YzEtMiAzLTIgNCAwIi8+CjwvZz4KPC9zdmc+","白羊座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRkRGMkVDIiBzdHJva2U9IiNDMDQwMzAiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiNEMDYwNTAiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzhCMjAyMCIgc3Ryb2tlLXdpZHRoPSIyLjIiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+CjxwYXRoIGQ9Ik0xNiAzNmMyLTggNi0xNCAxNC0xNmMzLTEgNiAwIDggMiIvPgo8cGF0aCBkPSJNNDggMzZjLTItOC02LTE0LTE0LTE2Yy0zLTEtNiAwLTggMiIvPgo8cGF0aCBkPSJNMTggMzhjNC0xMiA4LTE0IDE0LTEyYzYgMiA4IDggOCA4TTQ2IDM4Yy00LTEyLTgtMTQtMTQtMTJjLTYgMi04IDgtOCA4Ii8+CjwvZz4KPHBhdGggZD0iTTI4IDQwYzAtMiAyLTQgNC00czQgMiA0IDQiIHN0cm9rZT0iIzhCMjAyMCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGZpbGw9Im5vbmUiLz4KPC9zdmc+","金牛座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRjhGMkVBIiBzdHJva2U9IiNBMDg1NUIiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiNDNEE4N0MiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzZCNEYzQSIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPgo8cGF0aCBkPSJNMjYgMjBjMi02IDgtOCAxMi02YzIgMSA0IDMgNCA2Ii8+CjxwYXRoIGQ9Ik0xOCAyOGMwIDQgMiA4IDYgMTBsNCAxMGMxIDIgMiAzIDQgM3MzLTEgNC0zbDQtMTBjNC0yIDYtNiA2LTEwIi8+CjxjaXJjbGUgY3g9IjI0IiBjeT0iMjQiIHI9IjIiIGZpbGw9IiM2QjRGM0EiLz4KPGNpcmNsZSBjeD0iNDAiIGN5PSIyNCIgcj0iMiIgZmlsbD0iIzZCNEYzQSIvPgo8cGF0aCBkPSJNMjggMzRoOCIvPgo8L2c+Cjwvc3ZnPg==","双子座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRjBGNUY4IiBzdHJva2U9IiM1QjhGQTgiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiM3QkFGQzgiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzNBNjA3MCIgc3Ryb2tlLXdpZHRoPSIxLjgiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+CjxwYXRoIGQ9Ik0yMiAxNGMwIDQgMiA2IDUgNnM1LTIgNS02Ii8+CjxwYXRoIGQ9Ik0yMiAyMHYyMGMwIDYgMiAxMCA0IDEyIi8+CjxwYXRoIGQ9Ik0zMCAxNGMwIDQgMiA2IDUgNnM1LTIgNS02Ii8+CjxwYXRoIGQ9Ik0zMCAyMHYyMGMwIDYgMiAxMCA0IDEyIi8+CjxwYXRoIGQ9Ik0yNCAyOGMxLTIgMy0zIDUtMk0zMiAyOGMxLTIgMy0zIDUtMiIvPgo8L2c+CjxjaXJjbGUgY3g9IjI0IiBjeT0iMTQiIHI9IjMiIGZpbGw9IiMzQTYwNzAiLz4KPGNpcmNsZSBjeD0iMzIiIGN5PSIxNCIgcj0iMyIgZmlsbD0iIzNBNjA3MCIvPgo8L3N2Zz4=","巨蟹座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRjJGMEY4IiBzdHJva2U9IiM2QjVCOTUiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiM4QjdCQjUiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzRBMzU3MCIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPgo8cGF0aCBkPSJNMTYgMjhjNC00IDgtNCAxMi0yYzItMyA1LTMgOCAwYzMtMyA2LTMgMTAtMiIvPgo8cGF0aCBkPSJNMTQgMzRjNCA2IDggMTAgMTggMTBzMTQtNCAxOC0xMCIvPgo8cGF0aCBkPSJNMjQgNDRjMyA0IDYgNiA4IDZzNS0yIDgtNiIvPgo8cGF0aCBkPSJNMTggMzR2LTZNNDYgMzR2LTYiLz4KPC9nPgo8Y2lyY2xlIGN4PSIxOCIgY3k9IjIyIiByPSIyIiBmaWxsPSIjNEEzNTcwIi8+CjxjaXJjbGUgY3g9IjQ2IiBjeT0iMjIiIHI9IjIiIGZpbGw9IiM0QTM1NzAiLz4KPC9zdmc+","狮子座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRkRGMkVDIiBzdHJva2U9IiNDMDQwMzAiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiNEMDYwNTAiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzhCMjAyMCIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPgo8cGF0aCBkPSJNMzIgMTJjLTYgMi0xMCA2LTEyIDEwYy0xIDItMSA0IDAgNmMyIDYgNiAxMCAxMiAxMmM2LTIgMTAtNiAxMi0xMmMxLTIgMS00IDAtNmMtMi00LTYtOC0xMi0xMHoiLz4KPHBhdGggZD0iTTI4IDIyYzEtMiAzLTMgNC0yczEgMyAwIDQiLz4KPHBhdGggZD0iTTM2IDIyYy0xLTItMy0zLTQtMnMtMSAzIDAgNCIvPgo8cGF0aCBkPSJNMzAgMjhjMC0xIDEtMSAyIDBjMSAxIDEgMSAyIDAiLz4KPC9nPgo8L3N2Zz4=","处女座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRjhGMkVBIiBzdHJva2U9IiNBMDg1NUIiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiNDNEE4N0MiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzZCNEYzQSIgc3Ryb2tlLXdpZHRoPSIxLjgiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+CjxwYXRoIGQ9Ik0zMiAxMmMwIDQtMiA2LTUgNiIvPgo8cGF0aCBkPSJNMzIgMTh2MTJjMCA4LTIgMTItNCAxNmMyIDIgNCA0IDggNHM2LTIgOC00Yy0yLTQtNC04LTQtMTZWMTgiLz4KPHBhdGggZD0iTTIyIDQ2bDQtNGw0IDQiLz4KPHBhdGggZD0iTTQyIDQ2bC00LTRsLTQgNCIvPgo8cGF0aCBkPSJNMjggMjBsMiAxNCIvPgo8cGF0aCBkPSJNMzYgMjBsLTIgMTQiLz4KPC9nPgo8Y2lyY2xlIGN4PSIyNyIgY3k9IjEyIiByPSIzIiBmaWxsPSIjNkI0RjNBIi8+Cjwvc3ZnPg==","天秤座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRjBGNUY4IiBzdHJva2U9IiM1QjhGQTgiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiM3QkFGQzgiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzNBNjA3MCIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPgo8cGF0aCBkPSJNMTYgMThoMzIiLz4KPHBhdGggZD0iTTMyIDE4djgiLz4KPHBhdGggZD0iTTE4IDI2bC0yIDhjMCAyIDEgNCAzIDRzMy0yIDMtNGMwIDIgMSA0IDMgNHMzLTItMy00YzAgMiAxIDQgMyA0czMtMiAzLTRsLTItOCIvPgo8cGF0aCBkPSJNMjAgNDJjNCA2IDggMTAgMTIgMTBzOC00IDEyLTEwIi8+CjwvZz4KPC9zdmc+","天蝎座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRjJGMEY4IiBzdHJva2U9IiM2QjVCOTUiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiM4QjdCQjUiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzRBMzU3MCIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPgo8cGF0aCBkPSJNMjggMTZjLTQgMC02IDQtNiA4YzAgMyAxIDUgMyA2Ii8+CjxwYXRoIGQ9Ik0zNiAxNmM0IDAgNiA0IDYgOGMwIDMtMSA1LTMgNiIvPgo8cGF0aCBkPSJNMjIgMzBjLTIgNC00IDEwLTIgMTRjMiA1IDYgOCAxMiA4czEwLTMgMTItOGMyLTQgMC0xMC0yLTE0Ii8+CjxwYXRoIGQ9Ik0zMiAzMHYyMiIvPgo8cGF0aCBkPSJNMjYgNDhjMyAzIDYgNCA4IDJjMy0zIDMtNiAxLTEwTTM4IDQ4Yy0zIDMtNiA0LTggMmMtMy0zLTMtNi0xLTEwIi8+CjwvZz4KPC9zdmc+","射手座":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjMwIiBmaWxsPSIjRkRGMkVDIiBzdHJva2U9IiNDMDQwMzAiIHN0cm9rZS13aWR0aD0iMi41Ii8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjI4IiBmaWxsPSJub25lIiBzdHJva2U9IiNEMDYwNTAiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxnIHN0cm9rZT0iIzhCMjAyMCIgc3Ryb2tlLXdpZHRoPSIyLjIiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+CjxwYXRoIGQ9Ik0xOCA0NmMyLTggNi0xOCAxNi0zMGM0IDQgOCA2IDEyIDZjMiAwIDQtMSA0LTIiLz4KPHBhdGggZD0iTTM0IDE2YzYgMiAxMCA2IDEyIDEyIi8+CjxwYXRoIGQ9Ik00NiAyOGwtNCA4bC04LTQiLz4KPC9nPgo8cGF0aCBkPSJNMjggNDBjMCA2IDIgMTAgNCAxMmMyLTIgNC02IDQtMTIiIHN0cm9rZT0iIzhCMjAyMCIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPC9zdmc+"};
|
||
function zodiacBadge(z){return '<span class="zodiac-dh '+(z.el==='火'?'fire':z.el==='土'?'earth':z.el==='风'?'air':'water')+'"><img src="'+ZODIAC_ICON[z.name]+'" width="32" height="32" alt="'+z.name+'" style="width:100%;height:100%;border-radius:50%"></span>';}
|
||
|
||
var HOURS=['子时 23-1','丑时 1-3','寅时 3-5','卯时 5-7','辰时 7-9','巳时 9-11','午时 11-13','未时 13-15','申时 15-17','酉时 17-19','戌时 19-21','亥时 21-23'];
|
||
var CITIES=['北京','上海','广州','深圳','成都','杭州','武汉','南京','西安','重庆','长沙','其他'];
|
||
|
||
var REGIONS={
|
||
'北京':{'北京':['东城','西城','朝阳','海淀','丰台','石景山','通州','大兴','顺义','昌平','房山','门头沟','平谷','怀柔','密云','延庆']},
|
||
'上海':{'上海':['黄浦','徐汇','长宁','静安','普陀','虹口','杨浦','浦东','闵行','宝山','嘉定','松江','金山','青浦','奉贤','崇明']},
|
||
'天津':{'天津':['和平','河东','河西','南开','河北','红桥','滨海','东丽','西青','津南','北辰','武清','宝坻','宁河','静海','蓟州']},
|
||
'重庆':{'重庆':['渝中','江北','沙坪坝','九龙坡','南岸','大渡口','北碚','渝北','巴南','万州','涪陵','黔江','长寿','江津','合川','永川','南川','綦江','大足','璧山','铜梁','潼南','荣昌','开州','梁平','武隆','城口','丰都','垫江','忠县','云阳','奉节','巫山','巫溪','石柱','秀山','酉阳','彭水']},
|
||
'广东':{'广州':['越秀','天河','海珠','荔湾','白云','黄埔','番禺','花都','南沙','从化','增城'],'深圳':['福田','罗湖','南山','盐田','宝安','龙岗','龙华','坪山','光明'],'珠海':['香洲','斗门','金湾'],'汕头':['金平','龙湖','濠江','潮阳','潮南','澄海','南澳'],'佛山':['禅城','南海','顺德','三水','高明'],'韶关':['浈江','武江','曲江','乐昌','南雄','始兴','仁化','翁源','新丰','乳源'],'湛江':['赤坎','霞山','坡头','麻章','廉江','雷州','吴川','遂溪','徐闻'],'肇庆':['端州','鼎湖','高要','四会','广宁','怀集','封开','德庆'],'江门':['蓬江','江海','新会','台山','开平','鹤山','恩平'],'茂名':['茂南','电白','高州','化州','信宜'],'惠州':['惠城','惠阳','博罗','惠东','龙门'],'梅州':['梅江','梅县','兴宁','大埔','丰顺','五华','平远','蕉岭'],'汕尾':['城区','陆丰','海丰','陆河'],'河源':['源城','紫金','龙川','连平','和平','东源'],'阳江':['江城','阳东','阳春','阳西'],'清远':['清城','清新','英德','连州','佛冈','阳山','连山','连南'],'东莞':['莞城','南城','东城','万江','虎门','长安','厚街','寮步','大朗','塘厦','凤岗','常平'],'中山':['石岐','东区','西区','南区','小榄','古镇','三乡','坦洲','南朗'],'潮州':['湘桥','潮安','饶平'],'揭阳':['榕城','揭东','普宁','惠来','揭西'],'云浮':['云城','云安','罗定','新兴','郁南']},
|
||
'江苏':{'南京':['玄武','秦淮','建邺','鼓楼','栖霞','雨花台','江宁','浦口','六合','溧水','高淳'],'苏州':['姑苏','虎丘','吴中','相城','吴江','常熟','张家港','昆山','太仓'],'无锡':['梁溪','锡山','惠山','滨湖','新吴','江阴','宜兴'],'常州':['天宁','钟楼','新北','武进','金坛','溧阳'],'镇江':['京口','润州','丹徒','丹阳','扬中','句容'],'南通':['崇川','通州','海门','启东','如皋','海安','如东'],'扬州':['广陵','邗江','江都','仪征','高邮','宝应'],'泰州':['海陵','高港','姜堰','兴化','靖江','泰兴'],'盐城':['亭湖','盐都','大丰','东台','响水','滨海','阜宁','射阳','建湖'],'淮安':['清江浦','淮安','淮阴','洪泽','涟水','盱眙','金湖'],'连云港':['连云','海州','赣榆','东海','灌云','灌南'],'徐州':['鼓楼','云龙','贾汪','泉山','铜山','新沂','邳州','丰县','沛县','睢宁'],'宿迁':['宿城','宿豫','沭阳','泗阳','泗洪']},
|
||
'浙江':{'杭州':['上城','拱墅','西湖','滨江','萧山','余杭','临平','钱塘','富阳','临安','桐庐','淳安','建德'],'宁波':['海曙','江北','北仑','镇海','鄞州','奉化','余姚','慈溪','象山','宁海'],'温州':['鹿城','龙湾','瓯海','洞头','瑞安','乐清','永嘉','平阳','苍南','文成','泰顺'],'嘉兴':['南湖','秀洲','海宁','平湖','桐乡','嘉善','海盐'],'湖州':['吴兴','南浔','德清','长兴','安吉'],'绍兴':['越城','柯桥','上虞','诸暨','嵊州','新昌'],'金华':['婺城','金东','兰溪','义乌','东阳','永康','武义','浦江','磐安'],'衢州':['柯城','衢江','江山','常山','开化','龙游'],'舟山':['定海','普陀','岱山','嵊泗'],'台州':['椒江','黄岩','路桥','温岭','临海','玉环','三门','天台','仙居'],'丽水':['莲都','龙泉','青田','缙云','遂昌','松阳','云和','庆元','景宁']},
|
||
'山东':{'济南':['历下','市中','槐荫','天桥','历城','长清','章丘','济阳','莱芜','钢城','平阴','商河'],'青岛':['市南','市北','黄岛','崂山','李沧','城阳','即墨','胶州','平度','莱西'],'淄博':['淄川','张店','博山','临淄','周村','桓台','高青','沂源'],'枣庄':['市中','薛城','峄城','台儿庄','山亭','滕州'],'东营':['东营','河口','垦利','利津','广饶'],'烟台':['芝罘','福山','牟平','莱山','蓬莱','龙口','莱阳','莱州','招远','栖霞','海阳'],'潍坊':['潍城','寒亭','坊子','奎文','青州','诸城','寿光','安丘','高密','昌邑','临朐','昌乐'],'济宁':['任城','兖州','曲阜','邹城','微山','鱼台','金乡','嘉祥','汶上','泗水','梁山'],'泰安':['泰山','岱岳','新泰','肥城','宁阳','东平'],'威海':['环翠','文登','荣成','乳山'],'日照':['东港','岚山','五莲','莒县'],'临沂':['兰山','罗庄','河东','沂南','郯城','沂水','兰陵','费县','平邑','莒南','蒙阴','临沭'],'德州':['德城','陵城','乐陵','禹城','宁津','庆云','临邑','齐河','平原','夏津','武城'],'聊城':['东昌府','茌平','临清','阳谷','莘县','东阿','冠县','高唐'],'滨州':['滨城','沾化','邹平','惠民','阳信','无棣','博兴'],'菏泽':['牡丹','定陶','曹县','单县','成武','巨野','郓城','鄄城','东明']},
|
||
'河南':{'郑州':['中原','二七','管城','金水','上街','惠济','巩义','荥阳','新密','新郑','登封','中牟'],'开封':['龙亭','顺河','鼓楼','禹王台','祥符','杞县','通许','尉氏','兰考'],'洛阳':['老城','西工','瀍河','涧西','偃师','孟津','新安','栾川','嵩县','汝阳','宜阳','洛宁','伊川'],'平顶山':['新华','卫东','石龙','湛河','舞钢','汝州','宝丰','叶县','鲁山','郏县'],'安阳':['文峰','北关','殷都','龙安','林州','安阳','汤阴','滑县','内黄'],'鹤壁':['鹤山','山城','淇滨','浚县','淇县'],'新乡':['红旗','卫滨','凤泉','牧野','卫辉','辉县','新乡','获嘉','原阳','延津','封丘','长垣'],'焦作':['解放','中站','马村','山阳','沁阳','孟州','修武','博爱','武陟','温县'],'濮阳':['华龙','清丰','南乐','范县','台前','濮阳'],'许昌':['魏都','建安','禹州','长葛','鄢陵','襄城'],'漯河':['源汇','郾城','召陵','舞阳','临颍'],'三门峡':['湖滨','陕州','义马','灵宝','渑池','卢氏'],'南阳':['宛城','卧龙','邓州','南召','方城','西峡','镇平','内乡','淅川','社旗','唐河','新野','桐柏'],'商丘':['梁园','睢阳','永城','民权','睢县','宁陵','柘城','虞城','夏邑'],'信阳':['浉河','平桥','罗山','光山','新县','商城','固始','潢川','淮滨','息县'],'周口':['川汇','淮阳','项城','扶沟','西华','商水','沈丘','郸城','太康','鹿邑'],'驻马店':['驿城','西平','上蔡','平舆','正阳','确山','泌阳','汝南','遂平','新蔡'],'济源':['济源']},
|
||
'河北':{'石家庄':['长安','桥西','新华','井陉','裕华','藁城','鹿泉','栾城','正定','行唐','灵寿','高邑','深泽','赞皇','无极','平山','元氏','赵县','晋州','新乐'],'唐山':['路南','路北','古冶','开平','丰南','丰润','曹妃甸','遵化','迁安','滦州','滦南','乐亭','迁西','玉田'],'秦皇岛':['海港','山海关','北戴河','抚宁','昌黎','卢龙','青龙'],'邯郸':['邯山','丛台','复兴','峰峰','肥乡','永年','武安','临漳','成安','大名','涉县','磁县','邱县','鸡泽','广平','馆陶','魏县','曲周'],'邢台':['襄都','信都','任泽','南和','南宫','沙河','临城','内丘','柏乡','隆尧','宁晋','巨鹿','新河','广宗','平乡','威县','清河','临西'],'保定':['竞秀','莲池','满城','清苑','徐水','涿州','定州','安国','高碑店','涞水','阜平','定兴','唐县','高阳','容城','涞源','望都','安新','易县','曲阳','蠡县','顺平','博野','雄县'],'张家口':['桥东','桥西','宣化','下花园','万全','崇礼','张北','康保','沽源','尚义','蔚县','阳原','怀安','怀来','涿鹿','赤城'],'承德':['双桥','双滦','鹰手营子','平泉','承德','兴隆','滦平','隆化','丰宁','宽城','围场'],'沧州':['新华','运河','泊头','任丘','黄骅','河间','沧县','青县','东光','海兴','盐山','肃宁','南皮','吴桥','献县','孟村'],'廊坊':['安次','广阳','霸州','三河','固安','永清','香河','大城','文安','大厂'],'衡水':['桃城','冀州','深州','枣强','武邑','武强','饶阳','安平','故城','景县','阜城']},
|
||
'四川':{'成都':['锦江','青羊','金牛','武侯','成华','龙泉驿','青白江','新都','温江','双流','郫都','新津','都江堰','彭州','邛崃','崇州','简阳','金堂','大邑','蒲江'],'绵阳':['涪城','游仙','安州','江油','三台','盐亭','梓潼','平武','北川'],'自贡':['自流井','贡井','大安','沿滩','荣县','富顺'],'攀枝花':['东区','西区','仁和','米易','盐边'],'泸州':['江阳','纳溪','龙马潭','泸县','合江','叙永','古蔺'],'德阳':['旌阳','罗江','广汉','什邡','绵竹','中江'],'广元':['利州','昭化','朝天','旺苍','青川','剑阁','苍溪'],'遂宁':['船山','安居','射洪','蓬溪','大英'],'内江':['市中','东兴','隆昌','威远','资中'],'乐山':['市中','沙湾','五通桥','金口河','峨眉山','犍为','井研','夹江','沐川','峨边','马边'],'南充':['顺庆','高坪','嘉陵','阆中','南部','营山','蓬安','仪陇','西充'],'眉山':['东坡','彭山','仁寿','洪雅','丹棱','青神'],'宜宾':['翠屏','南溪','叙州','江安','长宁','高县','珙县','筠连','兴文','屏山'],'广安':['广安','前锋','华蓥','岳池','武胜','邻水'],'达州':['通川','达川','万源','宣汉','开江','大竹','渠县'],'雅安':['雨城','名山','荥经','汉源','石棉','天全','芦山','宝兴'],'巴中':['巴州','恩阳','通江','南江','平昌'],'资阳':['雁江','安岳','乐至'],'凉山':['西昌','会理','木里','盐源','德昌','会东','宁南','普格','布拖','金阳','昭觉','喜德','冕宁','越西','甘洛','美姑','雷波'],'甘孜':['康定','泸定','丹巴','九龙','雅江','道孚','炉霍','甘孜','新龙','德格','白玉','石渠','色达','理塘','巴塘','乡城','稻城','得荣'],'阿坝':['马尔康','汶川','理县','茂县','松潘','九寨沟','金川','小金','黑水','壤塘','阿坝','若尔盖','红原']},
|
||
'湖北':{'武汉':['江岸','江汉','硚口','汉阳','武昌','青山','洪山','东西湖','汉南','蔡甸','江夏','黄陂','新洲'],'黄石':['黄石港','西塞山','下陆','铁山','大冶','阳新'],'十堰':['茅箭','张湾','郧阳','丹江口','郧西','竹山','竹溪','房县'],'宜昌':['西陵','伍家岗','点军','猇亭','夷陵','宜都','当阳','枝江','远安','兴山','秭归','长阳','五峰'],'襄阳':['襄城','樊城','襄州','老河口','枣阳','宜城','南漳','谷城','保康'],'鄂州':['鄂城','华容','梁子湖'],'荆门':['东宝','掇刀','钟祥','京山','沙洋'],'孝感':['孝南','应城','安陆','汉川','孝昌','大悟','云梦'],'荆州':['沙市','荆州','石首','洪湖','松滋','监利','公安','江陵'],'黄冈':['黄州','麻城','武穴','团风','红安','罗田','英山','浠水','蕲春','黄梅'],'咸宁':['咸安','赤壁','嘉鱼','通城','崇阳','通山'],'随州':['曾都','广水','随县'],'恩施':['恩施','利川','建始','巴东','宣恩','咸丰','来凤','鹤峰'],'仙桃':['仙桃'],'潜江':['潜江'],'天门':['天门']},
|
||
'湖南':{'长沙':['芙蓉','天心','岳麓','开福','雨花','望城','浏阳','宁乡','长沙'],'株洲':['天元','荷塘','芦淞','石峰','渌口','醴陵','攸县','茶陵','炎陵'],'湘潭':['雨湖','岳塘','湘乡','韶山','湘潭'],'衡阳':['珠晖','雁峰','石鼓','蒸湘','南岳','耒阳','常宁','衡阳','衡南','衡山','衡东','祁东'],'邵阳':['双清','大祥','北塔','武冈','邵东','新邵','邵阳','隆回','洞口','绥宁','新宁','城步'],'岳阳':['岳阳楼','云溪','君山','汨罗','临湘','岳阳','华容','湘阴','平江'],'常德':['武陵','鼎城','津市','安乡','汉寿','澧县','临澧','桃源','石门'],'张家界':['永定','武陵源','慈利','桑植'],'益阳':['资阳','赫山','沅江','南县','桃江','安化'],'郴州':['北湖','苏仙','资兴','桂阳','宜章','永兴','嘉禾','临武','汝城','桂东','安仁'],'永州':['零陵','冷水滩','祁阳','东安','双牌','道县','江永','宁远','蓝山','新田','江华'],'怀化':['鹤城','洪江','中方','沅陵','辰溪','溆浦','会同','麻阳','新晃','芷江','靖州','通道'],'娄底':['娄星','冷水江','涟源','双峰','新化'],'湘西':['吉首','泸溪','凤凰','花垣','保靖','古丈','永顺','龙山']},
|
||
'福建':{'福州':['鼓楼','台江','仓山','马尾','晋安','长乐','福清','闽侯','连江','罗源','闽清','永泰','平潭'],'厦门':['思明','湖里','集美','海沧','同安','翔安'],'莆田':['城厢','涵江','荔城','秀屿','仙游'],'三明':['三元','沙县','永安','明溪','清流','宁化','大田','尤溪','将乐','泰宁','建宁'],'泉州':['鲤城','丰泽','洛江','泉港','石狮','晋江','南安','惠安','安溪','永春','德化','金门'],'漳州':['芗城','龙文','龙海','长泰','云霄','漳浦','诏安','东山','南靖','平和','华安'],'南平':['延平','建阳','邵武','武夷山','建瓯','顺昌','浦城','光泽','松溪','政和'],'龙岩':['新罗','永定','漳平','长汀','上杭','武平','连城'],'宁德':['蕉城','福安','福鼎','霞浦','古田','屏南','寿宁','周宁','柘荣']},
|
||
'安徽':{'合肥':['瑶海','庐阳','蜀山','包河','巢湖','长丰','肥东','肥西','庐江'],'芜湖':['镜湖','鸠江','弋江','湾沚','繁昌','无为','南陵'],'蚌埠':['龙子湖','蚌山','禹会','淮上','怀远','五河','固镇'],'淮南':['大通','田家庵','谢家集','八公山','潘集','凤台','寿县'],'马鞍山':['花山','雨山','博望','当涂','含山','和县'],'淮北':['杜集','相山','烈山','濉溪'],'铜陵':['铜官','义安','郊区','枞阳'],'安庆':['迎江','大观','宜秀','桐城','怀宁','潜山','太湖','宿松','望江','岳西'],'黄山':['屯溪','黄山','徽州','歙县','休宁','黟县','祁门'],'滁州':['琅琊','南谯','天长','明光','来安','全椒','定远','凤阳'],'阜阳':['颍州','颍东','颍泉','界首','临泉','太和','阜南','颍上'],'宿州':['埇桥','砀山','萧县','灵璧','泗县'],'六安':['金安','裕安','叶集','霍邱','舒城','金寨','霍山'],'亳州':['谯城','涡阳','蒙城','利辛'],'池州':['贵池','东至','石台','青阳'],'宣城':['宣州','宁国','广德','郎溪','泾县','绩溪','旌德']},
|
||
'江西':{'南昌':['东湖','西湖','青云谱','青山湖','新建','红谷滩','南昌','进贤','安义'],'景德镇':['昌江','珠山','乐平','浮梁'],'萍乡':['安源','湘东','莲花','上栗','芦溪'],'九江':['濂溪','浔阳','柴桑','瑞昌','共青城','庐山','武宁','修水','永修','德安','都昌','湖口','彭泽'],'新余':['渝水','分宜'],'鹰潭':['月湖','余江','贵溪'],'赣州':['章贡','南康','赣县','瑞金','信丰','大余','上犹','崇义','安远','定南','全南','宁都','于都','兴国','会昌','寻乌','石城','龙南'],'吉安':['吉州','青原','井冈山','吉安','吉水','峡江','新干','永丰','泰和','遂川','万安','安福','永新'],'宜春':['袁州','丰城','樟树','高安','奉新','万载','上高','宜丰','靖安','铜鼓'],'抚州':['临川','东乡','南城','黎川','南丰','崇仁','乐安','宜黄','金溪','资溪','广昌'],'上饶':['信州','广丰','广信','德兴','玉山','铅山','横峰','弋阳','余干','鄱阳','万年','婺源']},
|
||
'辽宁':{'沈阳':['和平','沈河','大东','皇姑','铁西','苏家屯','浑南','沈北','于洪','辽中','新民','康平','法库'],'大连':['中山','西岗','沙河口','甘井子','旅顺口','金州','普兰店','瓦房店','庄河','长海'],'鞍山':['铁东','铁西','立山','千山','海城','台安','岫岩'],'抚顺':['新抚','东洲','望花','顺城','抚顺','新宾','清原'],'本溪':['平山','溪湖','明山','南芬','本溪','桓仁'],'丹东':['元宝','振兴','振安','东港','凤城','宽甸'],'锦州':['古塔','凌河','太和','凌海','北镇','黑山','义县'],'营口':['站前','西市','鲅鱼圈','老边','盖州','大石桥'],'阜新':['海州','新邱','太平','清河门','细河','彰武','阜新'],'辽阳':['白塔','文圣','宏伟','弓长岭','太子河','灯塔','辽阳'],'盘锦':['双台子','兴隆台','大洼','盘山'],'铁岭':['银州','清河','调兵山','开原','铁岭','西丰','昌图'],'朝阳':['双塔','龙城','北票','凌源','朝阳','建平','喀左'],'葫芦岛':['连山','龙港','南票','兴城','绥中','建昌']},
|
||
'陕西':{'西安':['新城','碑林','莲湖','灞桥','未央','雁塔','阎良','临潼','长安','高陵','鄠邑','蓝田','周至'],'铜川':['王益','印台','耀州','宜君'],'宝鸡':['渭滨','金台','陈仓','凤翔','岐山','扶风','眉县','陇县','千阳','麟游','凤县','太白'],'咸阳':['秦都','杨陵','渭城','兴平','三原','泾阳','乾县','礼泉','永寿','长武','旬邑','淳化','武功','彬州'],'渭南':['临渭','华州','韩城','华阴','潼关','大荔','合阳','澄城','蒲城','白水','富平'],'延安':['宝塔','安塞','子长','延长','延川','志丹','吴起','甘泉','富县','洛川','宜川','黄龙','黄陵'],'汉中':['汉台','南郑','城固','洋县','西乡','勉县','宁强','略阳','镇巴','留坝','佛坪'],'榆林':['榆阳','横山','神木','府谷','靖边','定边','绥德','米脂','佳县','吴堡','清涧','子洲'],'安康':['汉滨','旬阳','汉阴','石泉','宁陕','紫阳','岚皋','平利','镇坪','白河'],'商洛':['商州','洛南','丹凤','商南','山阳','镇安','柞水']},
|
||
'山西':{'太原':['杏花岭','迎泽','小店','尖草坪','万柏林','晋源','古交','清徐','阳曲','娄烦'],'大同':['平城','云冈','新荣','云州','阳高','天镇','广灵','灵丘','浑源','左云'],'阳泉':['城区','矿区','郊区','平定','盂县'],'长治':['潞州','上党','屯留','潞城','襄垣','平顺','黎城','壶关','长子','武乡','沁县','沁源'],'晋城':['城区','泽州','高平','沁水','阳城','陵川'],'朔州':['朔城','平鲁','怀仁','山阴','应县','右玉'],'晋中':['榆次','太谷','介休','榆社','左权','和顺','昔阳','寿阳','祁县','平遥','灵石'],'运城':['盐湖','永济','河津','临猗','万荣','闻喜','稷山','新绛','绛县','垣曲','夏县','平陆','芮城'],'忻州':['忻府','原平','定襄','五台','代县','繁峙','宁武','静乐','神池','五寨','岢岚','河曲','保德','偏关'],'临汾':['尧都','侯马','霍州','曲沃','翼城','襄汾','洪洞','古县','安泽','浮山','吉县','乡宁','大宁','隰县','永和','蒲县','汾西'],'吕梁':['离石','孝义','汾阳','文水','交城','兴县','临县','柳林','石楼','岚县','方山','中阳','交口']},
|
||
'黑龙江':{'哈尔滨':['道里','南岗','道外','平房','松北','香坊','呼兰','阿城','双城','尚志','五常','依兰','方正','宾县','巴彦','木兰','通河','延寿'],'齐齐哈尔':['龙沙','建华','铁锋','昂昂溪','富拉尔基','碾子山','梅里斯','讷河','龙江','依安','泰来','甘南','富裕','克山','克东','拜泉'],'鸡西':['鸡冠','恒山','滴道','梨树','城子河','麻山','虎林','密山','鸡东'],'鹤岗':['向阳','工农','南山','兴安','东山','兴山','萝北','绥滨'],'双鸭山':['尖山','岭东','四方台','宝山','集贤','友谊','宝清','饶河'],'大庆':['萨尔图','龙凤','让胡路','红岗','大同','肇州','肇源','林甸','杜尔伯特'],'伊春':['伊美','乌翠','友好','金林','铁力','嘉荫','汤旺','丰林','大箐山','南岔'],'佳木斯':['前进','向阳','东风','郊区','同江','富锦','桦南','桦川','汤原','抚远'],'七台河':['新兴','桃山','茄子河','勃利'],'牡丹江':['东安','阳明','爱民','西安','绥芬河','海林','宁安','穆棱','东宁','林口'],'黑河':['爱辉','北安','五大连池','嫩江','逊克','孙吴'],'绥化':['北林','安达','肇东','海伦','望奎','兰西','青冈','庆安','明水','绥棱'],'大兴安岭':['加格达奇','漠河','呼玛','塔河']},
|
||
'吉林':{'长春':['南关','宽城','朝阳','二道','绿园','双阳','九台','榆树','德惠','公主岭','农安'],'吉林':['昌邑','龙潭','船营','丰满','永吉','蛟河','桦甸','舒兰','磐石'],'四平':['铁西','铁东','双辽','梨树','伊通'],'辽源':['龙山','西安','东丰','东辽'],'通化':['东昌','二道江','梅河口','集安','通化','辉南','柳河'],'白山':['浑江','江源','临江','抚松','靖宇','长白'],'松原':['宁江','扶余','长岭','乾安','前郭'],'白城':['洮北','洮南','大安','镇赉','通榆'],'延边':['延吉','图们','敦化','珲春','龙井','和龙','汪清','安图']},
|
||
'云南':{'昆明':['五华','盘龙','官渡','西山','东川','呈贡','安宁','晋宁','富民','宜良','嵩明','石林','禄劝','寻甸'],'曲靖':['麒麟','沾益','马龙','宣威','陆良','师宗','罗平','富源','会泽'],'玉溪':['红塔','江川','澄江','通海','华宁','易门','峨山','新平','元江'],'保山':['隆阳','腾冲','施甸','龙陵','昌宁'],'昭通':['昭阳','鲁甸','巧家','盐津','大关','永善','绥江','镇雄','彝良','威信','水富'],'丽江':['古城','玉龙','永胜','华坪','宁蒗'],'普洱':['思茅','宁洱','墨江','景东','景谷','镇沅','江城','孟连','澜沧','西盟'],'临沧':['临翔','凤庆','云县','永德','镇康','双江','耿马','沧源'],'楚雄':['楚雄','禄丰','双柏','牟定','南华','姚安','大姚','永仁','元谋','武定'],'红河':['蒙自','个旧','开远','弥勒','建水','石屏','泸西','元阳','红河','绿春','金平','屏边','河口'],'文山':['文山','砚山','西畴','麻栗坡','马关','丘北','广南','富宁'],'西双版纳':['景洪','勐海','勐腊'],'大理':['大理','祥云','宾川','弥渡','永平','云龙','洱源','剑川','鹤庆','漾濞','南涧','巍山'],'德宏':['芒市','瑞丽','梁河','盈江','陇川'],'怒江':['泸水','福贡','贡山','兰坪'],'迪庆':['香格里拉','德钦','维西']},
|
||
'贵州':{'贵阳':['南明','云岩','花溪','乌当','白云','观山湖','清镇','开阳','息烽','修文'],'六盘水':['钟山','水城','六枝','盘州'],'遵义':['红花岗','汇川','播州','赤水','仁怀','桐梓','绥阳','正安','道真','务川','凤冈','湄潭','余庆','习水'],'安顺':['西秀','平坝','普定','镇宁','关岭','紫云'],'毕节':['七星关','大方','黔西','金沙','织金','纳雍','威宁','赫章'],'铜仁':['碧江','万山','江口','玉屏','石阡','思南','印江','德江','沿河','松桃'],'黔西南':['兴义','兴仁','普安','晴隆','贞丰','望谟','册亨','安龙'],'黔东南':['凯里','黄平','施秉','三穗','镇远','岑巩','天柱','锦屏','剑河','台江','黎平','榕江','从江','雷山','麻江','丹寨'],'黔南':['都匀','福泉','荔波','贵定','瓮安','独山','平塘','罗甸','长顺','龙里','惠水','三都']},
|
||
'广西':{'南宁':['兴宁','青秀','江南','西乡塘','良庆','邕宁','武鸣','横州','隆安','马山','上林','宾阳'],'柳州':['城中','鱼峰','柳南','柳北','柳江','柳城','鹿寨','融安','融水','三江'],'桂林':['秀峰','叠彩','象山','七星','雁山','临桂','阳朔','灵川','全州','兴安','永福','灌阳','龙胜','资源','平乐','荔浦','恭城'],'梧州':['万秀','长洲','龙圩','岑溪','苍梧','藤县','蒙山'],'北海':['海城','银海','铁山港','合浦'],'防城港':['港口','防城','东兴','上思'],'钦州':['钦南','钦北','灵山','浦北'],'贵港':['港北','港南','覃塘','桂平','平南'],'玉林':['玉州','福绵','北流','容县','陆川','博白','兴业'],'百色':['右江','田阳','靖西','田东','德保','那坡','凌云','乐业','田林','西林','隆林'],'贺州':['八步','平桂','昭平','钟山','富川'],'河池':['金城江','宜州','南丹','天峨','凤山','东兰','罗城','环江','巴马','都安','大化'],'来宾':['兴宾','合山','忻城','象州','武宣','金秀'],'崇左':['江州','凭祥','扶绥','宁明','龙州','大新','天等']},
|
||
'海南':{'海口':['秀英','龙华','琼山','美兰'],'三亚':['海棠','吉阳','天涯','崖州'],'三沙':['三沙'],'儋州':['儋州'],'五指山':['五指山'],'琼海':['琼海'],'文昌':['文昌'],'万宁':['万宁'],'东方':['东方'],'定安':['定安'],'屯昌':['屯昌'],'澄迈':['澄迈'],'临高':['临高'],'白沙':['白沙'],'昌江':['昌江'],'乐东':['乐东'],'陵水':['陵水'],'保亭':['保亭'],'琼中':['琼中']},
|
||
'甘肃':{'兰州':['城关','七里河','西固','安宁','红古','永登','皋兰','榆中'],'嘉峪关':['嘉峪关'],'金昌':['金川','永昌'],'白银':['白银','平川','靖远','会宁','景泰'],'天水':['秦州','麦积','清水','秦安','甘谷','武山','张家川'],'武威':['凉州','民勤','古浪','天祝'],'张掖':['甘州','民乐','临泽','高台','山丹','肃南'],'平凉':['崆峒','华亭','泾川','灵台','崇信','庄浪','静宁'],'酒泉':['肃州','玉门','敦煌','金塔','瓜州','肃北','阿克塞'],'庆阳':['西峰','庆城','环县','华池','合水','正宁','宁县','镇原'],'定西':['安定','通渭','陇西','渭源','临洮','漳县','岷县'],'陇南':['武都','成县','文县','宕昌','康县','西和','礼县','徽县','两当'],'临夏':['临夏','临夏县','康乐','永靖','广河','和政','东乡','积石山'],'甘南':['合作','临潭','卓尼','舟曲','迭部','玛曲','碌曲','夏河']},
|
||
'内蒙古':{'呼和浩特':['新城','回民','玉泉','赛罕','托克托','和林格尔','清水河','武川','土默特左'],'包头':['昆都仑','青山','东河','九原','石拐','白云鄂博','固阳','土默特右','达尔罕茂明安'],'乌海':['海勃湾','海南','乌达'],'赤峰':['红山','元宝山','松山','阿鲁科尔沁','巴林左','巴林右','林西','克什克腾','翁牛特','喀喇沁','宁城','敖汉'],'通辽':['科尔沁','霍林郭勒','科尔沁左翼中','科尔沁左翼后','开鲁','库伦','奈曼','扎鲁特'],'鄂尔多斯':['东胜','康巴什','达拉特','准格尔','鄂托克前','鄂托克','杭锦','乌审','伊金霍洛'],'呼伦贝尔':['海拉尔','扎赉诺尔','满洲里','牙克石','扎兰屯','额尔古纳','根河','阿荣旗','莫力达瓦','鄂伦春','鄂温克','陈巴尔虎','新巴尔虎左','新巴尔虎右'],'巴彦淖尔':['临河','五原','磴口','乌拉特前','乌拉特中','乌拉特后','杭锦后'],'乌兰察布':['集宁','丰镇','卓资','化德','商都','兴和','凉城','察哈尔右翼前','察哈尔右翼中','察哈尔右翼后','四子王'],'兴安盟':['乌兰浩特','阿尔山','科尔沁右翼前','科尔沁右翼中','扎赉特','突泉'],'锡林郭勒':['锡林浩特','二连浩特','阿巴嘎','苏尼特左','苏尼特右','东乌珠穆沁','西乌珠穆沁','太仆寺','镶黄','正镶白','正蓝','多伦'],'阿拉善':['阿拉善左','阿拉善右','额济纳']},
|
||
'新疆':{'乌鲁木齐':['天山','沙依巴克','新市','水磨沟','头屯河','达坂城','米东','乌鲁木齐'],'克拉玛依':['克拉玛依','独山子','白碱滩','乌尔禾'],'吐鲁番':['高昌','鄯善','托克逊'],'哈密':['伊州','巴里坤','伊吾'],'昌吉':['昌吉','阜康','呼图壁','玛纳斯','奇台','吉木萨尔','木垒'],'博州':['博乐','阿拉山口','精河','温泉'],'巴州':['库尔勒','轮台','尉犁','若羌','且末','焉耆','和静','和硕','博湖'],'阿克苏':['阿克苏','温宿','库车','沙雅','新和','拜城','乌什','阿瓦提','柯坪'],'克州':['阿图什','阿克陶','阿合奇','乌恰'],'喀什':['喀什','疏附','疏勒','英吉沙','泽普','莎车','叶城','麦盖提','岳普湖','伽师','巴楚','塔什库尔干'],'和田':['和田','和田县','墨玉','皮山','洛浦','策勒','于田','民丰'],'伊犁':['伊宁','奎屯','霍尔果斯','伊宁县','察布查尔','霍城','巩留','新源','昭苏','特克斯','尼勒克'],'塔城':['塔城','乌苏','额敏','沙湾','托里','裕民','和布克赛尔'],'阿勒泰':['阿勒泰','布尔津','富蕴','福海','哈巴河','青河','吉木乃'],'石河子':['石河子']},
|
||
'西藏':{'拉萨':['城关','堆龙德庆','达孜','林周','当雄','尼木','曲水','墨竹工卡'],'日喀则':['桑珠孜','南木林','江孜','定日','萨迦','拉孜','昂仁','谢通门','白朗','仁布','康马','定结','仲巴','亚东','吉隆','聂拉木','萨嘎','岗巴'],'昌都':['卡若','江达','贡觉','类乌齐','丁青','察雅','八宿','左贡','芒康','洛隆','边坝'],'林芝':['巴宜','工布江达','米林','墨脱','波密','察隅','朗县'],'山南':['乃东','扎囊','贡嘎','桑日','琼结','曲松','措美','洛扎','加查','隆子','错那','浪卡子'],'那曲':['色尼','嘉黎','比如','聂荣','安多','申扎','索县','班戈','巴青','尼玛','双湖'],'阿里':['普兰','札达','噶尔','日土','革吉','改则','措勤']},
|
||
'青海':{'西宁':['城东','城中','城西','城北','湟中','湟源','大通'],'海东':['乐都','平安','民和','互助','化隆','循化'],'海北':['海晏','祁连','刚察','门源'],'黄南':['同仁','尖扎','泽库','河南'],'海南':['共和','同德','贵德','兴海','贵南'],'果洛':['玛沁','班玛','甘德','达日','久治','玛多'],'玉树':['玉树','杂多','称多','治多','囊谦','曲麻莱'],'海西':['德令哈','格尔木','茫崖','乌兰','都兰','天峻']},
|
||
'宁夏':{'银川':['兴庆','西夏','金凤','永宁','贺兰','灵武'],'石嘴山':['大武口','惠农','平罗'],'吴忠':['利通','红寺堡','青铜峡','盐池','同心'],'固原':['原州','西吉','隆德','泾源','彭阳'],'中卫':['沙坡头','中宁','海原']},
|
||
'香港':{'香港':['中西区','湾仔','东区','南区','油尖旺','深水埗','九龙城','黄大仙','观塘','荃湾','屯门','元朗','北区','大埔','沙田','西贡','离岛']},
|
||
'澳门':{'澳门':['澳门半岛','氹仔','路环']},
|
||
'台湾':{'台北':['中正','大同','中山','松山','大安','万华','信义','士林','北投','内湖','南港','文山'],'新北':['板桥','三重','中和','永和','新庄','新店','土城','芦洲','汐止','树林','淡水'],'桃园':['桃园','中坜','平镇','八德','杨梅','芦竹','大溪'],'台中':['中区','东区','南区','西区','北区','北屯','西屯','南屯','大里','太平','丰原'],'台南':['中西','东区','南区','北区','安平','安南','永康','新营'],'高雄':['苓雅','前镇','三民','新兴','前金','盐埕','鼓山','左营','楠梓','凤山','冈山'],'基隆':['仁爱','信义','中正','中山','安乐','暖暖','七堵'],'新竹':['东区','北区','香山','竹北'],'嘉义':['东区','西区'],'苗栗':['苗栗','头份','竹南'],'彰化':['彰化','员林'],'南投':['南投','埔里','草屯'],'云林':['斗六','虎尾'],'屏东':['屏东','潮州'],'宜兰':['宜兰','罗东'],'花莲':['花莲'],'台东':['台东'],'澎湖':['马公']}
|
||
};
|
||
|
||
var QUIZ=[
|
||
{q:'周末你更倾向于怎样度过?',d:'探索社交能量来源',opts:['宅家看书看剧,享受独处时光','约上好友聚会,热闹才开心','一个人去户外徒步探索','看心情,随时切换']},
|
||
{q:'做重要决定时,你更依赖什么?',d:'揭示决策模式',opts:['逻辑分析和客观事实','直觉和内心感受','多方征求意见后再定','综合考虑,权衡利弊']},
|
||
{q:'面对突如其来的变化,第一反应?',d:'测试应变模式',opts:['立即调整计划,快速适应','先有点慌,然后慢慢接受','感到兴奋,喜欢新鲜感','冷静分析,找到最优应对']},
|
||
{q:'在团队中你通常扮演什么角色?',d:'了解协作风格',opts:['组织者和领导者','创意提供者','执行者和细节把控者','协调者和氛围维护者']},
|
||
{q:'朋友形容你最多的是什么?',d:'外部认知画像',opts:['理性、冷静、靠谱','热情、阳光、有趣','温柔、体贴、细腻','独立、自由、有主见']},
|
||
{q:'你更容易被什么打动?',d:'情感触发点',opts:['一段感人的故事','一个精妙的创意','一处绝美的风景','一个实实在在的帮助']},
|
||
{q:'面对压力时通常怎么做?',d:'压力应对机制',opts:['制定详细计划,一步步解决','找人倾诉,释放情绪','暂时逃避,给自己缓冲时间','运动或做事来转移注意力']},
|
||
{q:'情绪更像哪种自然现象?',d:'情绪波动模式',opts:['深海——表面平静,内在丰富','火焰——来得快去得也快','潮汐——有规律地起伏','山峦——稳定不易波动']},
|
||
{q:'理想中的生活状态?',d:'人生价值取向',opts:['稳步上升,一切在掌控中','充满惊喜和可能性','宁静平和,岁月静好','自由自在,不被束缚']},
|
||
{q:'亲密关系中最看重什么?',d:'关系需求模式',opts:['深度的灵魂共鸣和理解','浪漫和激情,保持新鲜感','稳定的陪伴和安全感','共同成长,互相成就']}
|
||
];
|
||
|
||
var PLANETS=[
|
||
{name:'太阳',r:0,s:0,size:14,color:'#FFD700',glow:'rgba(255,215,0,0.3)',desc:'核心自我 · 生命力',orbitDays:365.25},
|
||
{name:'月亮',r:34,s:0.015,size:8,color:'#C0C0C0',glow:'rgba(192,192,192,0.2)',desc:'情绪反应 · 潜意识',orbitDays:27.32},
|
||
{name:'水星',r:52,s:0.025,size:5,color:'#B8860B',glow:'rgba(184,134,11,0.15)',desc:'思维方式 · 沟通',orbitDays:87.97},
|
||
{name:'金星',r:68,s:0.018,size:7,color:'#FF69B4',glow:'rgba(255,105,180,0.2)',desc:'爱情观念 · 审美',orbitDays:224.7},
|
||
{name:'火星',r:82,s:0.012,size:6,color:'#E54D42',glow:'rgba(229,77,66,0.2)',desc:'行动模式 · 欲望',orbitDays:686.98},
|
||
{name:'木星',r:98,s:0.008,size:11,color:'#F5A623',glow:'rgba(245,166,35,0.2)',desc:'幸运领域 · 成长',orbitDays:4332.59},
|
||
{name:'土星',r:114,s:0.006,size:10,color:'#8B8B83',glow:'rgba(139,139,131,0.15)',desc:'责任课题 · 考验',orbitDays:10759.22}
|
||
];
|
||
var CHART_MODE='live'; // 'live' or 'birth'
|
||
var BIRTH_ANGLES=null;
|
||
var REF_DATE=new Date(2000,0,1,12,0,0).getTime();
|
||
var CHART_ZI=[];function chartPreloadIcons(){ZODIAC.forEach(function(z,i){var img=new Image();img.src=ZODIAC_ICON[z.name];CHART_ZI[i]=img;});}
|
||
chartPreloadIcons();
|
||
var CHART_INTRO=-1;
|
||
var CHART_PAIRS=[];
|
||
var CHART_TIMER=null;
|
||
var CHART_REVEALED=[];
|
||
var CHART_CUR_START=0;
|
||
var CHART_LINE_DUR=3000;
|
||
var CHART_FROZEN_NOW=0;
|
||
var CHART_DONE=false; // prevent auto-restart after first play
|
||
|
||
function getPlanetAngles(birth){
|
||
if(!birth)return null;
|
||
var bd=new Date(birth.year,birth.month-1,birth.day,12,0,0).getTime();
|
||
var days=(bd-REF_DATE)/86400000;
|
||
var angles=[];
|
||
PLANETS.forEach(function(p,i){
|
||
if(p.orbitDays){
|
||
var baseAngle=p.baseAngle||0;
|
||
angles.push(((days/p.orbitDays)%1)*Math.PI*2+baseAngle);
|
||
}else{angles.push(0);}
|
||
});
|
||
return angles;
|
||
}
|
||
|
||
var FEED_CAT=['推荐','星盘解读','性格分析','合盘配对','运势播报','心理成长'];
|
||
var FEED=[
|
||
{c:0,t:'天蝎座不为人知的五个秘密',a:'星语师小鹿',d:'2:34',v:'12.8万',tags:['天蝎座','深度'],bg1:'#1a1a2e',bg2:'#8B0000',icon:'🦂'},
|
||
{c:0,t:'MBTI测试结果反转!我居然不是INTJ',a:'心理探长',d:'1:52',v:'8.3万',tags:['性格测试','反转'],bg1:'#16213e',bg2:'#0f3460',icon:'🧠'},
|
||
{c:1,t:'教你三分钟看懂自己的本命星盘',a:'占星小课堂',d:'3:15',v:'25.6万',tags:['星盘入门','教程'],bg1:'#0f3460',bg2:'#1a1a2e',icon:'🌟'},
|
||
{c:2,t:'双人合盘大揭秘:你们真的合适吗',a:'星空对话',d:'3:16',v:'20.1万',tags:['合盘','感情'],bg1:'#2d1b69',bg2:'#1a1a2e',icon:'💫'},
|
||
{c:1,t:'十二上升星座的外貌气质全解析',a:'星座美学',d:'4:02',v:'18.3万',tags:['上升星座','外貌'],bg1:'#1a1a2e',bg2:'#2d1b69',icon:'✨'},
|
||
{c:3,t:'水逆期生存指南:避开这三个坑',a:'星座大叔',d:'2:08',v:'9.7万',tags:['水逆','避坑'],bg1:'#0f3460',bg2:'#16213e',icon:'⚠️'},
|
||
{c:4,t:'2026下半年十二星座运势总览',a:'星空预言家',d:'5:30',v:'33.2万',tags:['运势','年度'],bg1:'#1a1a2e',bg2:'#0f3460',icon:'🔮'},
|
||
{c:5,t:'如何走出焦虑:占星视角的情绪管理',a:'心灵星座',d:'2:45',v:'11.5万',tags:['焦虑','情绪管理'],bg1:'#16213e',bg2:'#2d1b69',icon:'💆'},
|
||
{c:0,t:'金星落在十二星座的爱情模式',a:'恋爱占星师',d:'4:20',v:'16.7万',tags:['金星','爱情'],bg1:'#2d1b69',bg2:'#1a1a2e',icon:'💕'},
|
||
{c:2,t:'INTJ和ENFP为什么是天生一对',a:'人格解码',d:'2:55',v:'7.2万',tags:['性格配对','MBTI'],bg1:'#0f3460',bg2:'#16213e',icon:'🎭'},
|
||
{c:1,t:'冥王星换座:未来二十年大变局',a:'深度占星',d:'6:10',v:'28.9万',tags:['冥王星','时代'],bg1:'#1a1a2e',bg2:'#8B0000',icon:'🌑'},
|
||
{c:4,t:'本周十二星座注意事项',a:'每周星运',d:'3:40',v:'14.1万',tags:['周运','提醒'],bg1:'#16213e',bg2:'#0f3460',icon:'📅'}
|
||
];
|
||
|
||
var HOROSCOPES=[
|
||
{msg:'今天的星象提示你:相信直觉。某个看似偶然的相遇可能带来重要转机。',color:'珊瑚粉',num:7},
|
||
{msg:'创造力格外活跃,把灵感记录下来。月亮与海王星的互动让直觉变得敏锐。',color:'薰衣草紫',num:3},
|
||
{msg:'保持耐心是今天的关键词,好事值得等待。火星给你带来额外行动力。',color:'琥珀橙',num:9},
|
||
{msg:'适合整理和规划的一天,为未来播下种子。木星的幸运光环正照耀着你。',color:'薄荷绿',num:5},
|
||
{msg:'勇敢迈出第一步,宇宙会回应你的勇气。金星与木星的相位带来好运。',color:'天空蓝',num:8},
|
||
{msg:'给自己一些独处的时间,倾听内心的声音。今日适合冥想和自我关怀。',color:'玫瑰金',num:2},
|
||
{msg:'一个久违的朋友可能会联系你,珍惜这份重逢。水星顺行带来沟通顺畅。',color:'暖黄色',num:6},
|
||
{msg:'处理事务时多一份耐心,今天适合完成搁置已久的计划。',color:'雾蓝色',num:4}
|
||
];
|
||
|
||
var TRENDING=[
|
||
{t:'十二上升星座全解',d:'外貌·气质·第一印象',i:'✨'},
|
||
{t:'月亮星座看原生家庭',d:'童年模式如何影响你',i:'🌙'},
|
||
{t:'金星星座看爱情',d:'你的爱情语言是什么',i:'💕'},
|
||
{t:'火星星座看行动力',d:'驱动你的内在引擎',i:'🔥'}
|
||
];
|
||
|
||
// ═══════ STATE ═══════
|
||
var S={tab:'home',quizIdx:0,answers:[],birth:null,sign:null,feedCat:0,isMember:false,history:[],navHistory:[]};
|
||
|
||
// ═══════ INIT ═══════
|
||
(function init(){
|
||
var h=localStorage.getItem('xj_history');
|
||
S.history=h?JSON.parse(h):[];
|
||
// Migrate old signEmoji → signBadge
|
||
S.history.forEach(function(r){if(!r.signBadge&&r.signEmoji){var z=ZODIAC.find(function(zz){return zz.name===r.signName});if(z)r.signBadge=zodiacBadge(z);}});
|
||
if(S.history.length>0){var last=S.history[S.history.length-1];S.sign=ZODIAC.find(function(z){return z.name===last.signName});S.birth=last.birth;BIRTH_ANGLES=getPlanetAngles(S.birth);CHART_MODE='birth';}
|
||
S.isMember=localStorage.getItem('xj_member')==='1';
|
||
|
||
renderHome();renderFeedTabs();renderFeed();renderHistory();renderProfile();
|
||
setTimeout(function(){drawChart()},200);
|
||
|
||
var today=new Date();var seed=(today.getFullYear()*10000+(today.getMonth()+1)*100+today.getDate())%HOROSCOPES.length;
|
||
var ho=HOROSCOPES[seed];
|
||
document.querySelector('#horoCard .hday').textContent=today.getFullYear()+'年'+(today.getMonth()+1)+'月'+today.getDate()+'日 · 今日运势';
|
||
document.querySelector('#horoCard .hmsg').textContent=ho.msg;
|
||
document.getElementById('hlColor').textContent=ho.color;
|
||
document.getElementById('hlNum').textContent=ho.num;
|
||
var m=today.getMonth()+1,d=today.getDate();
|
||
document.getElementById('hlMonth').textContent=m+'月'+d+'日 · 今日星象';
|
||
var cz=getZodiac(m,d);
|
||
document.getElementById('hzEmoji').innerHTML=zodiacBadge(cz);
|
||
document.getElementById('hzSign').textContent=cz.name+'季';
|
||
document.getElementById('hzDate').textContent=cz.trait;
|
||
renderTrending();
|
||
setupTestInputs();
|
||
})();
|
||
|
||
function setupTestInputs(){
|
||
var ms=document.getElementById('tMonth');if(!ms||ms.options.length>1)return;
|
||
for(var i=1;i<=12;i++){var o=document.createElement('option');o.value=i;o.text=i+'月';ms.appendChild(o);}
|
||
var ds=document.getElementById('tDay');for(var i=1;i<=31;i++){var o=document.createElement('option');o.value=i;o.text=i+'日';ds.appendChild(o);}
|
||
var hs=document.getElementById('tHour');HOURS.forEach(function(h,i){var o=document.createElement('option');o.value=i;o.text=h;hs.appendChild(o);});
|
||
var ps=document.getElementById('tProv');
|
||
Object.keys(REGIONS).forEach(function(p){var o=document.createElement('option');o.value=p;o.text=p;ps.appendChild(o);});
|
||
}
|
||
function onProvChange(){
|
||
var p=document.getElementById('tProv').value;
|
||
var cs=document.getElementById('tCity');cs.innerHTML='<option value="">市区</option>';
|
||
var ds=document.getElementById('tDist');ds.innerHTML='<option value="">县/区</option>';
|
||
if(p&®IONS[p]){Object.keys(REGIONS[p]).forEach(function(c){var o=document.createElement('option');o.value=c;o.text=c;cs.appendChild(o);});}
|
||
}
|
||
function onCityChange(){
|
||
var p=document.getElementById('tProv').value;
|
||
var c=document.getElementById('tCity').value;
|
||
var ds=document.getElementById('tDist');ds.innerHTML='<option value="">县/区</option>';
|
||
if(p&&c&®IONS[p]&®IONS[p][c]){REGIONS[p][c].forEach(function(d){var o=document.createElement('option');o.value=d;o.text=d;ds.appendChild(o);});}
|
||
}
|
||
|
||
// ═══════ NAVIGATION ═══════
|
||
var MAIN_TABS=['home','chart','report','community','profile'];
|
||
|
||
function showPage(id,title,showBack,showNav){
|
||
document.querySelectorAll('.page').forEach(function(p){p.classList.remove('active')});
|
||
document.getElementById('page-'+id).classList.add('active');
|
||
S.tab=id;
|
||
|
||
// Topbar
|
||
document.querySelector('#topbar .tbt').textContent=title;
|
||
var backBtn=document.getElementById('backBtn');
|
||
if(showBack){backBtn.classList.add('show')}else{backBtn.classList.remove('show')}
|
||
|
||
// Bottom nav
|
||
var nav=document.getElementById('bottomNav');
|
||
if(nav) nav.style.display='none'; // 统一由愈心谷壳导航,星镜内不再显示底栏
|
||
|
||
// Highlight nav item
|
||
document.querySelectorAll('.nav-item').forEach(function(n){n.classList.remove('active')});
|
||
if(showNav){
|
||
var idx=MAIN_TABS.indexOf(id);
|
||
if(idx>=0)document.querySelectorAll('.nav-item')[idx].classList.add('active');
|
||
}
|
||
|
||
S.navHistory.push({id:id,title:title,showBack:showBack,showNav:showNav});
|
||
}
|
||
|
||
function switchTab(tab){
|
||
var titles={home:'星镜',chart:'星镜 · 星盘',report:'星镜 · 报告',community:'星镜 · 社区',profile:'星镜 · 我的'};
|
||
showPage(tab,titles[tab],false,true);
|
||
if(tab==='chart'){setTimeout(function(){drawChart();startChartIntro();},100);}
|
||
if(tab==='home')renderHome();
|
||
}
|
||
|
||
function goTest(){
|
||
S.quizIdx=0;S.answers=[];
|
||
setupTestInputs();
|
||
showPage('test-birth','星镜 · 测试',true,false);
|
||
}
|
||
|
||
function goHome(){
|
||
showPage('home','星镜',false,true);
|
||
renderHome();
|
||
}
|
||
|
||
function openSchulte(){
|
||
showPage('schulte','星镜 · 舒尔特',true,false);
|
||
initSchulteBest();
|
||
if(schulteState.running){clearInterval(schulteState.timer);schulteState.timer=null;}
|
||
schulteState.running=false;schulteState.next=1;
|
||
document.getElementById('schulteTimer').textContent='00:00.0';
|
||
document.getElementById('schulteBtn').textContent='开始训练';
|
||
document.getElementById('schulteSub').textContent='按顺序点击 1→25,训练专注力与反应速度';
|
||
var scene=document.getElementById('cubeScene');scene.classList.remove('paused');
|
||
var cube=document.getElementById('cubeEl');cube.style.transform='rotateX(-15deg) rotateY(25deg)';
|
||
buildSchulteGrid();
|
||
}
|
||
|
||
function goBack(){
|
||
if(S.navHistory.length<=1){location.href='know.html';return;}
|
||
S.navHistory.pop(); // remove current
|
||
var prev=S.navHistory[S.navHistory.length-1];
|
||
if(!prev){goHome();return;}
|
||
showPage(prev.id,prev.title,prev.showBack,prev.showNav);
|
||
if(prev.id==='home')renderHome();
|
||
if(prev.id==='chart')setTimeout(function(){drawChart()},100);
|
||
}
|
||
|
||
// ═══════ ZODIAC ═══════
|
||
function getZodiac(m,d){
|
||
for(var i=0;i<ZODIAC.length;i++){var z=ZODIAC[i];for(var j=0;j<z.range.length;j++){var r=z.range[j];if((m===r[0]&&d>=r[1])||(m===r[2]&&d<=r[3]))return z;}}
|
||
return ZODIAC[0];
|
||
}
|
||
|
||
// ═══════ TEST FLOW ═══════
|
||
function startQuiz(){
|
||
var y=parseInt(document.getElementById('tYear').value);
|
||
var m=parseInt(document.getElementById('tMonth').value);
|
||
var d=parseInt(document.getElementById('tDay').value);
|
||
if(!y||!m||!d){showToast('请填写完整的出生年月日');return;}
|
||
if(y<1900||y>2026){showToast('请输入有效的出生年份');return;}
|
||
S.birth={year:y,month:m,day:d};
|
||
S.sign=getZodiac(m,d);
|
||
S.quizIdx=0;S.answers=[];
|
||
showPage('test-quiz','星镜 · 答题',true,false);
|
||
renderQuizCard();
|
||
}
|
||
|
||
function renderQuizCard(){
|
||
var q=QUIZ[S.quizIdx];
|
||
document.getElementById('quizHint').textContent=q.d;
|
||
document.getElementById('qNow').textContent=S.quizIdx+1;
|
||
document.getElementById('qBar').style.width=((S.quizIdx+1)/QUIZ.length*100)+'%';
|
||
var h='<div class="quiz-q"><div class="q-text">'+q.q+'</div>';
|
||
q.opts.forEach(function(o,i){h+='<button class="quiz-opt" onclick="pickAnswer('+i+')">'+o+'</button>';});
|
||
h+='</div>';
|
||
document.getElementById('quizCard').innerHTML=h;
|
||
}
|
||
|
||
function pickAnswer(idx){
|
||
S.answers.push(idx);S.quizIdx++;
|
||
if(S.quizIdx>=QUIZ.length){showResult();}else{renderQuizCard();}
|
||
}
|
||
|
||
function showResult(){
|
||
showPage('test-result','星镜 · 解读',true,false);
|
||
if(S.birth){BIRTH_ANGLES=getPlanetAngles(S.birth);CHART_MODE='birth';updateChartToggle();}
|
||
var sign=S.sign,a=S.answers;
|
||
|
||
var dims=[
|
||
{name:'开放性',val:Math.max(20,(a[1]===3||a[8]===3?60:20)+20+(a[1]===3?20:0)),color:'#4A90E2',left:'传统',right:'好奇'},
|
||
{name:'尽责性',val:Math.max(20,(a[6]===0||a[0]===0?55:20)+20+(a[6]===0?25:0)),color:'#5CB85C',left:'随性',right:'自律'},
|
||
{name:'外向性',val:Math.max(20,(a[0]===1||a[3]===0?60:20)+20+(a[3]===0?20:0)),color:'#F5A623',left:'内向',right:'外向'},
|
||
{name:'宜人性',val:Math.max(20,(a[4]===2||a[9]===2?55:20)+20+(a[9]===2?20:0)),color:'#FF69B4',left:'独立',right:'共情'},
|
||
{name:'情绪性',val:Math.max(20,(a[7]===1||a[2]===1?50:25)+25+(a[7]===1?25:0)),color:'#E54D42',left:'稳定',right:'敏感'}
|
||
];
|
||
|
||
var mbti='';
|
||
mbti+=(a[0]===0||a[0]===2?'I':'E');mbti+=(a[1]===0||a[1]===3?'T':'F');
|
||
mbti+=(a[6]===0?'J':'P');mbti+=(a[5]===1||a[8]===3?'N':'S');
|
||
|
||
var elScore={火:25,土:25,风:25,水:25};
|
||
if(sign.el==='火')elScore.火+=20;else if(sign.el==='土')elScore.土+=20;else if(sign.el==='风')elScore.风+=20;else elScore.水+=20;
|
||
elScore.火+=a[0]===1?10:a[0]===3?5:0;elScore.土+=a[6]===0?10:a[3]===2?5:0;
|
||
elScore.风+=a[1]===0?10:a[5]===3?5:0;elScore.水+=a[9]===0?10:a[4]===2?5:0;
|
||
var total=elScore.火+elScore.土+elScore.风+elScore.水;
|
||
var els=[{name:'火',pct:Math.round(elScore.火/total*100),color:'#E54D42'},{name:'土',pct:Math.round(elScore.土/total*100),color:'#5CB85C'},{name:'风',pct:Math.round(elScore.风/total*100),color:'#4A90E2'},{name:'水',pct:Math.round(elScore.水/total*100),color:'#7B68EE'}];
|
||
|
||
var style=a[8]===0?'稳步前行型':a[8]===1?'探索冒险型':a[8]===2?'宁静致远型':'自由奔放型';
|
||
var emotion=a[7]===0?'深沉内敛':a[7]===1?'热烈奔放':a[7]===2?'起伏有致':'稳定平和';
|
||
var love=a[9]===0?'灵魂共鸣型':a[9]===1?'浪漫激情型':a[9]===2?'温暖陪伴型':'成长伙伴型';
|
||
|
||
var h='';
|
||
h+='<div class="result-hero"><div class="rzodiac">'+zodiacBadge(sign)+'</div><div class="rsign">'+sign.name+'</div><div class="rmbti">'+mbti+' · '+style+'</div><div>';
|
||
h+='<span class="result-tag">'+sign.el+'象</span><span class="result-tag">'+emotion+'</span><span class="result-tag">'+love+'</span></div></div>';
|
||
|
||
h+='<div class="card card-sm"><div class="card-title">四大元素能量分布</div>';
|
||
els.forEach(function(e){h+='<div class="elem-bar"><span class="el">'+e.name+'</span><div class="eb"><div class="ebf" style="width:'+e.pct+'%;background:'+e.color+'"></div></div><span class="ev">'+e.pct+'%</span></div>';});
|
||
h+='</div>';
|
||
|
||
h+='<div class="card card-sm"><div class="card-title">人格五维度画像</div>';
|
||
dims.forEach(function(d){h+='<div class="dim-row"><span class="dl">'+d.left+'</span><div class="dbar"><div class="dfill" style="width:'+d.val+'%;background:'+d.color+'">'+d.name+'</div></div><span class="dr">'+d.right+'</span></div>';});
|
||
h+='</div>';
|
||
|
||
h+='<div class="card card-sm"><div class="card-title">性格综述</div><div class="card-sub">你是一个<strong>'+sign.name+'</strong>,'+sign.trait+'。属于<strong>'+sign.el+'象星座</strong>,风格偏向<strong>'+style+'</strong>。情感方面表现为<strong>'+emotion+'</strong>,在亲密关系中最看重<strong>'+love.replace('型','')+'</strong>。</div></div>';
|
||
|
||
h+='<button class="btn btn-pri btn-block" onclick="playVideoReport()">▶ 播放专属视频报告</button>';
|
||
h+='<button class="btn btn-outline btn-block btn-sm" onclick="switchTab(\'chart\')" style="margin-top:6px">◎ 查看动态星盘</button>';
|
||
|
||
document.getElementById('resultContent').innerHTML=h;
|
||
|
||
var entry={signName:sign.name,signBadge:zodiacBadge(sign),mbti:mbti,style:style,birth:S.birth,el:sign.el,date:new Date().toISOString().slice(0,10),els:els,dims:dims};
|
||
S.history.push(entry);localStorage.setItem('xj_history',JSON.stringify(S.history));
|
||
renderHistory();renderProfile();
|
||
}
|
||
|
||
// ═══════ HOME ═══════
|
||
function renderHome(){
|
||
if(S.sign){document.getElementById('hzEmoji').innerHTML=zodiacBadge(S.sign);document.getElementById('hzSign').textContent=S.sign.name;document.getElementById('hzDate').textContent=S.sign.trait;}
|
||
}
|
||
function renderTrending(){
|
||
var h='';TRENDING.forEach(function(it){h+='<div style="flex-shrink:0;width:130px;background:#fff;border-radius:12px;padding:14px 12px;text-align:center;box-shadow:0 2px 6px rgba(0,0,0,0.03);cursor:pointer" onclick="showToast(\'即将上线\')"><div style="font-size:28px;margin-bottom:4px">'+it.i+'</div><div style="font-size:12px;font-weight:600">'+it.t+'</div><div style="font-size:10px;color:var(--sub)">'+it.d+'</div></div>';});
|
||
document.getElementById('trendingRow').innerHTML=h;
|
||
}
|
||
|
||
// ═══════ CHART ═══════
|
||
var chartAngle=0,chartZoom=1,chartDragging=false,chartLastX=0,chartPinchDist=0;
|
||
|
||
function drawChart(){
|
||
var canvas=document.getElementById('chartCanvas');if(!canvas)return;
|
||
var ctx=canvas.getContext('2d'),dpr=window.devicePixelRatio||1;
|
||
var w=canvas.parentElement.clientWidth-32;if(w<10)return;
|
||
var s=Math.min(w,380);canvas.width=s*dpr;canvas.height=s*dpr;canvas.style.width=s+'px';canvas.style.height=s+'px';ctx.scale(dpr,dpr);
|
||
var cx=s/2,cy=s/2,mr=s/2-16;
|
||
|
||
function render(){
|
||
ctx.clearRect(0,0,s,s);ctx.fillStyle='#0a0a1a';ctx.fillRect(0,0,s,s);
|
||
ctx.save();ctx.translate(cx,cy);ctx.scale(chartZoom,chartZoom);ctx.rotate(chartAngle);
|
||
var seed=42;
|
||
for(var i=0;i<80;i++){seed=(seed*16807)%2147483647;var sr=12+((seed%1000)/1000)*(mr-12),sa=((seed%6283)/1000);ctx.fillStyle='rgba(255,255,255,'+(0.15+Math.sin(Date.now()/2500+i*0.7)*0.12)+')';ctx.beginPath();ctx.arc(Math.cos(sa)*sr,Math.sin(sa)*sr,0.5+Math.random()*0.6,0,Math.PI*2);ctx.fill();}
|
||
ctx.strokeStyle='rgba(255,255,255,0.06)';ctx.lineWidth=1;ctx.beginPath();ctx.arc(0,0,mr,0,Math.PI*2);ctx.stroke();ctx.beginPath();ctx.arc(0,0,mr-4,0,Math.PI*2);ctx.stroke();
|
||
for(var i=0;i<12;i++){var a=i/12*Math.PI*2-Math.PI/2;ctx.strokeStyle='rgba(255,255,255,0.03)';ctx.lineWidth=0.5;ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(Math.cos(a)*mr,Math.sin(a)*mr);ctx.stroke();}
|
||
// Draw zodiac icons around the wheel
|
||
var isz=16;
|
||
for(var i=0;i<12;i++){
|
||
var a=i/12*Math.PI*2-Math.PI/2;
|
||
var ix=Math.cos(a)*(mr-14),iy=Math.sin(a)*(mr-14);
|
||
ctx.save();ctx.translate(ix,iy);
|
||
ctx.globalAlpha=0.7;
|
||
if(CHART_ZI[i]&&CHART_ZI[i].complete)ctx.drawImage(CHART_ZI[i],-isz,-isz,isz*2,isz*2);
|
||
ctx.restore();
|
||
}
|
||
PLANETS.forEach(function(p){if(p.r>0){ctx.strokeStyle='rgba(255,255,255,0.03)';ctx.lineWidth=0.5;ctx.beginPath();ctx.arc(0,0,p.r,0,Math.PI*2);ctx.stroke();}});
|
||
var now=Date.now()/1000;
|
||
if(CHART_MODE==='birth'&&BIRTH_ANGLES){now=0;}
|
||
// Freeze time during intro so planets match locked pairs
|
||
if(CHART_INTRO>=0){if(CHART_FROZEN_NOW===0)CHART_FROZEN_NOW=now;now=CHART_FROZEN_NOW;}
|
||
var pos=[];
|
||
PLANETS.forEach(function(p,i){
|
||
var angle;
|
||
if(CHART_MODE==='birth'&&BIRTH_ANGLES){angle=BIRTH_ANGLES[i]||0;}
|
||
else{angle=(p.r>0)?(now*p.s+i*0.8):0;}
|
||
pos.push({x:Math.cos(angle)*p.r,y:Math.sin(angle)*p.r});
|
||
});
|
||
// Build pairs only once per intro (lock during animation)
|
||
if(CHART_INTRO<0||CHART_PAIRS.length===0){
|
||
CHART_PAIRS=[];
|
||
var seen={};
|
||
// Step 1: proximity-based pairs
|
||
for(var i=0;i<pos.length;i++){for(var j=i+1;j<pos.length;j++){
|
||
var dx=pos[j].x-pos[i].x,dy=pos[j].y-pos[i].y;
|
||
if(Math.hypot(dx,dy)<100){var key=i+','+j;seen[key]=true;CHART_PAIRS.push({a:i,b:j,ax:pos[i].x,ay:pos[i].y,bx:pos[j].x,by:pos[j].y,order:Math.min(PLANETS[i].r,PLANETS[j].r)});}
|
||
}}
|
||
// Step 2: guarantee every planet has at least 1 line (closest neighbour)
|
||
for(var i=0;i<pos.length;i++){
|
||
var has=false;for(var pi=0;pi<CHART_PAIRS.length;pi++){if(CHART_PAIRS[pi].a===i||CHART_PAIRS[pi].b===i){has=true;break;}}
|
||
if(!has){
|
||
var bestJ=-1,bestDist=Infinity;
|
||
for(var j=0;j<pos.length;j++){if(j===i)continue;var dd=Math.hypot(pos[j].x-pos[i].x,pos[j].y-pos[i].y);if(dd<bestDist){bestDist=dd;bestJ=j;}}
|
||
if(bestJ>=0){
|
||
var aa=Math.min(i,bestJ),bb=Math.max(i,bestJ),key=aa+','+bb;
|
||
if(!seen[key]){seen[key]=true;CHART_PAIRS.push({a:aa,b:bb,ax:pos[aa].x,ay:pos[aa].y,bx:pos[bb].x,by:pos[bb].y,order:Math.min(PLANETS[aa].r,PLANETS[bb].r)});}
|
||
}
|
||
}
|
||
}
|
||
CHART_PAIRS.sort(function(p,q){return p.order-q.order;});
|
||
}
|
||
// Draw aspect lines with animation
|
||
var introDone=(CHART_INTRO<0&&CHART_REVEALED.length>0);
|
||
for(var pi=0;pi<CHART_PAIRS.length;pi++){
|
||
var pr=CHART_PAIRS[pi];
|
||
var isRevealed=CHART_REVEALED.indexOf(pi)>=0;
|
||
var isCurrent=(CHART_INTRO>=0&&pi===CHART_INTRO);
|
||
if(!isRevealed&&!isCurrent)continue;
|
||
var alpha, lw;
|
||
if(isCurrent){alpha=0.8;lw=1.8;}
|
||
else if(introDone){alpha=0.35;lw=0.6;}
|
||
else{alpha=0.3;lw=0.5;}
|
||
ctx.strokeStyle='rgba(255,255,255,'+alpha+')';ctx.lineWidth=lw;
|
||
ctx.beginPath();
|
||
if(isCurrent){
|
||
var elapsed=Date.now()-CHART_CUR_START;
|
||
var t=Math.min(1,elapsed/CHART_LINE_DUR);
|
||
// ease-out
|
||
t=1-Math.pow(1-t,3);
|
||
ctx.moveTo(pr.ax,pr.ay);
|
||
ctx.lineTo(pr.ax+(pr.bx-pr.ax)*t,pr.ay+(pr.by-pr.ay)*t);
|
||
}else{
|
||
ctx.moveTo(pr.ax,pr.ay);ctx.lineTo(pr.bx,pr.by);
|
||
}
|
||
ctx.stroke();
|
||
}
|
||
// Highlight active zodiac sign
|
||
if(CHART_INTRO>=0&&CHART_INTRO<CHART_PAIRS.length){
|
||
var ap=CHART_PAIRS[CHART_INTRO];
|
||
var midAngle=Math.atan2((ap.ay+ap.by)/2,(ap.ax+ap.bx)/2);
|
||
var zi=Math.floor(((midAngle+Math.PI/2+Math.PI*2)%(Math.PI*2))/(Math.PI*2)*12);
|
||
var za=zi/12*Math.PI*2-Math.PI/2;
|
||
ctx.fillStyle='rgba(255,255,255,0.7)';
|
||
var hz=22;
|
||
ctx.save();ctx.translate(Math.cos(za)*(mr-10),Math.sin(za)*(mr-10));
|
||
if(CHART_ZI[zi]&&CHART_ZI[zi].complete)ctx.drawImage(CHART_ZI[zi],-hz,-hz,hz*2,hz*2);
|
||
ctx.restore();
|
||
}
|
||
// Post-intro: highlight current sun zodiac sign with glow + enlarged icon
|
||
if(CHART_DONE){
|
||
var activeZi;
|
||
if(CHART_MODE==='birth'&&S.sign){activeZi=ZODIAC.indexOf(S.sign);}
|
||
else{var cz2=getZodiac(new Date().getMonth()+1,new Date().getDate());activeZi=ZODIAC.indexOf(cz2);}
|
||
if(activeZi>=0){
|
||
var activeA=activeZi/12*Math.PI*2-Math.PI/2;
|
||
var pulse=1+Math.sin(Date.now()/1200)*0.08;
|
||
var az=18*pulse;
|
||
var ag=ctx.createRadialGradient(Math.cos(activeA)*(mr-10),Math.sin(activeA)*(mr-10),az*0.5,Math.cos(activeA)*(mr-10),Math.sin(activeA)*(mr-10),az*2);
|
||
ag.addColorStop(0,'rgba(255,215,0,0.4)');ag.addColorStop(0.5,'rgba(255,180,0,0.15)');ag.addColorStop(1,'rgba(255,180,0,0)');
|
||
ctx.fillStyle=ag;ctx.beginPath();ctx.arc(Math.cos(activeA)*(mr-10),Math.sin(activeA)*(mr-10),az*2,0,Math.PI*2);ctx.fill();
|
||
ctx.save();ctx.translate(Math.cos(activeA)*(mr-10),Math.sin(activeA)*(mr-10));
|
||
ctx.globalAlpha=0.95;
|
||
if(CHART_ZI[activeZi]&&CHART_ZI[activeZi].complete)ctx.drawImage(CHART_ZI[activeZi],-az,-az,az*2,az*2);
|
||
ctx.restore();
|
||
// Show name below the icon
|
||
ctx.fillStyle='rgba(255,255,255,0.8)';ctx.font='bold 10px sans-serif';ctx.textAlign='center';
|
||
ctx.fillText(ZODIAC[activeZi].name,Math.cos(activeA)*(mr-10),Math.sin(activeA)*(mr-10)+az+10);
|
||
}
|
||
}
|
||
PLANETS.forEach(function(p,i){var angle;if(CHART_MODE==='birth'&&BIRTH_ANGLES){angle=BIRTH_ANGLES[i]||0;}else{angle=(p.r>0)?(now*p.s+i*0.8):0;}var px=Math.cos(angle)*p.r,py=Math.sin(angle)*p.r;var g=ctx.createRadialGradient(px,py,0,px,py,p.size*1.8);g.addColorStop(0,p.glow);g.addColorStop(1,'rgba(0,0,0,0)');ctx.fillStyle=g;ctx.beginPath();ctx.arc(px,py,p.size*1.8,0,Math.PI*2);ctx.fill();ctx.fillStyle=p.color;ctx.beginPath();ctx.arc(px,py,p.size,0,Math.PI*2);ctx.fill();ctx.fillStyle='rgba(255,255,255,0.5)';ctx.font='8px sans-serif';ctx.textAlign='center';ctx.fillText(p.name,px,py-p.size-5);});
|
||
var sg=ctx.createRadialGradient(0,0,0,0,0,15);sg.addColorStop(0,'#FFF8DC');sg.addColorStop(0.4,'#FFD700');sg.addColorStop(1,'rgba(255,215,0,0)');ctx.fillStyle=sg;ctx.beginPath();ctx.arc(0,0,15,0,Math.PI*2);ctx.fill();ctx.fillStyle='#FFD700';ctx.beginPath();ctx.arc(0,0,7,0,Math.PI*2);ctx.fill();
|
||
ctx.restore();
|
||
}
|
||
render();
|
||
canvas.onclick=function(e){var rect=canvas.getBoundingClientRect();var mx=e.clientX-rect.left-cx,my=e.clientY-rect.top-cy;var cos=Math.cos(-chartAngle),sin=Math.sin(-chartAngle);var rx=mx*cos-my*sin,ry=mx*sin+my*cos;var found=-1;PLANETS.forEach(function(p,i){var a;if(CHART_MODE==='birth'&&BIRTH_ANGLES){a=BIRTH_ANGLES[i]||0;}else{var now2=Date.now()/1000;a=(p.r>0)?(now2*p.s+i*0.8):0;}var px=Math.cos(a)*p.r,py=Math.sin(a)*p.r;if(Math.hypot(rx-px,ry-py)<p.size*2.5)found=i;});if(Math.hypot(rx,ry)<14)found=0;if(found>=0){var p=PLANETS[found];document.getElementById('chartInfo').innerHTML='<span class="pn">'+p.name+'</span> · '+p.desc;document.getElementById('chartHint').textContent='已选中:'+p.name;}};
|
||
canvas.addEventListener('mousedown',function(e){chartDragging=true;chartLastX=e.clientX;});
|
||
canvas.addEventListener('mousemove',function(e){if(!chartDragging)return;chartAngle+=(e.clientX-chartLastX)*0.005;chartLastX=e.clientX;render();});
|
||
canvas.addEventListener('mouseup',function(){chartDragging=false;});canvas.addEventListener('mouseleave',function(){chartDragging=false;});
|
||
canvas.addEventListener('touchstart',function(e){if(e.touches.length===1){chartDragging=true;chartLastX=e.touches[0].clientX;}if(e.touches.length===2){chartPinchDist=Math.hypot(e.touches[0].clientX-e.touches[1].clientX,e.touches[0].clientY-e.touches[1].clientY);}},{passive:false});
|
||
canvas.addEventListener('touchmove',function(e){if(e.touches.length===1&&chartDragging){chartAngle+=(e.touches[0].clientX-chartLastX)*0.005;chartLastX=e.touches[0].clientX;render();}if(e.touches.length===2){e.preventDefault();var d=Math.hypot(e.touches[0].clientX-e.touches[1].clientX,e.touches[0].clientY-e.touches[1].clientY);chartZoom=Math.max(0.5,Math.min(2,chartZoom*(d/chartPinchDist)));chartPinchDist=d;render();}},{passive:false});
|
||
canvas.addEventListener('touchend',function(){chartDragging=false;});
|
||
if(!canvas._anim){canvas._anim=true;function anim(){render();requestAnimationFrame(anim);}anim();}
|
||
}
|
||
|
||
function toggleChartMode(){
|
||
if(!S.birth){showToast('请先完成星盘测试');return;}
|
||
CHART_MODE=CHART_MODE==='birth'?'live':'birth';
|
||
CHART_DONE=false; // allow replay
|
||
updateChartToggle();
|
||
startChartIntro();
|
||
drawChart();
|
||
}
|
||
function updateChartToggle(){
|
||
var el=document.getElementById('chartToggle');
|
||
if(!el)return;
|
||
if(!S.birth){el.textContent='◎ 实时天象';return;}
|
||
if(CHART_MODE==='birth'){
|
||
var d=S.birth;el.textContent='📅 '+d.year+'.'+d.month+'.'+d.day+' 本命盘';
|
||
}else{el.textContent='◎ 实时天象';}
|
||
}
|
||
|
||
function startChartIntro(){
|
||
if(CHART_DONE)return; // play once only
|
||
if(CHART_TIMER){clearInterval(CHART_TIMER);CHART_TIMER=null;}
|
||
CHART_INTRO=-1;CHART_PAIRS=[];CHART_REVEALED=[];CHART_FROZEN_NOW=0;
|
||
// Wait for first render to fill CHART_PAIRS, then start
|
||
setTimeout(function(){
|
||
if(CHART_PAIRS.length===0)return;
|
||
CHART_INTRO=0;CHART_CUR_START=Date.now();
|
||
updateIntroText(0);
|
||
CHART_TIMER=setInterval(function(){
|
||
// Current line done, move to revealed
|
||
CHART_REVEALED.push(CHART_INTRO);
|
||
CHART_INTRO++;
|
||
if(CHART_INTRO>=CHART_PAIRS.length){
|
||
CHART_INTRO=-1;clearInterval(CHART_TIMER);CHART_TIMER=null;CHART_DONE=true;
|
||
updateIntroDone();return;
|
||
}
|
||
CHART_CUR_START=Date.now();
|
||
updateIntroText(CHART_INTRO);
|
||
},CHART_LINE_DUR);
|
||
},200);
|
||
}
|
||
|
||
function updateIntroText(idx){
|
||
var pr=CHART_PAIRS[idx];
|
||
var na=PLANETS[pr.a].name,nb=PLANETS[pr.b].name;
|
||
var key=pr.a<pr.b?pr.a+'-'+pr.b:pr.b+'-'+pr.a;
|
||
var meanings={
|
||
'0-1':'意识与潜意识的对话,内外自我的和谐',
|
||
'0-2':'思维模式的自我表达,语言与创造力',
|
||
'0-3':'魅力与价值感,如何被世界所爱',
|
||
'0-4':'意志力转化为行动,勇气与进取',
|
||
'0-5':'自信与机遇,生命中的贵人方向',
|
||
'0-6':'责任塑造人格,成熟与自律之路',
|
||
'1-2':'感性与理性的平衡,直觉与逻辑',
|
||
'1-3':'情感需求与爱的表达方式',
|
||
'1-4':'情绪驱动行为,内在感受的出口',
|
||
'1-5':'情感丰盈与内心安全感',
|
||
'1-6':'情绪克制与内在成熟度',
|
||
'2-3':'沟通中的温度,语言的艺术魅力',
|
||
'2-4':'思维果敢,言之有物的力量',
|
||
'2-5':'智慧的高度,宏观视野与哲学思考',
|
||
'2-6':'严谨的逻辑,深入本质的洞察力',
|
||
'3-4':'爱与欲望的张力,吸引力法则',
|
||
'3-5':'幸运眷顾,美好事物的吸引力',
|
||
'3-6':'感情中的承诺与长久关系',
|
||
'4-5':'行动带来扩张,勇气与成长',
|
||
'4-6':'克制中的力量,持久与耐力',
|
||
'5-6':'理想与现实的平衡,成长与沉淀'
|
||
};
|
||
var meaning=meanings[key]||(na+'与'+nb+'的相位互动');
|
||
document.getElementById('chartHint').textContent='✦ '+na+' ↔ '+nb;
|
||
document.getElementById('chartInfo').innerHTML='<span style="color:var(--pri);font-weight:600">第'+(idx+1)+'/'+CHART_PAIRS.length+'条</span> <span style="font-size:11px;color:var(--sub)">'+meaning+'</span>';
|
||
}
|
||
|
||
function updateIntroDone(){
|
||
document.getElementById('chartHint').textContent='全部 '+CHART_PAIRS.length+' 条相位连线已完成';
|
||
document.getElementById('chartInfo').innerHTML='<span style="cursor:pointer;color:var(--pri);font-weight:600" onclick="toggleChartMode()" id="chartToggle"></span><span style="margin-left:8px;font-size:11px;color:var(--sub)">拖拽旋转 · 双指缩放 · 点击行星</span>';
|
||
updateChartToggle();
|
||
}
|
||
|
||
// ═══════ VIDEO ═══════
|
||
var videoTimer=null;
|
||
function playVideoReport(){
|
||
if(!S.sign){showToast('请先完成测试');return;}
|
||
var overlay=document.getElementById('videoOverlay');overlay.classList.add('on');
|
||
var canvas=document.getElementById('videoCanvas'),ctx=canvas.getContext('2d'),dpr=window.devicePixelRatio||1;
|
||
var w=Math.min(430,window.innerWidth),h=window.innerHeight;
|
||
canvas.width=w*dpr;canvas.height=h*dpr;canvas.style.width=w+'px';canvas.style.height=h+'px';ctx.scale(dpr,dpr);
|
||
var wm=document.getElementById('vWatermark');wm.style.display=S.isMember?'none':'block';
|
||
var sign=S.sign,fps=30,totalFrames=30*fps,frame=0;
|
||
var signImg=new Image();signImg.src=ZODIAC_ICON[sign.name];
|
||
|
||
var scenes=[
|
||
{start:0,end:3,texts:[{t:0,text:'星镜',x:w/2,y:h*0.15,fs:40,fc:'#fff'}]},
|
||
{start:3,end:8,imgs:[{t:0,img:signImg,x:w/2,y:h*0.28,s:120}],texts:[{t:0,text:sign.name,x:w/2,y:h*0.43,fs:26,fc:'#fff'},{t:1.5,text:sign.trait,x:w/2,y:h*0.50,fs:13,fc:'rgba(255,255,255,0.7)'}]},
|
||
{start:8,end:20,texts:[{t:0,text:sign.el+'象星座',x:w/2,y:h*0.22,fs:20,fc:sign.color},{t:2,text:'天赋特质',x:w/2,y:h*0.35,fs:15,fc:'rgba(255,255,255,0.5)'},{t:3,text:sign.trait.split('·')[0],x:w/2,y:h*0.44,fs:18,fc:'#fff'},{t:5.5,text:sign.trait.split('·')[1],x:w/2,y:h*0.52,fs:16,fc:'#fff'},{t:8,text:sign.trait.split('·')[2],x:w/2,y:h*0.60,fs:16,fc:'#fff'},{t:10.5,text:'开启视频解读 · 了解更多',x:w/2,y:h*0.72,fs:12,fc:'rgba(255,255,255,0.4)'}]},
|
||
{start:20,end:26,texts:[{t:0,text:'开通星镜会员',x:w/2,y:h*0.35,fs:18,fc:'#fff'},{t:1.5,text:'解锁无水印完整视频报告',x:w/2,y:h*0.44,fs:13,fc:'rgba(255,255,255,0.8)'},{t:3,text:'首月仅 ¥9.9',x:w/2,y:h*0.56,fs:20,fc:'#FFD700'}]},
|
||
{start:26,end:30,imgs:[{t:0,img:signImg,x:w/2,y:h*0.32,s:64}],texts:[{t:0,text:'星镜',x:w/2,y:h*0.48,fs:20,fc:'#fff'},{t:1.5,text:'让每一次自我探索,都成为可播放的电影',x:w/2,y:h*0.56,fs:11,fc:'rgba(255,255,255,0.5)'}]}
|
||
];
|
||
|
||
var stars=[];for(var i=0;i<80;i++)stars.push({x:Math.random()*w,y:Math.random()*h,r:Math.random()*1.5+0.5,a:Math.random(),sp:Math.random()*0.02+0.005});
|
||
|
||
function drawFrame(){
|
||
ctx.fillStyle='#0a0a1a';ctx.fillRect(0,0,w,h);var t=frame/fps;
|
||
stars.forEach(function(s){s.a+=s.sp;ctx.fillStyle='rgba(255,255,255,'+(0.3+Math.sin(s.a)*0.4)+')';ctx.beginPath();ctx.arc(s.x,s.y,s.r,0,Math.PI*2);ctx.fill();});
|
||
for(var si=0;si<scenes.length;si++){var sc=scenes[si];if(t>=sc.start&&t<=sc.end){var st=t-sc.start;
|
||
// Draw images
|
||
if(sc.imgs)sc.imgs.forEach(function(ix){if(st>=ix.t&&ix.img.complete&&ix.img.naturalWidth>0){var alpha=Math.min(1,(st-ix.t)/0.5);ctx.globalAlpha=alpha;ctx.drawImage(ix.img,ix.x-ix.s/2,ix.y-ix.s/2,ix.s,ix.s);ctx.globalAlpha=1;}});
|
||
// Draw texts
|
||
if(sc.texts)sc.texts.forEach(function(tx){if(st>=tx.t){var alpha=Math.min(1,(st-tx.t)/0.5);ctx.fillStyle=tx.fc.replace(/rgba\\((\\d+),(\\d+),(\\d+),([\\d.]+)\\)/,function(_,r,g,b,a2){return'rgba('+r+','+g+','+b+','+(alpha*parseFloat(a2)).toFixed(2)+')';});ctx.font='bold '+tx.fs+'px -apple-system,sans-serif';ctx.textAlign='center';ctx.fillText(tx.text,tx.x,tx.y);}});
|
||
}}
|
||
frame++;document.getElementById('vBar').style.width=(frame/totalFrames*100)+'%';
|
||
if(frame>=totalFrames){clearInterval(videoTimer);videoTimer=null;return;}
|
||
}
|
||
if(videoTimer)clearInterval(videoTimer);
|
||
frame=0;document.getElementById('vBar').style.width='0%';drawFrame();
|
||
videoTimer=setInterval(drawFrame,1000/fps);
|
||
}
|
||
|
||
function stopVideo(){if(videoTimer){clearInterval(videoTimer);videoTimer=null;}document.getElementById('videoOverlay').classList.remove('on');}
|
||
|
||
// ═══════ FEED ═══════
|
||
function renderFeedTabs(){var h='';FEED_CAT.forEach(function(c,i){h+='<span class="feed-tab'+(i===S.feedCat?' active':'')+'" onclick="switchFeedCat('+i+')">'+c+'</span>';});document.getElementById('feedTabs').innerHTML=h;}
|
||
function switchFeedCat(i){S.feedCat=i;renderFeedTabs();renderFeed();}
|
||
function renderFeed(){var list=FEED.filter(function(f){return S.feedCat===0||f.c===S.feedCat||f.c===0});var h='';list.forEach(function(f){h+='<div class="feed-item" onclick="showToast(\'视频播放中...\')"><div class="f-thumb" style="background:linear-gradient(135deg,'+f.bg1+','+f.bg2+')"><div class="play-btn">▶</div><div class="f-dur">'+f.d+'</div><div class="f-avatar">'+f.icon+'</div></div><div class="f-info"><div class="f-title">'+f.t+'</div><div class="f-meta"><span>'+f.a+'</span><span>'+f.v+' 次观看</span></div></div><div class="f-tags">';f.tags.forEach(function(t){h+='<span class="feed-tag">#'+t+'</span>';});h+='</div></div>';});document.getElementById('feedList').innerHTML=h;}
|
||
|
||
// ═══════ HISTORY ═══════
|
||
function renderHistory(){
|
||
var list=document.getElementById('historyList');
|
||
if(S.history.length===0){list.innerHTML='<div class="card" style="text-align:center"><div style="font-size:36px;margin-bottom:6px">🎬</div><div class="card-title">还没有测试记录</div><div class="card-sub">完成星盘测试后,你的专属报告将保存在这里</div><button class="btn btn-pri btn-sm" style="margin-top:10px" onclick="goTest()">开始测试 →</button></div>';return;}
|
||
var h='';for(var i=S.history.length-1;i>=0;i--){var r=S.history[i];h+='<div class="hist-item" onclick="replayHistory('+i+')"><div class="hi">'+r.signBadge+'</div><div class="hc"><div class="hn">'+r.signName+' · '+r.mbti+'</div><div class="hd">'+r.date+' · '+r.style+' · '+r.el+'象星座</div></div><div style="font-size:11px;color:var(--pri)">▶</div></div>';}list.innerHTML=h;}
|
||
function replayHistory(idx){var r=S.history[idx];S.sign=ZODIAC.find(function(z){return z.name===r.signName});S.birth=r.birth;playVideoReport();}
|
||
|
||
// ═══════ PROFILE ═══════
|
||
function renderProfile(){
|
||
if(S.history.length>0){var last=S.history[S.history.length-1];document.getElementById('pAvatar').innerHTML=last.signBadge;document.getElementById('pSign').textContent=last.signName+' · '+last.mbti;document.getElementById('pDetail').textContent=last.style+' · '+last.el+'象星座 · 已完成'+S.history.length+'次测试';}
|
||
var badges=[{name:'初识星盘',icon:'🔭',unlock:S.history.length>=1},{name:'探索者',icon:'🌟',unlock:S.history.length>=2},{name:'星象达人',icon:'🌙',unlock:S.history.length>=3},{name:'深度玩家',icon:'✨',unlock:S.history.length>=5},{name:'会员专属',icon:'👑',unlock:S.isMember}];
|
||
var h='';badges.forEach(function(b){h+='<div class="badge-item"><div class="bi'+(b.unlock?'':' locked')+'" style="background:'+(b.unlock?'#FFF5F0':'#f0f0f0')+'">'+b.icon+'</div>'+b.name+'</div>';});document.getElementById('badgeRow').innerHTML=h;
|
||
}
|
||
|
||
// ═══════ PURCHASE ═══════
|
||
function openPurchase(){document.getElementById('purchaseModal').classList.add('on');}
|
||
function closePurchase(){document.getElementById('purchaseModal').classList.remove('on');}
|
||
function doPurchase(){S.isMember=true;localStorage.setItem('xj_member','1');showToast('购买成功!欢迎加入星镜会员 🎉');closePurchase();renderProfile();}
|
||
|
||
// ═══════ UTILS ═══════
|
||
function showToast(msg){var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');setTimeout(function(){t.classList.remove('show')},2000);}
|
||
window.addEventListener('resize',function(){if(S.tab==='chart')drawChart();});
|
||
document.getElementById('purchaseModal').addEventListener('click',function(e){if(e.target===this)closePurchase();});
|
||
|
||
// ═══════ SYNASTRY ═══════
|
||
var synMode='romance';
|
||
function setSynMode(m){
|
||
synMode=m;
|
||
document.querySelectorAll('.syn-tab').forEach(function(t){t.classList.remove('active');});
|
||
document.getElementById('synTab'+{romance:'Romance',friendship:'Friend',family:'Family'}[m]).classList.add('active');
|
||
var cfg={romance:{icon:'❤️',title:'两性合盘',sub:'分析两人的情感模式、吸引力与亲密关系契合度',l1:'👤 你',l2:'💕 伴侣',btn:'❤️ 开始两性合盘'},
|
||
friendship:{icon:'🤝',title:'缘分配对',sub:'输入两人的出生信息,解锁星座契合度分析',l1:'👤 你',l2:'👤 TA',btn:'💫 开始合盘分析'},
|
||
family:{icon:'🏠',title:'家庭合盘',sub:'分析亲子、手足或家庭成员的星座互动与相处模式',l1:'👤 我',l2:'👨👩👧 家人',btn:'🏠 开始家庭合盘'}}[m];
|
||
document.getElementById('synIcon').textContent=cfg.icon;
|
||
document.getElementById('synTitle').textContent='双人合盘 · '+cfg.title;
|
||
document.getElementById('synSub').textContent=cfg.sub;
|
||
document.getElementById('synLabel1').textContent=cfg.l1;
|
||
document.getElementById('synLabel2').textContent=cfg.l2;
|
||
document.getElementById('synBtn').textContent=cfg.btn;
|
||
// Show family relationship selector only in family mode
|
||
var relSel=document.getElementById('synFamilyRel');if(relSel)relSel.style.display=m==='family'?'inline-block':'none';
|
||
document.getElementById('synastryResult').innerHTML='';
|
||
}
|
||
|
||
var synChartType='compare';
|
||
function setSynChart(t){
|
||
synChartType=t;
|
||
document.querySelectorAll('#synChartTabs .syn-tab').forEach(function(b){b.classList.remove('active');});
|
||
var idx={compare:0,composite:1,marksAB:2,marksBA:3}[t];
|
||
document.querySelectorAll('#synChartTabs .syn-tab')[idx].classList.add('active');
|
||
}
|
||
|
||
// ═══ Synastry wheel drawing engine ═══
|
||
function drawSynastryWheel(cvid,birth1,birth2){
|
||
var cv=document.getElementById(cvid);if(!cv)return;
|
||
var ctx=cv.getContext('2d'),dpr=window.devicePixelRatio||1;
|
||
var w=340,h=340;cv.width=w*dpr;cv.height=h*dpr;cv.style.width='100%';cv.style.maxWidth=w+'px';cv.style.height='auto';ctx.scale(dpr,dpr);
|
||
var cx=w/2,cy=h/2;
|
||
var ang1=birth1?getPlanetAngles(birth1):null;
|
||
var ang2=birth2?getPlanetAngles(birth2):null;
|
||
if(!ang1||!ang2)return;
|
||
|
||
var zSigns=['♑','♒','♓','♈','♉','♊','♋','♌','♍','♎','♏','♐'];
|
||
var zNames=['摩羯','水瓶','双鱼','白羊','金牛','双子','巨蟹','狮子','处女','天秤','天蝎','射手'];
|
||
var pColors=['#FFD700','#C0C0C0','#B8860B','#FF69B4','#E54D42','#F5A623','#8B8B83'];
|
||
var pNames=['日','月','水','金','火','木','土'];
|
||
|
||
// Aspect detection helper
|
||
function getAspect(deg){
|
||
deg=((deg%360)+360)%360;
|
||
if(deg<=8||deg>=352)return{t:'合',c:'#FFD700',w:2.5,o:0};
|
||
if(deg>=172&°<=188)return{t:'冲',c:'#E54D42',w:2,o:180};
|
||
if(deg>=114&°<=126)return{t:'拱',c:'#4A90E2',w:1.8,o:120};
|
||
if(deg>=84&°<=96)return{t:'刑',c:'#FF6347',w:1.5,o:90};
|
||
if(deg>=54&°<=66)return{t:'六合',c:'#5CB85C',w:1.5,o:60};
|
||
return null;
|
||
}
|
||
|
||
// Compute composite midpoints
|
||
var compAng=[];
|
||
for(var i=0;i<7;i++){
|
||
var diff=ang2[i]-ang1[i];
|
||
if(diff>Math.PI)diff-=Math.PI*2;if(diff<-Math.PI)diff+=Math.PI*2;
|
||
compAng.push((ang1[i]+diff/2+Math.PI*2)%(Math.PI*2));
|
||
}
|
||
|
||
function render(){
|
||
ctx.clearRect(0,0,w,h);
|
||
ctx.fillStyle='#0a0a1a';ctx.fillRect(0,0,w,h);
|
||
|
||
if(synChartType==='compare'){
|
||
// === COMPARISON CHART: dual rings ===
|
||
var ir=80,or=125,zr=155;
|
||
// Zodiac ring
|
||
for(var i=0;i<12;i++){var a=i/12*Math.PI*2-Math.PI/2;ctx.strokeStyle='rgba(255,255,255,.08)';ctx.lineWidth=.5;ctx.beginPath();ctx.arc(cx,cy,zr-12,a,a+Math.PI/6);ctx.stroke();}
|
||
// Sector lines
|
||
for(var i=0;i<12;i++){var a=i/12*Math.PI*2-Math.PI/2;ctx.strokeStyle='rgba(255,255,255,.06)';ctx.beginPath();ctx.moveTo(cx+Math.cos(a)*(zr-12),cy+Math.sin(a)*(zr-12));ctx.lineTo(cx+Math.cos(a)*zr,cy+Math.sin(a)*zr);ctx.stroke();}
|
||
// Zodiac labels
|
||
for(var i=0;i<12;i++){var a=(i+.5)/12*Math.PI*2-Math.PI/2;ctx.fillStyle='rgba(255,255,255,.35)';ctx.font='9px sans-serif';ctx.textAlign='center';ctx.fillText(zSigns[i],cx+Math.cos(a)*(zr-6),cy+Math.sin(a)*(zr-6)+3);}
|
||
// Rings
|
||
ctx.strokeStyle='rgba(255,255,255,.1)';ctx.lineWidth=1;ctx.beginPath();ctx.arc(cx,cy,ir,0,Math.PI*2);ctx.stroke();ctx.beginPath();ctx.arc(cx,cy,or,0,Math.PI*2);ctx.stroke();
|
||
// Inner ring = Person A's planets
|
||
var pos1=[],pos2=[];
|
||
for(var i=0;i<7;i++){var a=ang1[i];var px=cx+Math.cos(a)*ir,py=cy+Math.sin(a)*ir;pos1.push({x:px,y:py,a:a});ctx.fillStyle=pColors[i];ctx.beginPath();ctx.arc(px,py,5,0,Math.PI*2);ctx.fill();ctx.fillStyle='#fff';ctx.font='bold 7px sans-serif';ctx.textAlign='center';ctx.fillText(pNames[i],px,py+2);}
|
||
// Outer ring = Person B's planets
|
||
for(var i=0;i<7;i++){var a=ang2[i];var px=cx+Math.cos(a)*or,py=cy+Math.sin(a)*or;pos2.push({x:px,y:py,a:a});ctx.fillStyle=pColors[i];ctx.beginPath();ctx.arc(px,py,5,0,Math.PI*2);ctx.fill();ctx.strokeStyle='rgba(255,255,255,.5)';ctx.lineWidth=1;ctx.stroke();ctx.fillStyle='#fff';ctx.font='bold 7px sans-serif';ctx.textAlign='center';ctx.fillText(pNames[i],px,py+2);}
|
||
// Aspect lines between rings
|
||
for(var i=0;i<7;i++){for(var j=0;j<7;j++){
|
||
var da=((ang2[j]-ang1[i])%(Math.PI*2)+Math.PI*2)%(Math.PI*2);
|
||
var asp=getAspect(da/Math.PI*180);
|
||
if(asp){
|
||
ctx.strokeStyle=asp.c;ctx.lineWidth=asp.w;ctx.globalAlpha=.45;
|
||
ctx.beginPath();ctx.moveTo(pos1[i].x,pos1[i].y);ctx.lineTo(pos2[j].x,pos2[j].y);ctx.stroke();
|
||
ctx.globalAlpha=1;
|
||
}
|
||
}}
|
||
// Legend
|
||
ctx.fillStyle='rgba(255,255,255,.6)';ctx.font='9px sans-serif';ctx.fillText('内圈:你 · 外圈:TA',cx,cy+or+16);
|
||
}else{
|
||
// === SINGLE-RING CHARTS: composite / marks ===
|
||
var sr=125,zr=sr+28;
|
||
var angles;var title='';
|
||
if(synChartType==='composite'){angles=compAng;title='组合中点盘';}
|
||
else if(synChartType==='marksAB'){angles=ang2.map(function(a,i){return(a+ang1[i]*.38)%(Math.PI*2);});title='马盘 A→B(A眼中的B)';}
|
||
else{angles=ang1.map(function(a,i){return(a+ang2[i]*.38)%(Math.PI*2);});title='马盘 B→A(B眼中的A)';}
|
||
// Zodiac sectors
|
||
for(var i=0;i<12;i++){var a=i/12*Math.PI*2-Math.PI/2;ctx.strokeStyle='rgba(255,255,255,.08)';ctx.lineWidth=.5;ctx.beginPath();ctx.arc(cx,cy,sr+10,a,a+Math.PI/6);ctx.stroke();}
|
||
for(var i=0;i<12;i++){var a=i/12*Math.PI*2-Math.PI/2;ctx.strokeStyle='rgba(255,255,255,.06)';ctx.beginPath();ctx.moveTo(cx+Math.cos(a)*(sr+10),cy+Math.sin(a)*(sr+10));ctx.lineTo(cx+Math.cos(a)*zr,cy+Math.sin(a)*zr);ctx.stroke();}
|
||
for(var i=0;i<12;i++){var a=(i+.5)/12*Math.PI*2-Math.PI/2;ctx.fillStyle='rgba(255,255,255,.35)';ctx.font='9px sans-serif';ctx.textAlign='center';ctx.fillText(zSigns[i],cx+Math.cos(a)*(zr-6),cy+Math.sin(a)*(zr-6)+3);}
|
||
// Planet ring
|
||
ctx.strokeStyle='rgba(255,255,255,.15)';ctx.lineWidth=1.5;ctx.beginPath();ctx.arc(cx,cy,sr,0,Math.PI*2);ctx.stroke();
|
||
// Planets
|
||
var poses=[];
|
||
for(var i=0;i<7;i++){var a=angles[i];var px=cx+Math.cos(a)*sr,py=cy+Math.sin(a)*sr;poses.push({x:px,y:py,a:a});ctx.fillStyle=pColors[i];ctx.beginPath();ctx.arc(px,py,6,0,Math.PI*2);ctx.fill();ctx.strokeStyle='rgba(255,255,255,.3)';ctx.lineWidth=1;ctx.stroke();ctx.fillStyle='#fff';ctx.font='bold 7px sans-serif';ctx.textAlign='center';ctx.fillText(pNames[i],px,py+2);}
|
||
// Inner aspects
|
||
for(var i=0;i<7;i++){for(var j=i+1;j<7;j++){
|
||
var da=((angles[j]-angles[i])%(Math.PI*2)+Math.PI*2)%(Math.PI*2);
|
||
var asp=getAspect(da/Math.PI*180);
|
||
if(asp){
|
||
ctx.strokeStyle=asp.c;ctx.lineWidth=asp.w;ctx.globalAlpha=.5;
|
||
ctx.beginPath();ctx.moveTo(poses[i].x,poses[i].y);ctx.lineTo(poses[j].x,poses[j].y);ctx.stroke();
|
||
ctx.globalAlpha=1;
|
||
}
|
||
}}
|
||
ctx.fillStyle='rgba(255,255,255,.5)';ctx.font='10px sans-serif';ctx.textAlign='center';ctx.fillText(title,cx,cy+zr+6);
|
||
}
|
||
}
|
||
render();
|
||
}
|
||
|
||
function openSynastry(){
|
||
showPage('synastry','星镜 · 合盘',true,false);
|
||
setupSynastryInputs();
|
||
setSynMode(synMode);
|
||
}
|
||
function setupSynastryInputs(){
|
||
['s1','s2'].forEach(function(p){
|
||
var ms=document.getElementById(p+'Month');if(!ms||ms.options.length>1)return;
|
||
for(var i=1;i<=12;i++){var o=document.createElement('option');o.value=i;o.text=i+'月';ms.appendChild(o);}
|
||
var ds=document.getElementById(p+'Day');for(var i=1;i<=31;i++){var o=document.createElement('option');o.value=i;o.text=i+'日';ds.appendChild(o);}
|
||
});
|
||
}
|
||
function runSynastry(){
|
||
var y1=parseInt(document.getElementById('s1Year').value),m1=parseInt(document.getElementById('s1Month').value),d1=parseInt(document.getElementById('s1Day').value);
|
||
var y2=parseInt(document.getElementById('s2Year').value),m2=parseInt(document.getElementById('s2Month').value),d2=parseInt(document.getElementById('s2Day').value);
|
||
if(!y1||!m1||!d1||!y2||!m2||!d2){showToast('请填写两人的完整出生日期');return;}
|
||
var familyRel='家人';var relSel=document.getElementById('synFamilyRel');if(relSel&&relSel.style.display!=='none')familyRel=relSel.value;
|
||
var z1=getZodiac(m1,d1),z2=getZodiac(m2,d2);
|
||
// Element & sign compat
|
||
var elCompat={火火:75,土土:80,风风:78,水水:82,火土:45,土火:45,火风:88,风火:88,火水:35,水火:35,土风:55,风土:55,土水:72,水土:72,风水:60,水风:60};
|
||
var elScore=elCompat[z1.el+z2.el]||50;
|
||
var zCompat={摩羯:['金牛',55],水瓶:['双子',60],双鱼:['巨蟹',65],白羊:['狮子',70],金牛:['处女',68],双子:['天秤',72],巨蟹:['天蝎',75],狮子:['射手',70],处女:['摩羯',65],天秤:['水瓶',68],天蝎:['双鱼',78],射手:['白羊',72]};
|
||
var zScore=50;var zm=zCompat[z1.name];if(zm&&zm[0]===z2.name)zScore=zm[1];
|
||
var zm2=zCompat[z2.name];if(zm2&&zm2[0]===z1.name)zScore=Math.max(zScore,zm2[1]);
|
||
|
||
// === Planet aspect analysis (测测-style) ===
|
||
var pairs=[
|
||
{a:'太阳',b:'太阳',icon:'☀☀',cat:'吸引力',d:'核心自我的共鸣'},
|
||
{a:'太阳',b:'月亮',icon:'☀☽',cat:'情感深度',d:'意识与潜意识的互动'},
|
||
{a:'金星',b:'火星',icon:'♀♂',cat:'激情火花',d:'爱与欲望的磁场'},
|
||
{a:'水星',b:'水星',icon:'☿☿',cat:'沟通',d:'思维频率的匹配'},
|
||
{a:'月亮',b:'月亮',icon:'☽☽',cat:'心灵默契',d:'情绪安全感的共振'},
|
||
{a:'金星',b:'金星',icon:'♀♀',cat:'吸引力',d:'爱情语言的契合'},
|
||
{a:'火星',b:'火星',icon:'♂♂',cat:'激情火花',d:'行动力与欲望碰撞'},
|
||
{a:'月亮',b:'金星',icon:'☽♀',cat:'情感深度',d:'情绪滋养与爱的表达'},
|
||
{a:'太阳',b:'水星',icon:'☀☿',cat:'沟通',d:'自我表达与言语理解'},
|
||
{a:'木星',b:'土星',icon:'♃♄',cat:'关系持久',d:'理想与现实的平衡'}
|
||
];
|
||
var planetAspects=[],dims={吸引力:0,沟通:0,情感深度:0,关系持久:0,激情火花:0,心灵默契:0},dc={吸引力:0,沟通:0,情感深度:0,关系持久:0,激情火花:0,心灵默契:0};
|
||
pairs.forEach(function(p){
|
||
var s=elCompat[z1.el+z2.el]||50;
|
||
if(p.a==='金星'&&p.b==='火星')s=z1.el+z2.el==='火风'||z1.el+z2.el==='风火'?88:z1.el+z2.el==='水火'||z1.el+z2.el==='火水'?40:z1.el+z2.el==='土水'||z1.el+z2.el==='水土'?70:s;
|
||
if(p.a==='太阳'&&p.b==='月亮')s=z1.name===z2.name?85:z1.el+z2.el==='火风'?82:z1.el+z2.el==='水土'?75:s;
|
||
if(p.a==='水星'&&p.b==='水星')s=z1.el+z2.el==='风风'?90:z1.el+z2.el==='火风'?78:z1.el+z2.el==='土水'?65:s;
|
||
if(p.a==='月亮'&&p.b==='月亮')s=z1.el+z2.el==='水水'?88:z1.el+z2.el==='土土'?82:z1.el+z2.el==='火火'?55:s;
|
||
if(p.a==='金星'&&p.b==='金星')s=z1.el+z2.el==='土土'?82:z1.el+z2.el==='风风'?78:z1.el+z2.el==='水水'?75:s;
|
||
if(p.a==='火星'&&p.b==='火星')s=z1.el+z2.el==='火火'?85:z1.el+z2.el==='风风'?62:z1.el+z2.el==='土土'?55:s;
|
||
if(p.a==='月亮'&&p.b==='金星')s=z1.el+z2.el==='水土'?80:z1.el+z2.el==='水水'?78:z1.el+z2.el==='火风'?72:s;
|
||
if(p.a==='太阳'&&p.b==='水星')s=z1.el+z2.el==='风风'?85:z1.el+z2.el==='火风'?76:z1.el+z2.el==='水土'?68:s;
|
||
if(p.a==='木星'&&p.b==='土星')s=z1.el+z2.el==='土土'?85:z1.el+z2.el==='风风'?70:z1.el+z2.el==='火火'?50:s;
|
||
s=Math.max(25,Math.min(95,s+Math.round((Math.random()-0.5)*10)));
|
||
var stars=s>=85?'★★★★★':s>=70?'★★★★☆':s>=55?'★★★☆☆':s>=35?'★★☆☆☆':'★☆☆☆☆';
|
||
var it='';var zn1=z1.name,zn2=z2.name;
|
||
if(p.a==='太阳'&&p.b==='太阳')it=s>=75?zn1+'与'+zn2+'的核心人格高度共振,彼此理解对方的本质需求。':s>=50?'两人有各自独立的人格魅力,需要花时间理解彼此的处事方式。':'两个独立的灵魂,互相尊重比互相改变更重要。';
|
||
else if(p.a==='太阳'&&p.b==='月亮')it=s>=75?zn1+'的自我表达能温柔包裹'+zn2+'的情绪世界,给予充分的安全感。':s>=50?'理性与感性需要磨合,但正是这种差异让你们更完整。':'自我与情绪的冲突可能让彼此疲惫,学会换位是关键。';
|
||
else if(p.a==='金星'&&p.b==='火星')it=s>=75?'吸引力爆棚!你们的磁场天然共振,初次见面就有强烈的好感。':s>=50?'有不错的情愫流动,多创造独处机会让火花升温。':'感情的节奏不太同步,需要更多耐心等待对方跟上。';
|
||
else if(p.a==='水星'&&p.b==='水星')it=s>=75?'沟通丝滑顺畅,能聊到天亮也不累。你们的脑回路在同一条线上。':s>=50?'大部分话题能聊得来,偶尔的思维碰撞反而是调味剂。':'沟通风格差异明显,多确认双方的真正意图减少误会。';
|
||
else if(p.a==='月亮'&&p.b==='月亮')it=s>=75?'情绪共鸣极深,不用说出口就能感知对方的心情变化。':s>=50?'情绪节奏基本同步,偶尔不同频也能快速调整。':'情绪表达方式不同,需要更明确地告诉对方你的感受。';
|
||
else if(p.a==='金星'&&p.b==='金星')it=s>=75?'爱情观高度一致,你们享受浪漫的方式是如此相似。':s>=50?'对爱的理解有交集也有差异,互补让关系更丰富。':'表达爱的方式不太一样,别用自己的标准衡量对方的付出。';
|
||
else if(p.a==='火星'&&p.b==='火星')it=s>=75?'行动力超强的一对,一起做事效率翻倍,激情四射。':s>=50?'做事的节奏不同但可以互补,一快一慢相得益彰。':'都很有主见,处理冲突时学会退一步海阔天空。';
|
||
else if(p.a==='月亮'&&p.b==='金星')it=s>=75?'情感的滋养与爱的表达完美对接,在一起就是治愈。':s>=50?'情感上可以互相支持,多表达欣赏让对方感受到被爱。':'情感需求与爱的表达方式有落差,坦诚沟通胜过猜测。';
|
||
else if(p.a==='太阳'&&p.b==='水星')it=s>=75?zn1+'的表达能被'+zn2+'精准理解,交流毫无障碍。':s>=50?'多数情况下能顺畅交流,偶尔的误解无伤大雅。':'思维频道不完全一致,说清楚比让对方猜更重要。';
|
||
else if(p.a==='木星'&&p.b==='土星')it=s>=75?'理想与现实达到美妙平衡,一个负责想象一个负责落地。':s>=50?'乐观与务实需要磨合,但分工明确后会很稳定。':'自由与约束的张力较大,找到共同的目标是关键。';
|
||
planetAspects.push({icon:p.icon,label:p.a+' × '+p.b,cat:p.cat,score:s,stars:stars,desc:it});
|
||
if(dims[p.cat]!==undefined){dims[p.cat]+=s;dc[p.cat]++;}
|
||
});
|
||
Object.keys(dims).forEach(function(k){dims[k]=Math.round(dims[k]/dc[k]);});
|
||
var total=Math.round(dims.吸引力*0.22+dims.沟通*0.16+dims.情感深度*0.18+dims.关系持久*0.14+dims.激情火花*0.16+dims.心灵默契*0.14);
|
||
total=Math.min(98,Math.max(30,total));
|
||
|
||
// Mode config
|
||
var modeCfg={
|
||
romance:{title:'两性吸引力',icon:'❤️',heroBg:'linear-gradient(135deg,#3d0a2e,#2d1b69,#16213e)',
|
||
levels:[{max:48,l:'火花未燃',e:'🌱'},{max:65,l:'温柔吸引',e:'🌷'},{max:80,l:'热烈奔赴',e:'🔥'},{max:98,l:'灵魂伴侣',e:'💞'}],
|
||
keywords:['亲密','默契','吸引','成长','信任','守护'],
|
||
strength:z1.name+'与'+z2.name+'的相遇有一种天然的磁场。'+z1.el+'象与'+z2.el+'象的能量搭配'+(elScore>=75?'非常和谐':'富有张力')+',你们的组合在人群中总是特别的存在。',
|
||
watch:z1.el===z2.el?'同元素让你们容易理解彼此,但也可能陷入相同的盲点。尝试跳出舒适圈,给关系注入新鲜感。':'不同元素的碰撞是你们最大的财富,也可能是摩擦的来源。学会欣赏差异而非试图改变对方。',
|
||
advice:'保持每周一次深度对话,不聊日常琐事只谈心。'+z1.name+'可以多主动表达感受,'+z2.name+'需要给对方留出独处的空间。记住:最好的关系是两个完整的人并肩前行,而非两个半人拼凑。'},
|
||
friendship:{title:'缘分契合度',icon:'🤝',heroBg:'linear-gradient(135deg,#2d1b69,#16213e,#0f3460)',
|
||
levels:[{max:45,l:'有缘无分',e:'🌊'},{max:60,l:'淡淡默契',e:'🌸'},{max:75,l:'灵魂共鸣',e:'🔥'},{max:98,l:'天作之合',e:'💫'}],
|
||
keywords:['志趣','理解','成长','互补','共鸣','自由'],
|
||
strength:z1.name+'('+z1.trait.split('·')[0]+')与'+z2.name+'('+z2.trait.split('·')[0]+')的组合有一种天然的舒适感。在一起时可以自在地做自己,无需刻意迎合。',
|
||
watch:'两人的节奏偶尔会错位——一个想冲锋时另一个想休整。尊重各自的生命节拍,不必强求同步。尊重各自的边界是长久友谊的基础。',
|
||
advice:'一起培养一个共同爱好,让它成为你们友谊的锚点。'+z1.name+'可以多分享你的思考,'+z2.name+'可以带对方体验新鲜事物。友谊最好的样子是互相照亮而非彼此消耗。'},
|
||
family:{title:'家庭和谐度',icon:'🏠',heroBg:'linear-gradient(135deg,#1a3a2e,#16213e,#0f3460)',
|
||
levels:[{max:50,l:'需要磨合',e:'🏡'},{max:68,l:'和睦相处',e:'🌿'},{max:82,l:'互相扶持',e:'🌟'},{max:98,l:'家和万事兴',e:'🌈'}],
|
||
keywords:['包容','支持','理解','关怀','传承','温暖'],
|
||
strength:'你和'+familyRel+'('+z2.name+')之间有一种超越言语的亲情纽带。'+z1.el+'象与'+z2.el+'象的能量在家庭中'+(elScore>=70?'相辅相成':'需要更多磨合')+'。',
|
||
watch:z1.el===z2.el?'同元素的家人容易有相似的处事方式,但注意不要让固有模式限制彼此。多一点变通,少一点固执。':'不同元素的家人意味着多元的能量,理解对方的不同表达方式是和谐的关键。',
|
||
advice:'定期安排家庭聚会或视频通话,仪式感是家庭关系的润滑剂。'+z1.name+'可以多倾听,'+z2.name+'可以多表达。家人之间的爱不需要理由,但需要经营。'}
|
||
}[synMode];
|
||
var level=modeCfg.levels[0];for(var i=0;i<modeCfg.levels.length;i++){if(total<=modeCfg.levels[i].max){level=modeCfg.levels[i];break;}}
|
||
|
||
// === Build result HTML ===
|
||
var h='';
|
||
h+='<div class="result-hero" style="background:'+modeCfg.heroBg+'">';
|
||
h+='<div style="display:flex;align-items:center;justify-content:center;gap:12px;margin-bottom:8px">';
|
||
h+='<span>'+zodiacBadge(z1)+'</span><span style="font-size:20px;color:rgba(255,255,255,.5)">✕</span><span>'+zodiacBadge(z2)+'</span></div>';
|
||
h+='<div style="font-size:15px;opacity:.7;margin-bottom:2px">'+modeCfg.icon+' '+modeCfg.title+'</div>';
|
||
h+='<div style="font-size:48px;font-weight:900;color:#FFD700;margin:8px 0">'+total+'<span style="font-size:16px;opacity:.7">%</span></div>';
|
||
h+='<div style="font-size:17px;font-weight:700;margin-bottom:10px">'+level.l+' '+level.e+'</div>';
|
||
h+='<canvas id="synRadar" width="240" height="240" style="margin:4px auto;display:block;max-width:100%"></canvas>';
|
||
h+='</div>';
|
||
|
||
// Chart type tabs (result area)
|
||
h+='<div style="display:flex;gap:4px;margin-bottom:10px">';
|
||
h+='<button class="syn-tab'+(synChartType==='compare'?' active':'')+'" onclick="synChartType=\'compare\';drawSynastryWheel(\'synWheel\',{year:'+y1+',month:'+m1+',day:'+d1+'},{year:'+y2+',month:'+m2+',day:'+d2+'});refreshSynTabs()">◎ 比较盘</button>';
|
||
h+='<button class="syn-tab'+(synChartType==='composite'?' active':'')+'" onclick="synChartType=\'composite\';drawSynastryWheel(\'synWheel\',{year:'+y1+',month:'+m1+',day:'+d1+'},{year:'+y2+',month:'+m2+',day:'+d2+'});refreshSynTabs()">◉ 组合盘</button>';
|
||
h+='<button class="syn-tab'+(synChartType==='marksAB'?' active':'')+'" onclick="synChartType=\'marksAB\';drawSynastryWheel(\'synWheel\',{year:'+y1+',month:'+m1+',day:'+d1+'},{year:'+y2+',month:'+m2+',day:'+d2+'});refreshSynTabs()">👁 马盘 A→B</button>';
|
||
h+='<button class="syn-tab'+(synChartType==='marksBA'?' active':'')+'" onclick="synChartType=\'marksBA\';drawSynastryWheel(\'synWheel\',{year:'+y1+',month:'+m1+',day:'+d1+'},{year:'+y2+',month:'+m2+',day:'+d2+'});refreshSynTabs()">👁 马盘 B→A</button>';
|
||
h+='</div>';
|
||
|
||
// Synastry wheel canvas
|
||
h+='<canvas id="synWheel" width="340" height="340" style="display:block;max-width:100%;margin:0 auto 10px;border-radius:12px;background:#0a0a1a"></canvas>';
|
||
|
||
// Aspect detail table
|
||
h+='<div class="card card-sm"><div class="card-title">📐 相位详情表</div>';
|
||
// Compute aspects for the selected chart type
|
||
(function(){
|
||
var ang1=getPlanetAngles({year:y1,month:m1,day:d1});
|
||
var ang2=getPlanetAngles({year:y2,month:m2,day:d2});
|
||
var pNames=['日','月','水','金','火','木','土'];
|
||
var aspNames={合:'黄',冲:'红',拱:'蓝',刑:'橙',六合:'绿'};
|
||
var aspColors={合:'#FFD700',冲:'#E54D42',拱:'#4A90E2',刑:'#FF6347',六合:'#5CB85C'};
|
||
var aspects=[];
|
||
for(var i=0;i<7;i++){for(var j=0;j<7;j++){
|
||
var da=((ang2[j]-ang1[i])%(Math.PI*2)+Math.PI*2)%(Math.PI*2);
|
||
var deg=da/Math.PI*180;
|
||
var t=null;
|
||
deg=((deg%360)+360)%360;
|
||
if(deg<=8||deg>=352)t='合';else if(deg>=172&°<=188)t='冲';else if(deg>=114&°<=126)t='拱';else if(deg>=84&°<=96)t='刑';else if(deg>=54&°<=66)t='六合';
|
||
if(t)aspects.push({a:PLANETS[i].name,b:PLANETS[j].name,t:t,c:aspColors[t],deg:Math.round(deg),orb:Math.round(Math.abs(deg-(t==='合'?0:t==='冲'?180:t==='拱'?120:t==='刑'?90:60)))});
|
||
}}
|
||
// Sort: conjunctions first, then by orb
|
||
aspects.sort(function(x,y){var o={合:0,冲:1,拱:2,刑:3,六合:4};return(o[x.t]-o[y.t])||(x.orb-y.orb);});
|
||
aspects.slice(0,8).forEach(function(a){
|
||
h+='<div style="display:flex;align-items:center;gap:6px;padding:4px 0;border-bottom:1px solid #f5f5f5;font-size:11px">';
|
||
h+='<span style="font-weight:700;min-width:56px">'+a.a+' × '+a.b+'</span>';
|
||
h+='<span style="display:inline-block;width:20px;height:20px;line-height:20px;text-align:center;border-radius:50%;background:'+a.c+';color:#fff;font-size:9px;font-weight:700">'+a.t+'</span>';
|
||
h+='<span style="color:var(--sub)">'+a.deg+'°</span>';
|
||
h+='<span style="color:var(--sub);font-size:9px;margin-left:auto">容许 '+a.orb+'°</span>';
|
||
h+='</div>';
|
||
});
|
||
if(aspects.length===0)h+='<div style="color:var(--sub);font-size:11px">暂无显著的托勒密相位</div>';
|
||
})();
|
||
h+='</div>';
|
||
|
||
// Six dimensions
|
||
h+='<div class="card card-sm"><div class="card-title">🔮 六维解析</div>';
|
||
var dOrder=['吸引力','激情火花','情感深度','沟通','心灵默契','关系持久'];
|
||
var dColors={吸引力:'#E54D42',激情火花:'#FF6347',情感深度:'#7B68EE',沟通:'#4A90E2',心灵默契:'#FF69B4',关系持久:'#5CB85C'};
|
||
dOrder.forEach(function(d){
|
||
h+='<div class="elem-bar"><span class="el" style="width:56px;text-align:left;font-size:10px">'+d+'</span><div class="eb"><div class="ebf" style="width:'+dims[d]+'%;background:'+dColors[d]+'"></div></div><span style="font-size:10px;color:var(--sub);font-weight:700">'+dims[d]+'%</span></div>';
|
||
});
|
||
h+='</div>';
|
||
|
||
// Planet aspect details
|
||
h+='<div class="card card-sm"><div class="card-title">⭐ 行星相位解读</div>';
|
||
planetAspects.slice(0,6).forEach(function(a){
|
||
var alpha=a.score>=80?1:a.score>=60?.85:.7;
|
||
h+='<div style="margin-bottom:10px;opacity:'+alpha+'">';
|
||
h+='<div style="display:flex;align-items:center;gap:6px;margin-bottom:2px"><span style="font-size:15px">'+a.icon+'</span><span style="font-size:12px;font-weight:700">'+a.label+'</span><span style="font-size:10px;color:#FFD700">'+a.stars+'</span><span style="font-size:10px;color:var(--sub);margin-left:auto">'+a.score+'%</span></div>';
|
||
h+='<div style="font-size:11px;color:var(--sub);line-height:1.5">'+a.desc+'</div></div>';
|
||
});
|
||
h+='</div>';
|
||
|
||
// Keywords
|
||
h+='<div class="card card-sm"><div class="card-title">💫 关系关键词</div>';
|
||
h+='<div style="display:flex;flex-wrap:wrap;gap:6px;margin-top:4px">';
|
||
modeCfg.keywords.forEach(function(k){h+='<span style="padding:4px 12px;background:#FFF5F0;color:var(--pri);border-radius:16px;font-size:11px;font-weight:600">#'+k+'</span>';});
|
||
h+='</div></div>';
|
||
|
||
// Sections
|
||
h+='<div class="card card-sm"><div class="card-title">✅ 关系优势</div><div class="card-sub">'+modeCfg.strength+'</div></div>';
|
||
h+='<div class="card card-sm"><div class="card-title">⚠️ 需要注意</div><div class="card-sub">'+modeCfg.watch+'</div></div>';
|
||
h+='<div class="card card-sm"><div class="card-title">💌 给你们的建议</div><div class="card-sub">'+modeCfg.advice+'</div></div>';
|
||
h+='<button class="btn btn-outline btn-block btn-sm" onclick="openSynastry()" style="margin-bottom:16px">重新合盘</button>';
|
||
document.getElementById('synastryResult').innerHTML=h;
|
||
|
||
// Draw radar chart
|
||
setTimeout(function(){
|
||
var cv=document.getElementById('synRadar');if(!cv)return;
|
||
var ctx=cv.getContext('2d'),w=cv.width,h=cv.height,cx=w/2,cy=h/2,r=80;
|
||
ctx.clearRect(0,0,w,h);
|
||
for(var i=1;i<=4;i++){ctx.beginPath();ctx.arc(cx,cy,r*i/4,0,Math.PI*2);ctx.strokeStyle='rgba(255,255,255,'+(.06+.04*i)+')';ctx.lineWidth=.8;ctx.stroke();}
|
||
var labels=['吸引力','激情','情感','沟通','默契','持久'];
|
||
var vals=[dims.吸引力,dims.激情火花,dims.情感深度,dims.沟通,dims.心灵默契,dims.关系持久];
|
||
var clrs=['#E54D42','#FF6347','#7B68EE','#4A90E2','#FF69B4','#5CB85C'];
|
||
// Axes
|
||
for(var i=0;i<6;i++){var a=-Math.PI/2+i/6*Math.PI*2;ctx.beginPath();ctx.moveTo(cx,cy);ctx.lineTo(cx+Math.cos(a)*r,cy+Math.sin(a)*r);ctx.strokeStyle='rgba(255,255,255,.06)';ctx.stroke();}
|
||
// Data polygon
|
||
ctx.beginPath();
|
||
for(var i=0;i<6;i++){var a=-Math.PI/2+i/6*Math.PI*2;var vr=vals[i]/100*r;var px=cx+Math.cos(a)*vr,py=cy+Math.sin(a)*vr;if(i===0)ctx.moveTo(px,py);else ctx.lineTo(px,py);}
|
||
ctx.closePath();var g=ctx.createRadialGradient(cx,cy,0,cx,cy,r);g.addColorStop(0,'rgba(255,215,0,.28)');g.addColorStop(1,'rgba(255,100,50,.04)');ctx.fillStyle=g;ctx.fill();ctx.strokeStyle='rgba(255,215,0,.65)';ctx.lineWidth=2;ctx.stroke();
|
||
// Dots & labels
|
||
for(var i=0;i<6;i++){var a=-Math.PI/2+i/6*Math.PI*2;var vr=vals[i]/100*r;var px=cx+Math.cos(a)*vr,py=cy+Math.sin(a)*vr;ctx.fillStyle=clrs[i];ctx.beginPath();ctx.arc(px,py,4,0,Math.PI*2);ctx.fill();ctx.fillStyle='#FFD700';ctx.beginPath();ctx.arc(px,py,2.2,0,Math.PI*2);ctx.fill();var lx=cx+Math.cos(a)*(r+22),ly=cy+Math.sin(a)*(r+22);ctx.fillStyle='rgba(255,255,255,.65)';ctx.font='9px sans-serif';ctx.textAlign='center';ctx.fillText(labels[i],lx,ly+3);}
|
||
},100);
|
||
// Draw synastry wheel
|
||
setTimeout(function(){drawSynastryWheel('synWheel',{year:y1,month:m1,day:d1},{year:y2,month:m2,day:d2});},150);
|
||
}
|
||
|
||
// Tab refresh helper for result-area chart tabs
|
||
function refreshSynTabs(){
|
||
var tabs=document.querySelectorAll('#synastryResult .syn-tab');
|
||
tabs.forEach(function(t){t.classList.remove('active');});
|
||
var idx={compare:0,composite:1,marksAB:2,marksBA:3}[synChartType];
|
||
if(tabs[idx])tabs[idx].classList.add('active');
|
||
}
|
||
|
||
// ═══════ SCHULTE ═══════
|
||
var schulteState={running:false,next:1,nums:[],startTime:0,timer:null,best:parseFloat(localStorage.getItem('schulte_best')||'0')};
|
||
|
||
function initSchulteBest(){
|
||
var el=document.getElementById('schulteBest');
|
||
el.textContent=schulteState.best>0?'历史最佳:'+(schulteState.best/1000).toFixed(1)+'s':'';
|
||
}
|
||
initSchulteBest();
|
||
|
||
function shuffleSchulte(){
|
||
var arr=[];for(var i=1;i<=25;i++)arr.push(i);
|
||
for(var i=arr.length-1;i>0;i--){var j=Math.floor(Math.random()*(i+1));var t=arr[i];arr[i]=arr[j];arr[j]=t;}
|
||
return arr;
|
||
}
|
||
|
||
function buildSchulteGrid(){
|
||
if(schulteState.nums.length===0)schulteState.nums=shuffleSchulte();
|
||
var front=document.getElementById('cubeFront');
|
||
front.innerHTML='';
|
||
for(var i=0;i<25;i++){
|
||
var cell=document.createElement('div');cell.className='cs';
|
||
cell.textContent=schulteState.nums[i];
|
||
cell.setAttribute('data-num',schulteState.nums[i]);
|
||
cell.style.animationDelay=((i%5)*0.12+(Math.floor(i/5)*0.08))+'s';
|
||
cell.onclick=function(){schulteClick(this);};
|
||
front.appendChild(cell);
|
||
}
|
||
}
|
||
|
||
function schulteClick(el){
|
||
if(!schulteState.running)return;
|
||
var n=parseInt(el.getAttribute('data-num'));
|
||
if(n!==schulteState.next)return; // wrong order, ignore
|
||
el.classList.add('done');
|
||
schulteState.next++;
|
||
if(schulteState.next>25){finishSchulte();return;}
|
||
// Highlight next target
|
||
var front=document.getElementById('cubeFront');
|
||
var cells=front.querySelectorAll('.cs');
|
||
for(var i=0;i<cells.length;i++){
|
||
var cn=parseInt(cells[i].getAttribute('data-num'));
|
||
cells[i].classList.toggle('next',cn===schulteState.next);
|
||
}
|
||
}
|
||
|
||
function startSchulte(){
|
||
if(schulteState.running)return;
|
||
var scene=document.getElementById('cubeScene');
|
||
scene.classList.add('paused'); // freeze rotation while playing
|
||
schulteState.running=true;schulteState.next=1;
|
||
schulteState.nums=shuffleSchulte();
|
||
schulteState.startTime=performance.now();
|
||
buildSchulteGrid();
|
||
// Mark first number as next
|
||
var front=document.getElementById('cubeFront');
|
||
var cells=front.querySelectorAll('.cs');
|
||
for(var i=0;i<cells.length;i++){
|
||
var cn=parseInt(cells[i].getAttribute('data-num'));
|
||
cells[i].classList.toggle('next',cn===1);
|
||
}
|
||
document.getElementById('schulteBtn').textContent='训练中...';
|
||
document.getElementById('schulteSub').textContent='点击数字 1→2→3...→25,越快越好';
|
||
// Start timer display
|
||
updateSchulteTimer();
|
||
schulteState.timer=setInterval(updateSchulteTimer,100);
|
||
}
|
||
|
||
function updateSchulteTimer(){
|
||
if(!schulteState.running)return;
|
||
var elapsed=(performance.now()-schulteState.startTime);
|
||
document.getElementById('schulteTimer').textContent=(elapsed/1000).toFixed(1)+'s';
|
||
}
|
||
|
||
function finishSchulte(){
|
||
schulteState.running=false;
|
||
clearInterval(schulteState.timer);schulteState.timer=null;
|
||
var elapsed=performance.now()-schulteState.startTime;
|
||
document.getElementById('schulteTimer').textContent=(elapsed/1000).toFixed(1)+'s';
|
||
var scene=document.getElementById('cubeScene');
|
||
scene.classList.remove('paused');
|
||
document.getElementById('schulteBtn').textContent='再来一次';
|
||
document.getElementById('schulteSub').textContent='完成!前额叶激活 ✓ 专注力训练 ✓';
|
||
// Save best
|
||
if(schulteState.best===0||elapsed<schulteState.best){
|
||
schulteState.best=elapsed;
|
||
localStorage.setItem('schulte_best',elapsed);
|
||
document.getElementById('schulteBest').textContent='🎉 新纪录!最佳:'+(elapsed/1000).toFixed(1)+'s';
|
||
}else{
|
||
document.getElementById('schulteBest').textContent='最佳:'+(schulteState.best/1000).toFixed(1)+'s | 本次:'+(elapsed/1000).toFixed(1)+'s';
|
||
}
|
||
// Show result rank hint
|
||
var s=elapsed/1000;
|
||
var rank=s<25?'⚡ 反应极快':s<40?'🔥 优秀':s<60?'👍 良好':s<90?'📖 正常':'🌱 继续加油';
|
||
document.getElementById('schulteSub').textContent+=' · '+rank;
|
||
// Reset cube position
|
||
var cube=document.getElementById('cubeEl');
|
||
cube.style.transform='rotateX(-15deg) rotateY(25deg)';
|
||
}
|
||
|
||
// Cube drag rotate
|
||
(function(){
|
||
var scene=document.getElementById('cubeScene');
|
||
var cube=document.getElementById('cubeEl');
|
||
var dragging=false,lastX=0,rotY=25,rotX=-15;
|
||
scene.addEventListener('mousedown',function(e){if(schulteState.running)return;dragging=true;lastX=e.clientX;});
|
||
scene.addEventListener('mousemove',function(e){if(!dragging)return;rotY+=(e.clientX-lastX)*0.5;lastX=e.clientX;cube.style.transform='rotateX('+rotX+'deg) rotateY('+rotY+'deg)';});
|
||
scene.addEventListener('mouseup',function(){dragging=false;});
|
||
scene.addEventListener('mouseleave',function(){dragging=false;});
|
||
scene.addEventListener('touchstart',function(e){if(schulteState.running||e.touches.length!==1)return;dragging=true;lastX=e.touches[0].clientX;},{passive:true});
|
||
scene.addEventListener('touchmove',function(e){if(!dragging)return;rotY+=(e.touches[0].clientX-lastX)*0.5;lastX=e.touches[0].clientX;cube.style.transform='rotateX('+rotX+'deg) rotateY('+rotY+'deg)';},{passive:true});
|
||
scene.addEventListener('touchend',function(){dragging=false;});
|
||
})();
|