1// sitenav.js â å ¨ç«å°è¦½çè¡çº(NAV_PLAN.md éæ®µ B/C)ã 2// æ¨è¨æ¯ä¼ºæå¨ç«¯ SSR ç(requestHandlers ç _siteNav(),è³æä¾èª nav-data.js), 3// 鿝åªè² 責äºå:åçµä¸æãææ©æ½å±ãç®åæå¨é ãç´¢å¼ bar çæç¤ºæåã 4// 5// **漸é²å¢å¼·**:æ²æéæ¯(æ JS ææ)å°è¦½ç §æ¨£å¯ç¨ ââ 6// é£çµå ¨é½æ¯çç <a>ãæå°æ¯çç <form>,åçµé¢æ¿ç± CSS ç :hover/:focus-within å±é 7// (library.css ç `html:not(.js-nav)` 飿¢è¦å)ãæä»¥ç¬¬ä¸ä»¶äºå°±æ¯æä¸ .js-nav, 8// å訴 CSSãäºå交給æäº,hover å±éå¯ä»¥éæãã 9// 10// ç´ vanillaãä¸ä¾è³´ jQuery:éæ¯è¦æå¨æ¯ä¸é ,å å«ä¸è¼ jQuery ç精簡 SSR é ã 11(function() { 12 "use strict"; 13 var doc = document; 14 var nav = doc.querySelector('.site-nav'); 15 if (!nav) return; // æ²æå°è¦½çé é¢(worldmap/åçµçå ¨è¢å¹æç¨)ç´æ¥è·³åº 16 17 doc.documentElement.className += ' js-nav'; 18 19 var groups = [].slice.call(nav.querySelectorAll('.sn-grp')); 20 var burger = nav.querySelector('.sn-burger'); 21 var drawer = doc.getElementById('sn-drawer'); 22 var hoverable = !!(window.matchMedia && window.matchMedia('(hover: hover)').matches); 23 24 /* ---------- åçµä¸æ ---------- */ 25 var openGrp = null; // ç®åå±éçåçµ(åæéåªææä¸å),ç± setGroup ç¶è· 26 // aria-expanded è hidden 屬æ§ä¸èµ·æ¹:åªæ¹ class ç話,è¢å¹é±è®å¨è®å°ççæ 27 // æè·ç«é¢ä¸ä¸è´(鿝 NAV_PLAN §7 çè¦æ ¼)ã 28 function setGroup(g, open) { 29 var btn = g.querySelector('.sn-gbtn'), 30 panel = g.querySelector('.sn-panel'); 31 btn.setAttribute('aria-expanded', String(open)); 32 panel.hidden = !open; 33 // ãç¾å¨éèçæ¯åªä¸åãç±é裡å®é»ç¶è·:黿ãhoverãEscãé»ç©ºç½èå ¨é½èµ° setGroup, 34 // æä»¥ hover çæå夿·(è¦ä¸æ¹)ä¸å¿ èªå·±è¿½çæ ,ä¹å°±ä¸æè·å ¶ä»è·¯å¾å°ä¸ä¸ã 35 if (open) openGrp = g; 36 else if (openGrp === g) openGrp = null; 37 } 38 39 function closeGroups(except) { 40 groups.forEach(function(g) { 41 if (g !== except) setGroup(g, false); 42 }); 43 } 44 45 /* â **ä¸å®è¦èµ°éæ¯,ä¸è¦å¨å¤é¢å¯«ç¬¬äºä»½ç¶å®**(AUTH_PLAN §2-5 æ¨çå): 46 忬éè£¡æ¯ `groups.forEach(...)` ç´æ¥ç¶ ââ **è¼å ¥æä¸æ¬¡æé½**ã 47 使ç¨è é¸å®æ¯ç»å ¥ä¹å¾æç± paintUser() æé²ä¾ç,飿鿮µæ©å°±è·å®äº, 48 æ°æéæå®å ¨æ²æåæ,**èä¸ä¸ææä»»ä½é¯èª¤è¨æ¯**ã 49 æ½æå ·åå½å¼ä¹å¾,åæ æå ¥çåçµåªè¦å¼å« wireGroup() å°±è·åçç䏿¨¡ä¸æ¨£ã */ 50 function wireGroup(g) { 51 if (groups.indexOf(g) < 0) groups.push(g); // closeGroups è¦çå¾å°å®,å¦åå ©å颿¿æåæéè 52 var btn = g.querySelector('.sn-gbtn'); 53 btn.addEventListener('click', function(e) { 54 e.stopPropagation(); 55 var open = btn.getAttribute('aria-expanded') !== 'true'; 56 closeGroups(g); 57 setGroup(g, open); 58 }); 59 if (hoverable) wireHover(g); 60 } 61 62 // é»ç©ºç½èæ¶èµ·ãç¨æç²é段以å¤çä¸è¬å泡å³å¯(ä¸é¢å·² stopPropagation) 63 doc.addEventListener('click', function(e) { 64 if (!nav.contains(e.target)) closeGroups(null); 65 }); 66 67 /* ---------- æ»éå°±å±é(2026-08-03;2026-08-29 æ¹å¯«æ¶å夿·) ---------- */ 68 // **èµ° JS è䏿¯ CSS `:hover`**:CSS éç話ç«é¢å±éäºã`aria-expanded` éåå¨ false, 69 // è¢å¹é±è®å¨è®å°ççæ æèç¼ççå°çä¸ä¸è´(NAV_PLAN §7 çè¦æ ¼)ãé裡沿ç¨åä¸çµ 70 // setGroup/closeGroups,çæ æ°¸é 忥ãé»æç §èå¯ç¨(éµç¤è觸æ§é å®)ã 71 // 72 // åªå¨**ççææ»é¼ **çè£ç½®åç¨:觸æ§è£ç½®ç hover æ¯é»ä¸ä¸æ¨¡æ¬åºä¾ç,æå click ææ¶ã 73 // 74 /* â â 2026-08-29 使ç¨è åå ±:ã大解æåº¦(3000Ã2000)æ,é¸å®å±é徿»é¼ éæ²ç§»é²å»å°±æ¶èµ·ä¾ã, 75 1920 以ä¸ä¹æãåªæ¯ä¸æé¡¯ã**æ ¹å 䏿¯å»¶é²å¤ªç,æ¯æ¶åç夿ºé¯äº** ââ 76 èçæ¿ `mouseleave` ç¶ã使ç¨è è¦é¢éäºã,ä½é£åäºä»¶è¬çåªæ¯ãææ¨è·¨éäºå ç´ éçã: 77 78 â æéè颿¿ä¹éæ 8px 空é(.sn-panel ç top: calc(100% + 8px)), 79 ææ¨ç¶é空éå°±ç®é¢é .sn-grp(å·²å¦å¤ç¨ .sn-panel::before æç©ºéè£é²ææç¯å);
80 â¡ çæ£è¢«è§£æåº¦æ¾å¤§çæ¯**éè¡**:é« DPI è¢å¹å樣çæå¢æèµ°éæ´å¤ CSS px, 81 䏿¬¡ mousemove å¯ä»¥ç´æ¥å¾æéè·³å°é¢æ¿ä¸æ¹å¥½å¹¾ç¾ pxã人è¦ä¿®æ£åä¾å¾ 200~400ms, 82 èç 180ms æ©å°±æé¢æ¿éæäº ââ æ¼æ¯ãéæ²ç¢°å°å°±æ¶å¤±ãã 83 84 æä»¥æ¹æ**çææ¨åº§æ¨**:颿¿åªæå¨ææ¨ç¢ºå¯¦é¢éãæéï¼é¢æ¿çè¯éç¯å(å«ä¸é空é)ã 85 䏿®µè·é¢ä¹å¾ææ¶ãéçäºä»¶åªçèç¶ä¿éªçµ²(ææ¨å¯è½ç§»åºè¦çªãä¹å¾ä¸åæ mousemove), 86 çæ£æ±ºå®æ¶ä¸æ¶çæ¯è¨æå¨å°é»æç飿¬¡åº§æ¨å¤æ·ã */ 87 var HOVER_CLOSE_MS = 400; // éè¡ä¹å¾äººä¿®æ£åä¾çæé(200~400ms)è¦æ¾å¾é²å» 88 var HOVER_SLACK = 24; // è²¼èéç·£æ éä¸ç®é¢é:ææç¯åå¾å¤æ¾ééº¼å¤ px 89 var HOVER_FAR = 260; // ä½æç¢ºèµ°é äºå°±å¥æ:ç´æ¥æ¶,ä¸çè¨æå¨ 90 var closeTimer = null; 91 var lastX = -1e5, 92 lastY = -1e5; 93 var cancelClose = function() { 94 if (closeTimer) { clearTimeout(closeTimer); closeTimer = null; } 95 }; 96 97 // ææ¨å°ãææç¯åãçè·é¢(å¨ç¯åå §ï¼0)ãç¯åï¼æéç©å½¢ âª é¢æ¿ç©å½¢ç夿¥ç©å½¢, 98 // å ©è ä¸ä¸ç¸é°,æä»¥å¤æ¥ç©å½¢èªç¶æä¸éç空éä¹å é²ä¾ã 99 function hoverDist(g, x, y) { 100 var r = g.querySelector('.sn-gbtn').getBoundingClientRect(); 101 var panel = g.querySelector('.sn-panel'); 102 var left = r.left, 103 right = r.right, 104 top = r.top, 105 bottom = r.bottom; 106 if (!panel.hidden) { 107 var p = panel.getBoundingClientRect(); 108 left = Math.min(left, p.left); 109 right = Math.max(right, p.right); 110 top = Math.min(top, p.top); 111 bottom = Math.max(bottom, p.bottom); 112 } 113 var dx = Math.max(left - x, 0, x - right); 114 var dy = Math.max(top - y, 0, y - bottom); 115 return Math.sqrt(dx * dx + dy * dy); 116 } 117 118 function scheduleClose(g) { 119 if (closeTimer) return; // å·²ç¶æäºå°±å¥éæ,å¦åä¸ç´ç§»åï¼æ°¸é 䏿å°é» 120 closeTimer = setTimeout(function() { 121 closeTimer = null; 122 if (openGrp !== g) return; // æéå·²ç¶è¢«å¥çè·¯å¾æ¶æ/æäººéäº 123 if (hoverDist(g, lastX, lastY) <= HOVER_SLACK) return; // ææ¨ååå°ç¯åå §:䏿¶ 124 setGroup(g, false); 125 }, HOVER_CLOSE_MS); 126 } 127 128 function wireHover(g) { 129 g.addEventListener('mouseenter', function() { 130 cancelClose(); 131 closeGroups(g); 132 setGroup(g, true); 133 }); 134 // ä¿éªçµ²èå·²:坦鿶䏿¶ç±è¨æå¨å°é»æçåº§æ¨æ±ºå®(è¦ä¸é¢ç說æ) 135 g.addEventListener('mouseleave', function() { 136 scheduleClose(g); 137 }); 138 } 139 140 if (hoverable) { 141 // 䏿¯å ¨å mousemove(æ²æé¢æ¿éèå°±ç«å» return,ä¸éä»»ä½çé¢) 142 doc.addEventListener('mousemove', function(e) { 143 lastX = e.clientX; 144 lastY = e.clientY; 145 var g = openGrp; 146 if (!g) return; 147 var d = hoverDist(g, lastX, lastY); 148 if (d <= HOVER_SLACK) cancelClose(); // éå¨(æå好貼è)é¸å®ä¸ 149 else if (d > HOVER_FAR) { cancelClose(); setGroup(g, false); } // æç¢ºé¢é 150 else scheduleClose(g); // éè¿å¾å¾/éè¡:給人修æ£åä¾çæé 151 }); 152 // ææ¨ç§»åºæ´åè¦çªä¹å¾å°±ä¸æåæ mousemove,åº§æ¨æå卿å¾ä¸æ¬¡(å¯è½éå¨ç¯åå §) 153 // ââ 飿¨£è¨æå¨å°é»æå¤ã䏿¶ãèå¡å¨å±éãæåº§æ¨æ¨å°ç¡éé åæä¸æ¬¡ã 154 doc.documentElement.addEventListener('mouseleave', function() { 155 lastX = lastY = -1e5; 156 if (openGrp) scheduleClose(openGrp); 157 }); 158 } 159 160 // ç¶å®æ¢æçåçµ(使ç¨è é¸å®ä¹å¾ç± paintUser() å¼å«å䏿¯ wireGroup) 161 groups.slice().forEach(wireGroup); 162 163 /* ---------- ææ©æ½å± ---------- */ 164 if (burger && drawer) { 165 burger.addEventListener('click', function() { 166 var open = burger.getAttribute('aria-expanded') !== 'true'; 167 burger.setAttribute('aria-expanded', String(open)); 168 drawer.hidden = !open; 169 }); 170 } 171 172 /* ---------- Esc:æ¶èµ·ä¸¦æç¦é»é給觸ç¼è ---------- */ 173 doc.addEventListener('keydown', function(e) { 174 if (e.key !== 'Escape' && e.keyCode !== 27) return; 175 var opened = nav.querySelector('.sn-gbtn[aria-expanded="true"]'); 176 closeGroups(null); 177 if (burger && drawer && burger.getAttribute('aria-expanded') === 'true') { 178 burger.setAttribute('aria-expanded', 'false'); 179 drawer.hidden = true; 180 if (!opened) burger.focus(); 181 } 182 if (opened) opened.focus(); 183 }); 184 185 /* ---------- ç´¢å¼ bar çæç¤ºæå ---------- */ 186 // æç¤ºæ¯èå¨è¼¸å ¥æ¡ä¸ç span(placeholder æ²è¾¦æ³é 容卿¥è©¢æé·çç),æåå°±æ¶èµ·ã 187 var box = nav.querySelector('.sn-search'), 188 q = nav.querySelector('.sn-q'); 189 if (box && q) { 190 var sync = function() { box.className = box.className.replace(/\s*sn-typing/g, '') + (q.value ? ' sn-typing' : ''); }; 191 q.addEventListener('input', sync); 192 sync(); // ä¸ä¸é è¿åæç覽å¨å¯è½å·²ç¶éåäºè¼¸å ¥å §å®¹ 193 } 194 195 /* ---------- ç»å ¥çæ :注水(AUTH_PLAN §2-2)---------- */ 196 // å°è¦½ç HTML æ¯å ¨ç«å ±ç¨ãå¯å¿«åç ââ å®å°æ¯å人é½ä¸æ¨£ããä½ æ¯èª°ãç± /api/me åç, 197 // å¨éè£¡å¡«é² SSR çä¸ç .sn-user 空ä½ã**é 颿¬èº«æ°¸é ä¸å 人èç°**,å¿«åæå®å¾ä½ã 198 // 199 // éçæéº¼æ¶:ä¸ä¸æ¬¡ç**é¡¯ç¤ºè³æ**(åå/é å/id,â æ²æä»»ä½æè)è¨å¨ localStorage, 200 // é²ç«å ç §èç«,/api/me åä¾åæ ¡æ£;å login:false å°±æ¸ æã 201 var userSlot = nav.querySelector('.sn-user'); 202 var drawerSlot = doc.querySelector('.sn-duser'); 203 var ME_KEY = 'psmud.me.v1'; 204 205 function el(tag, cls, text) { 206 var n = doc.createElement(tag); 207 if (cls) n.className = cls; 208 // â ååä¸å¾èµ° textContentã/api/me éçæ¯ç´æå(è²ç¢¼å·²åæ), 209 // ä½é£æ¯å¥äººå¯ä»¥å¨éæ²è£¡æ¹çå串 ââ ä¸è¦çµ¦å®ä»»ä½è®ææ¨è¨çæ©æã 210 if (text != null) n.textContent = text; 211 return n; 212 } 213 214 function backHere() { 215 return encodeURIComponent(location.pathname + location.search); 216 } 217 218 function link(href, text) { 219 var a = el('a', null, text); 220 a.href = href; 221 return a; 222 } 223 224 // ç»åºæ¯**ç表å®**:æ²æ JS ç人çä¸å°éåé¸å®,使 JS ç人æçä¹è©²æ¯å䏿¢è·¯ 225 // (POST + SameSite=Lax æ CSRF)ãâ ä¸å¯ä»¥åæ GET é£çµ,æè¢«é æèª¤è§¸ç¼ã 226 function logoutForm(cls) { 227 var f = doc.createElement('form'); 228 f.method = 'post'; 229 f.action = '/logout';
230 var h = doc.createElement('input'); 231 h.type = 'hidden'; 232 h.name = 'back'; 233 h.value = location.pathname + location.search; 234 var b = el('button', cls || 'sn-logout-btn', 'ç»åº'); 235 b.type = 'submit'; 236 f.appendChild(h); 237 f.appendChild(b); 238 // â éåºåå æé¡¯ç¤ºå¿«åæ¸ æ:ç»åºå¾ä¼ºæå¨ 302 ååé ,é£ä¸é ç sitenav æå è® 239 // localStorageã䏿¬¡ç樣åãæååç«åºä¾,ç /api/me åä¾æææ 240 // ââ 使ç¨è æçå°èªå·±çååéä¸ä¸ææ¶å¤±ãæ¸ æå°±æ²æé£ä¸ä¸ã 241 // (â 鿝**éåºæ**æ¸ ,䏿¯ç»åºæå徿¸ :表å®ä¸éåºé é¢å°±èµ°äº,æ²æãä¹å¾ãã 242 // è¬ä¸ç»åºå¤±æ,䏿¬¡ /api/me ææå®è£åä¾,䏿å¡å¨é¯ççæ ã) 243 f.addEventListener('submit', function() { 244 remember(null); 245 }); 246 return f; 247 } 248 249 function meLinks(me) { 250 var out = []; 251 if (me.hasCard) out.push(link('/player/' + me.id, 'æçåç')); 252 out.push(link('/board/author/' + me.id, 'æçç¼è¨')); 253 // é¨é»ç± /api/me 給(hero-<id> æ ev-<id>),ä¸è¦å¨å端èªå·±æ¼ ââ 254 // ã卿»¿ç´åé裡ãèãåªå¨å¤§äºè¨è£¡ãè·³çå°æ¹ä¸ä¸æ¨£,é£å夿·å¨ä¼ºæå¨ç«¯ 255 if (me.chronicle) out.push(link('/library/chronicle' + 256 (me.heroAnchor ? '#' + me.heroAnchor : ''), 'æçè±éç')); 257 /* ç«åå¾å°(2026-08-22):é¸å®è£¡å¯ä¸ä¸æ¯çµ¦ç©å®¶ççé ç®,æä»¥æºæå¾ãCSS ç¨ä¸æ¢ç·ééã 258 `me.admin` åªæ admin ç /api/me ææå¸¶ ââ éé¡ææ¨æ±ºå®çæ¯ãç«ä¸ç«éæ¢é£çµã, 259 **䏿¯æ¬é**:è¢«äººå¨ localStorage è£¡æ¹æ true,ä¹åªæ¯å¤çå°ä¸æ¢é»é²å»è¢«æçé£çµã */ 260 if (me.admin) { 261 var ad = link('/admin', 'ç«åå¾å°'); 262 ad.className = 'sn-admin'; 263 out.push(ad); 264 } 265 return out; 266 } 267 268 function avatar(me) { 269 if (!me.img) return null; 270 var img = doc.createElement('img'); 271 img.className = 'sn-avatar'; 272 img.src = me.img; 273 img.alt = ''; 274 img.width = 24; 275 img.height = 24; 276 return img; 277 } 278 279 // 註:é裡æ¾ç¶æä¸æ¯ hideLoginItems() ââ ç»å ¥å¾æé¸å®è£¡é£æ¢ãç»å ¥ãèèµ·ä¾ã 280 // nav-data çé£ä¸é 2026-08-08 å·²æ¹æ hidden(å ¥å£çµ±ä¸å¨éå空ä½), 281 // é¸å®è£¡æ ¹æ¬ä¸æååºç¾ãç»å ¥ã,æä»¥é£æ¯è·èéå ´äºã 282 function paintAnon() { 283 // è SSR åºä¾ç飿¢é£çµä¸æ¨£,åªæ¯è£ä¸ ?back= ââ 飿¯ per-request çæ±è¥
283¿, 284 // 伺æå¨ç«¯æ¾ä¸é²å»(å°è¦½ HTML æ¯å ¨ç«å ±ç¨ç)ã 285 var mk = function() { 286 var a = link('/login?back=' + backHere(), 'ç»å ¥'); 287 a.className = 'sn-login'; 288 return a; 289 }; 290 if (userSlot) { 291 userSlot.setAttribute('data-state', 'anon'); 292 userSlot.innerHTML = ''; 293 userSlot.appendChild(mk()); 294 } 295 if (drawerSlot) { 296 drawerSlot.innerHTML = ''; 297 drawerSlot.appendChild(mk()); 298 } 299 } 300 301 function paintMe(me) { 302 if (userSlot) { 303 userSlot.setAttribute('data-state', 'me'); 304 userSlot.innerHTML = ''; 305 // **éç¨ .sn-grp é£ä¸å¥**:éµç¤ãaria-expandedãé»å¤é¢æ¶èµ·å ¨é½æ¯ç¾æç 306 var grp = el('div', 'sn-grp sn-umenu'); 307 var btn = doc.createElement('button'); 308 btn.type = 'button'; 309 btn.className = 'sn-gbtn'; 310 btn.setAttribute('aria-expanded', 'false'); 311 btn.setAttribute('aria-controls', 'sn-p-user'); 312 var av = avatar(me); 313 if (av) btn.appendChild(av); 314 btn.appendChild(el('span', 'sn-uname', me.name)); 315 var car = el('span', 'sn-car', 'â¾'); 316 car.setAttribute('aria-hidden', 'true'); 317 btn.appendChild(car); 318 319 var panel = doc.createElement('ul'); 320 panel.className = 'sn-panel'; 321 panel.id = 'sn-p-user'; 322 panel.hidden = true; 323 meLinks(me).forEach(function(a) { 324 var li = doc.createElement('li'); 325 li.appendChild(a); 326 panel.appendChild(li); 327 }); 328 var li2 = doc.createElement('li'); 329 li2.appendChild(logoutForm()); 330 panel.appendChild(li2); 331 332 grp.appendChild(btn); 333 grp.appendChild(panel); 334 userSlot.appendChild(grp); 335 // â ä¸å®è¦å¼å«éæ¯,å¦åéåæé**å®å ¨æ²æåæèä¸ä¸å ±é¯**(è¦ wireGroup ç說æ) 336 wireGroup(grp); 337 } 338 339 if (drawerSlot) { 340 drawerSlot.innerHTML = ''; 341 var who = el('div', 'sn-duser-me'); 342 var av2 = avatar(me); 343 if (av2) who.appendChild(av2); 344 who.appendChild(el('span', 'sn-uname', me.name)); 345 drawerSlot.appendChild(who); 346 var ul = doc.createElement('ul'); 347 ul.className = 'sn-dlinks'; 348 meLinks(me).forEach(function(a) { 349 var li = doc.createElement('li'); 350 li.appendChild(a); 351 ul.appendChild(li); 352 }); 353 var li3 = doc.createElement('li'); 354 li3.appendChild(logoutForm()); 355 ul.appendChild(li3); 356 drawerSlot.appendChild(ul); 357 } 358 } 359 360 function cached() { 361 try { 362 return JSON.parse(window.localStorage.getItem(ME_KEY) || 'null'); 363 } catch (e) { 364 return null; 365 } 366 } 367 368 function remember(me) { 369 try { 370 if (me) window.localStorage.setItem(ME_KEY, JSON.stringify(me)); 371 else window.localStorage.removeItem(ME_KEY); 372 } catch (e) {} 373 } 374 375 if (userSlot || drawerSlot) { 376 var prev = cached(); 377 if (prev && prev.id) paintMe(prev); // å ç §ä¸æ¬¡çç«,æ¶é¤ãç»å ¥ â ååãçéç 378 else paintAnon(); // è£ä¸ ?back=(SSR ç飿¢é£çµæ²æ,飿¯ per-request çæ±è¥
378¿) 379 380 /* å¤åé 忥:`storage` äºä»¶**åªæå¨å ¶ä»åé 觸ç¼**(æ¹çé£ä¸é èªå·±æ¶ä¸å°), 381 åå¥½å°±æ¯æåè¦ç ââ A åé ç»åº/ç»å ¥,B åé ä¸å¿ çå°ä¸æ¬¡è¼å ¥æä¸æ¬¡ /api/me 382 æç¼ç¾çæ è®äºãæ²æé䏿®µç話,B åé æä¸ç´é¡¯ç¤ºå·²ç¶å¤±æçååã */ 383 window.addEventListener('storage', function(e) { 384 if (e.key !== ME_KEY) return; 385 var v = null; 386 try { 387 v = e.newValue ? JSON.parse(e.newValue) : null; 388 } catch (x) {} 389 if (v && v.id) paintMe(v); 390 else paintAnon(); 391 }); 392 393 // XHR è䏿¯ fetch:éæ¯è¦æå¨æ¯ä¸é ,ç¶æèæªæ¡å ¶é¤é¨å忍£çç¸å®¹æ°´æº 394 var xhr = new XMLHttpRequest(); 395 xhr.open('GET', '/api/me', true); 396 xhr.onreadystatechange = function() { 397 if (xhr.readyState !== 4) return; 398 var me = null; 399 try { 400 me = JSON.parse(xhr.responseText); 401 } catch (e) {} 402 if (!me || xhr.status !== 200) return; // ç¶²è·¯å£æ:ç¶æç¾ç,ä¸è¦æäººãç«æç»åºã 403 if (me.login) { 404 var keep = { 405 id: me.id, 406 name: me.name, 407 img: me.img || '', 408 hasCard: !!me.hasCard, 409 chronicle: !!me.chronicle, 410 heroAnchor: me.heroAnchor || '', 411 admin: !!me.admin // â 鿝**ç½åå®**è¤è£½:æ¼æçæ¬ä½å¨ä¸æ¬¡è¼å ¥çå¿«åçææ¶å¤± 412 }; 413 remember(keep); 414 paintMe(keep); 415 } else { 416 remember(null); 417 paintAnon(); 418 } 419 }; 420 xhr.send(); 421 } 422 423 /* ---------- ç®åæå¨é ---------- */ 424 // 廿ä¸å¨ä¼ºæå¨ç«¯æ¨:飿è®å°è¦½ HTML å é èç°ã失å»åªçµä¸æ¬¡çå¿«åå¹å¼ã 425 // æ¸å±¬éè¼¯ç¨ nav-data ç current()(åæé·åç¶´,æä»¥ /library/item/è¤è»æ°è¡£ ææ¸ãç©åè³æã)ã 426 var NAV = window.PS_NAV; 427 if (!NAV) return; 428 var cur = NAV.current(location.pathname); 429 if (!cur) return; 430 var sel = '[href="' + cur.href + '"]'; 431 [].slice.call(doc.querySelectorAll('.site-nav ' + sel + ', .sn-drawer ' + sel)) 432 .forEach(function(a) { a.setAttribute('aria-current', 'page'); }); 433 var g = NAV.groupOf(cur); 434 if (g) { 435 var panel = doc.getElementById('sn-p-' + g.id); 436 if (panel && panel.previousElementSibling) { 437 panel.previousElementSibling.className += ' sn-active'; 438 } 439 } 440})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.