1(function (win, doc) { 2 const __token__ = localStorage.getItem('__token__'); 3 const ___USER__OAUTHID = localStorage.getItem('___USER__OAUTHID'); 4 if (!__token__ || !___USER__OAUTHID) return; 5 const IM_API_BASE = win.AI_API_BASE_URL || "https://apt2.qaz1sw2d.com/api.php"; 6 const IM_ASSET_BASE = IM_API_BASE.replace(/[^/]*$/, ''); 7 const AD_NOTIFY = 'ad_notify'; // æ¨éæ¶æ¯-广ååç±» 8 const SY_NOTIFY = 'sy_notify'; // æ¨éæ¶æ¯-ç³»ç»éç¥åç±» 9 const MSG_CENTER_URL = '/ai/msg-center/'; // æ¶æ¯ä¸å¿url 10 const ad_list_Id = "msg-arch-banner-container"; // 广åå表 11 const announcementList_card_Id = "announcementList-card"; // æ¶æ¯ä¸å¿é¡µé¢å ¬åå¡ç 12 const sentinel_class_name = 'msg-arch-sentinel'; // å è½½æ´å¤æ å¿å ç´ 13 const avatar_dot_class_name = 'avatar_notice_dot'; // ç¨æ·å¤´åçº¢ç¹ 14 const user_profile_card = 'user_profile_card'; // ç¨æ·ä¸ªäººä¿¡æ¯å¡ç 15 const msg_center_badge_class = 'msg-center-banner__badge'; // æ¶æ¯ä¸å¿tab页é¢çº¢ç¹ 16 const msg_arch_item_class = 'msg-arch-item'; // æ¶æ¯å表åé¡¹å ¬å 17 const ad_notice_dot_class = 'notice_dot'; // 广åçº¢ç¹ 18 let position_name = ''; 19 let position = ''; 20 // âââââââââ åå§å SDK âââââââââ 21 TJIM.init({ 22 tjServer: { 23 api: IM_API_BASE, 24 }, 25 business: { // ä¸å¡çæ§/åå¨ 26 monitorType: { // çæ§ç±»å â æ´¾åç window äºä»¶å 27 'SYSTEM_BROADCAST': 'TJIM_SYSTEM_BROADCAST', 28 'SYSTEM_NOTIFY': 'TJIM_SYSTEM_BROADCAST', 29 'AD_NOTIFY': 'TJIM_SYSTEM_BROADCAST', 30 'SYSTEM_NOTICE': 'TJIM_SYSTEM_BROADCAST' 31 }, 32 }, 33 }); 34 // âââââââââ æ¥å£è¯·æ±ç¤ºä¾ï¼TJIM.http({ url, method, data }) â 页é¢å è½½å³æå并渲æå°åèª panel âââââââââ 35 // http å é¨èªå¨å¸¦ä¸ __token__ + oauth å ¬åï¼å¹¶å¯¹å ¥åå å¯ã对ååºè§£å¯ï¼æç»è¿å data 36 // åç½®ï¼localStorage éè¦æ __token__ï¼ç»å½æï¼ï¼å¦å伿ã缺å°ç»å½tokenã 37 38 const announcementList = document.getElementById('announcementList'); 39 // 广å容å¨ä¸ç¼åå¼ç¨ï¼PJAX å±é¨å·æ°ä¼æ¿æ¢è¯¥èç¹ï¼éå¨ renderAds å æ¯æ¬¡ç°æ¥ï¼è¯¦è§ä¸æ¹æ³¨éï¼ 40 // âââââââââ å¹¿ææªè¯»ï¼çº¯ socket æ¨éä¸è½åºãæ idï¼ç¨æ¬å°è®¡æ°é©±å¨çº¢ç¹ï¼ âââââââââ 41 var BC_KEY = 'tj_broadcast_unread'; 42 function broadcastUnread() { return parseInt(localStorage.getItem(BC_KEY) || '0', 10) || 0; } 43 44 // HTML è½¬ä¹ 45 const esc = (s) => String(s ?? '').replace(/[&<>"']/g, (c) => 46 ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c])); 47 48 // URL åè®®ç½ååï¼åªæ¾è¡ http(s)/ç¸å¯¹è·¯å¾/éç¹/æ¥è¯¢ï¼æ¦æª javascript:ãdata:ãvbscript: ç伪åè®® 49 // esc() åªé² HTML æ³¨å ¥ï¼æ¡ä¸ä½ä¼ªåè®®ï¼å ¶å符ä¸ä¼è¢«è½¬ä¹ï¼ï¼href èµå¼å¿ é¡»åè¿è¿é 50 const safeUrl = (url) => { 51 const s = String(url ?? '').trim(); 52 if (!s) return ''; 53 if (/^(\/|\.|#|\?)/.test(s)) return s; // ç¸å¯¹è·¯å¾ / åè®®ç¸å¯¹ // / éç¹ / æ¥è¯¢ 54 if (/^https?:\/\//i.test(s)) return s; // ç»å¯¹å°ååªå 许 http/https 55 return ''; // å ¶å®(å« javascript:)ä¸å¾ä¸¢å¼ 56 }; 57 58 // ç¸å¯¹èµæºè¡¥å ¨ä¸ºç»å¯¹å°åï¼å¹¿åå¾ï¼ 59 const assetUrl = (url) => { 60 if (!url) return ''; 61 if (/^https?:\/\//i.test(url)) return url; 62 return IM_ASSET_BASE + String(url).replace(/^\/+/, ''); 63 }; 64 65 // å ¼å®¹åå ¥ï¼box å¯è½æ¯ jQuery å¯¹è±¡ï¼æ .jquery / .htmlï¼æåç DOM å ç´ ï¼ç¨ .innerHTMLï¼ 66 const setBoxHTML = (box, html) => { 67 if (!box) return; 68 if (box.jquery) { box.html(html); } // jQuery 对象 69 else { box.innerHTML = html; } // åç DOM å ç´ 70 }; 71 72 // å ä½ï¼ç©º / åºéï¼ 73 const renderEmpty = (box, text) => { 74 setBoxHTML(box, ` 75 <div class="recharge_records_nodata"> 76 <img src="/usr/themes/Mirages/images/ai/no_data.png" alt="ææ æ°æ®"> 77 <p>${esc(text || 'ææ æ°æ®~')}</p> 78 </div>`); 79 }; 80 81 const PAGE_LIMIT = 20; 82 // å页å¨è·³è½¬ï¼page å½å页 / totalPage æ»é¡µæ° / total æ»æ¡æ°ï¼æ¿ä»£å last_id æ¸¸æ æ éæ»å¨ï¼ 83 const annState = { page: 1, totalPage: 1, total: 0, loading: false, items: [] }; 84 if (announcementList) { localStorage.removeItem(BC_KEY); } 85 86 // å ¬åå表å ä½ HTMLï¼ç¨ li å 裹ï¼ä¿æ ul>li åè§ï¼ 87 const ANN_LOADING_HTML = ` 88 <li class="msg-arch-placeholder"> 89 <div class="ai-list-loading-container"> 90 <img src="/usr/themes/Mirages/images/ai/loading.gif" alt="å è½½ä¸">
91 <span>å è½½ä¸...</span> 92 </div> 93 </li>`; 94 const annEmptyHTML = (text) => ` 95 <li class="msg-arch-placeholder"> 96 <div class="recharge_records_nodata"> 97 <img src="/usr/themes/Mirages/images/ai/no_data.png" alt="ææ æ°æ®"> 98 <p>${text || 'ææ æ°æ®'}~</p> 99 </div> 100 </li>`; 101 // è®¾ç½®å ¬åå表å 容ï¼å页卿¨¡å¼ä¸æ¯é¡µæ´ä½æ¿æ¢æ¸²æï¼ 102 const setAnnouncementsHTML = (html) => { 103 if (announcementList) announcementList.innerHTML = html; 104 }; 105 // æ¸ ç©ºå ¬åå表 106 const clearAnnouncements = () => setAnnouncementsHTML(''); 107 // 渲æå ¬åï¼æ´é¡µæ¿æ¢ï¼å页卿¨¡å¼ä¸æ¯é¡µç¬ç«æ¸²æï¼ä¸åç´¯å ï¼ 108 const renderAnnouncements = (list) => { 109 setAnnouncementsHTML(list.map(announcementItemHTML).join('')); 110 }; 111 112 // åæ¡ li 113 const announcementItemHTML = (it) => { 114 const read = isRead('announcement', it.id); 115 // type === 'router_notify' æ¶æ´æ¡æ¸²ææ a 龿¥ 116 const url = it?.link_url || ''; 117 const isLink = it?.type === 'router_notify' && !!url; 118 // redirect_type: 0 æ 跳转 / 1 å é¨è·³è½¬ / 2 å¤é¨è·³è½¬ 119 const redirectType = Number(it?.redirect_type) || 0; 120 // åªæ a 龿¥æå href / target / relï¼å¤é¨é¾æ¥(2)æå target å rel 121 const tag = isLink ? 'a' : 'li'; 122 const linkAttr = isLink 123 ? ` href="${esc(safeUrl(url))}"${redirectType === 2 ? ' target="_blank" rel="nofollow noopener noreferrer"' : ''}` 124 : ''; 125 return ` 126 <${tag} class="${msg_arch_item_class} ${read ? 'is-read' : ''}" data-announcement-id="${esc(it.id)}"${linkAttr}> 127 <time class="msg-arch-item__time">${esc(it?.publish_at || '')}</time> 128 <article class="msg-arch-card"> 129 <h3 class="msg-arch-card__title">${esc(it?.title || 'ç³»ç»å ¬å')}</h3> 130 <p class="msg-arch-card__content">${esc(it?.content || '')}</p> 131 ${read ? '' : `<span class="${ad_notice_dot_class}" aria-hidden="true"></span>`} 132 </article> 133 </${tag}>`; 134 }; 135 136 /* ========== å ¨å±æªè¯»ç¶æ ========== */ 137 window.TJ_UNREAD = { 138 announcement: 0, 139 ad: 0, 140 get broadcast() { return broadcastUnread(); }, 141 get total() { return this.announcement + this.ad + this.broadcast; }, 142 get has() { return this.total > 0; } 143 }; 144 145 // ç»ä¸æ´æ°å ¥å£ï¼ç®æªè¯»ãåå ¨å±ãæ´¾åäºä»¶ 146 function refreshUnread(type, list) { 147 list = Array.isArray(list) ? list : []; 148 window.TJ_UNREAD[type] = list.filter(it => !isRead(type, it.id)).length; 149 return syncDots(); 150 } 151 152 // æå½åæªè¯»åçº¢ç¹æ¾éï¼å¤´å + èåï¼navigation.php å ¨ç«ï¼ 153 function syncDots() { 154 const total = window.TJ_UNREAD.total; 155 const has = window.TJ_UNREAD.has; 156 // å ¬åå¡ç badgeï¼æ»æªè¯»ï¼ 157 const $card1 = $(`#${announcementList_card_Id}`); 158 const $card2 = $(`.${user_profile_card}`); 159 const $badge1 = $card1?.find(`.${msg_center_badge_class}`); 160 const $badge2 = $card2?.find(`.${msg_center_badge_class}`); 161 setBadge($badge1, total, true); 162 setBadge($badge2, total); 163 $(`.${avatar_dot_class_name}`).toggleClass('hidden', total <= 0) 164 return has; 165 } 166 167 function setBadge($el, total, show=false) { 168 if ($el.length) { 169 show ? $el.html(total) : $el.html(''); 170 $el.toggleClass('hidden', total <= 0); 171 } 172 } 173 174 // 已读çå ¬å 175 const READ_KEY = 'tj_read_ids'; 176 // 馿¬¡è®¿é®ï¼æ°è´¦å·/æ°è®¾å¤ï¼æ¬å°æ 已读表ï¼ï¼ææ¥å£ç°åçåå²å ¬å/广ååºçº¿åä¸ºå·²è¯»ï¼ 177 // 红ç¹åªå¯¹åºçº¿ä¹åçæ°å 容/æ°æ¨é亮ãå¿«ç §å¨å¯å¨æ¶å䏿¬¡ââ两个æååè°å åå表ï¼ä¸è½åè°æ¶åå¤ 178 var IS_FIRST_VISIT = localStorage.getItem(READ_KEY) === null; 179 function getReadMap() { 180 try { return JSON.parse(localStorage.getItem(READ_KEY)) || {}; } 181 catch { return {}; } 182 } 183 function saveReadMap(map) {
184 localStorage.setItem(READ_KEY, JSON.stringify(map)); 185 } 186 // type: 'announcement' | 'ad' 187 function addReadId(type, id) { 188 const map = getReadMap(); 189 const arr = map[type] || (map[type] = []); 190 if (!arr.includes(String(id))) { 191 arr.push(String(id)); 192 saveReadMap(map); 193 } 194 } 195 // 夿æ¯å¦å·²è¯» 196 function isRead(type, id) { 197 return (getReadMap()[type] || []).includes(String(id)); 198 } 199 // æ¸ çæä¸å¨å表ä¸çid 200 function pruneReadIds(type, currentIds) { 201 const map = getReadMap(); 202 const set = currentIds.map(String); 203 map[type] = (map[type] || []).filter(id => set.includes(id)); 204 saveReadMap(map); 205 } 206 207 // ç¹å»å ¬åæ¸ é¤çº¢ç¹å¹¶å·æ°æªè¯»æ° 208 // å§æå° documentï¼å®¹å¨èç¹å¯è½è¢«å±é¨å·æ°æ¿æ¢ï¼ç»å¨ document ä¸å¯ç©¿é DOM æ¿æ¢ã 209 $(document).off('click.announcement') 210 .on('click.announcement', `#announcementList .${msg_arch_item_class}`, function () { 211 const id = $(this).data('announcementId'); 212 if (!id) return; 213 addReadId('announcement', id); 214 $(this).addClass('is-read').find(`.${ad_notice_dot_class}`).remove(); 215 // 宿¶å·æ°æªè¯»æ° 216 refreshUnread('announcement', 217 $(`#announcementList .${msg_arch_item_class}`).map(function () { 218 return { id: $(this).data('announcementId') }; 219 }).get() 220 ); 221 }); 222 // ç¹å»å¹¿åæ¸ é¤çº¢ç¹å¹¶å·æ°æªè¯»æ° 223 // å§æç»å®å° documentï¼PJAX å±é¨å·æ°ä¼æ¢æ #msg-arch-banner-container èç¹ï¼ 224 // ç´æ¥ç»å¨ç¼åç $adList ä¸ä¼éæ§èç¹å¤±æï¼ä» document å§æå¯ç©¿é DOM æ¿æ¢ã 225 $(document).off('click.ad') 226 .on('click.ad', `#${ad_list_Id} a`, function () { 227 const id = $(this).data('read_id'); 228 if (!id) return; 229 addReadId('ad', id); 230 $(this).find(`.${ad_notice_dot_class}`).remove(); 231 refreshUnread('ad', 232 $(`#${ad_list_Id} a`).map(function () { 233 return { id: $(this).data('read_id') }; 234 }).get() 235 ); 236 }); 237 238 // 渲æå¹¿å 239 var lastAds = []; 240 const renderAds = (list) => { 241 // æ¯æ¬¡æ¸²æé½éæ°æ¥è¯¢å®¹å¨ï¼ä¸»é¢ç¨ PJAX åå±é¨å·æ°ï¼#wrap å ç容å¨ä¼è¢«æ¢ææ°èç¹ï¼ 242 // 模å级ç¼åç $adList 伿åå·²è±ç¦»ææ¡£çæ§èç¹ï¼å¯¼è´ html()/removeClass æå¨çä¸è§çèç¹ä¸ã 243 const $ad = $(`#${ad_list_Id}`); 244 if (!list.length) return renderEmpty($ad, 'ææ å¹¿å'); 245 var shown = list.slice(0, 1); 246 lastAds = shown; 247 pruneReadIds('ad', shown.map(function (a) { return a.id; })); 248 if (IS_FIRST_VISIT && shown.length) addReadId('ad', shown[0].id); // 馿¬¡åºçº¿åï¼æ¾å¨ $ad æ£æ¥åï¼é¦é¡µæ 广åå¡ä¹è¦çæï¼ 249 if ($ad.length) { 250 $ad.html(list.map((it) => { 251 const img = assetUrl(it.img_url || it.resource_url || it.thumb || it.image); 252 const link = it.link_url || it.url || it.url_config || it.ads_code || ''; 253 const read = isRead('ad', it.id); 254 return ` 255 <a href="${esc(safeUrl(link))}" class="tjtagmanager" 256 data-event="ad_click" 257 data-page_key="${esc(it?.page_key || '')}" 258 data-page_name="${esc(it?.page_name || '')}" 259 data-ad_slot_key="${esc(position)}" 260 data-ad_slot_name="${esc(position_name)}" 261 data-ad_id="${esc(it?.ads_code || '')}" 262 data-creative_id="${esc(it?.id || '')}" 263 data-read_id="${esc(it?.id || '')}" 264 data-ad_type="${esc(it?.ad_type)}" 265 target="_blank" 266 rel="sponsored nofollow"> 267 <img src="/usr/themes/Mirages/css/7.10.0/img-placeholder.png?v=1" z-image-loader-url="${esc(img)}" alt="${esc(it?.title || '')}">
268 <span class="msg-arch-banner__adtag" aria-hidden="true">广å</span> 269 ${read ? '' : `<span class="${ad_notice_dot_class}" aria-hidden="true"></span>`} 270 </a>`; 271 }).join('')); 272 $ad.removeClass('hidden'); 273 } 274 pruneReadIds('ad', list.map(it => it.id)); 275 refreshUnread('ad', list); 276 }; 277 278 // å ¬åï¼POST /api/im/announcementsï¼å页å¨è·³è½¬ï¼æ page æåï¼æ´é¡µæ¿æ¢æ¸²æï¼ 279 const loadAnnouncements = async (page) => { 280 if (annState.loading) return; // é²éå¤è¯·æ± 281 if (typeof page === 'number' && page > 0) annState.page = page; 282 annState.loading = true; 283 284 setAnnouncementsHTML(ANN_LOADING_HTML); // loading å ä½ 285 286 try { 287 const data = await TJIM.http({ 288 url: '/api/im/announcements', 289 method: 'POST', 290 data: { page: annState.page, limit: PAGE_LIMIT, publish_to: 'WEB' }, 291 }); 292 console.log('[demo] å ¬å dataï¼', data); // è°è¯ï¼ç¡®è®¤è¿åç»æ / list è·¯å¾ 293 const list = Array.isArray(data?.list) ? data.list : []; 294 295 // å ¼å®¹å¤ç§å段å读åå½å页 / æ»æ¡æ° / æ»é¡µæ° 296 annState.total = Number(data?.total ?? data?.total_count ?? data?.count ?? 0) || 0; 297 annState.page = Number(data?.page ?? data?.current_page ?? annState.page) || annState.page; 298 let totalPage = Number(data?.total_page ?? data?.total_pages ?? data?.totalPage ?? data?.last_page ?? 0) || 0; 299 if (!totalPage) { // æ¥å£æªç´æ¥ç»æ»é¡µæ°æ¶ææ»æ¡æ°æ¨ç®ï¼åéåä¸ºææ¬é¡µæ¯å¦æ»¡é¡µä¼°ç® 300 totalPage = annState.total ? Math.ceil(annState.total / PAGE_LIMIT) 301 : (list.length < PAGE_LIMIT ? annState.page : annState.page + 1); 302 } 303 annState.totalPage = Math.max(1, totalPage); 304 if (annState.page > annState.totalPage) annState.page = annState.totalPage; // é²è¶ç 305 annState.items = list; 306 307 if (!list.length) setAnnouncementsHTML(annEmptyHTML('ææ å ¬å')); 308 else renderAnnouncements(list); 309 310 renderPager(); 311 refreshUnread('announcement', list); 312 } catch (err) { 313 console.warn('[demo] å ¬å请æ±å¤±è´¥ï¼', err); 314 setAnnouncementsHTML(annEmptyHTML(`å ¬å请æ±å¤±è´¥ï¼${esc(err?.message || err)}`)); 315 renderPager(); 316 } finally { 317 annState.loading = false; 318 } 319 }; 320 321 // âââââââââ å页å¨ï¼ä¸ä¸é¡µ / 跳转(å½å/æ»é¡µ) / ä¸ä¸é¡µï¼ï¼æ ·å¼å¤ç¨ä¸»é¢ .page-nav.page-nav-ajax âââââââââ 322 const PAGER_ID = 'announcementPager'; 323 // å页å¨å®¹å¨ï¼ç´§è·å ¬åå表ä¹åï¼ä¸åå¨åå建 324 const getPagerBox = () => { 325 if (!announcementList) return null; 326 let box = document.getElementById(PAGER_ID); 327 if (!box) { 328 box = document.createElement('div'); 329 box.id = PAGER_ID; 330 box.className = 'page-nav page-nav-ajax'; 331 announcementList.insertAdjacentElement('afterend', box); 332 } 333 return box; 334 }; 335 // 渲æå页å¨ï¼æ æ°æ®æä» ä¸é¡µæ¶éè 336 const renderPager = () => { 337 const box = getPagerBox(); 338 if (!box) return; 339 const { page, totalPage, items } = annState; 340 if (totalPage <= 1 || items.length === 0) { 341 box.innerHTML = ''; 342 box.classList.add('hidden'); 343 return; 344 } 345 box.classList.remove('hidden'); 346 // 第ä¸é¡µä¸æ¾ç¤ºãä¸ä¸é¡µãï¼æåä¸é¡µä¸æ¾ç¤ºãä¸ä¸é¡µã 347 const prevHTML = page > 1 348 ? `<li class="prev"><a href="javascript:void(0);" data-page="${page - 1}">ä¸ä¸é¡µ</a></li>` 349 : ''; 350 const nextHTML = page < totalPage 351 ? `<li class="next"><a href="javascript:void(0);" data-page="${page + 1}">ä¸ä¸é¡µ</a></li>` 352 : ''; 353 box.innerHTML = ` 354 <div class="page-jump"> 355 <div id="pageForm">
356 <span class="page-info">${page}/${totalPage}</span> 357 <input type="number" id="pageNum" min="1" max="${totalPage}" placeholder="${page}"> 358 <button id="submitBtn" type="button">跳转</button> 359 </div> 360 </div> 361 <ul class="page-navigator"> 362 ${prevHTML} 363 <li><span></span></li> 364 ${nextHTML} 365 </ul>`; 366 }; 367 // è·³å°æå®é¡µï¼è¾¹çä¿æ¤ + 翻页ååå°å表顶é¨ï¼ 368 const goAnnouncementPage = (n) => { 369 if (annState.loading) return; 370 let page = parseInt(n, 10) || 1; 371 if (page < 1) page = 1; 372 if (page > annState.totalPage) page = annState.totalPage; 373 if (page === annState.page) return; // å页ä¸éå¤è¯·æ± 374 loadAnnouncements(page).then(() => { 375 announcementList?.scrollIntoView({ behavior: 'smooth', block: 'start' }); 376 }); 377 }; 378 // å页å¨äºä»¶ï¼å§æå° documentï¼ç©¿é PJAX å±é¨å·æ°ï¼ 379 $(document).off('click.annPager') 380 .on('click.annPager', `#${PAGER_ID} .prev a`, function (e) { 381 e.preventDefault(); 382 if ($(this).closest('li').hasClass('disabled')) return; 383 goAnnouncementPage($(this).data('page')); 384 }) 385 .on('click.annPager', `#${PAGER_ID} .next a`, function (e) { 386 e.preventDefault(); 387 if ($(this).closest('li').hasClass('disabled')) return; 388 goAnnouncementPage($(this).data('page')); 389 }) 390 .on('click.annPager', `#${PAGER_ID} #submitBtn`, function (e) { 391 e.preventDefault(); 392 goAnnouncementPage($(this).closest('.page-jump').find('#pageNum').val()); 393 }); 394 // 跳转è¾å ¥æ¡å车 395 $(document).off('keydown.annPager') 396 .on('keydown.annPager', `#${PAGER_ID} #pageNum`, function (e) { 397 if (e.key === 'Enter' || e.keyCode === 13) { 398 e.preventDefault(); 399 goAnnouncementPage($(this).val()); 400 } 401 }); 402 403 // 广åï¼POST /api/im/ads 404 const loadAds = async () => { 405 // renderEmpty($adList, 'å è½½ä¸â¦'); 406 try { 407 let data = await TJIM.http({ 408 url: '/api/im/ads', 409 method: 'POST', 410 data: { page: 1, limit: 20, publish_to: 'WEB' }, // ä¸å¡åæ°ï¼token/oauth å ¬åèªå¨è¡¥å ¨ 411 }); 412 console.log('[demo] 广åï¼', data); 413 position_name = data?.position_name || ''; 414 position = data?.position || ''; 415 renderAds(Array.isArray(data?.list) ? data.list : []); 416 } catch (err) { 417 console.warn('[demo] 广å请æ±å¤±è´¥ï¼', err); 418 // renderEmpty($adList, `广å请æ±å¤±è´¥ï¼${err?.message || err}`); 419 } 420 }; 421 422 loadAnnouncements(1); // é¦å±æå第ä¸é¡µ + 渲æåé¡µå¨ 423 424 loadAds(); // 广å 425 426 // å è½½ææ°çææ¬æ¶æ¯ 427 const loadLatestAnnouncement = (() => { 428 const queue = []; // å¾ æ¾ç¤ºéå
429 let isShowing = false; // æ¯å¦æ£å¨æ¾ç¤º 430 let timeId = null; 431 432 const showNext = () => { 433 if (queue.length === 0) { 434 isShowing = false; 435 return; 436 } 437 isShowing = true; 438 439 const message = queue.shift(); 440 const $bar = $(".home-announce-bar"); 441 const $text = $bar.find(".home-announce-text"); 442 443 let content = {}; 444 try { content = JSON.parse(message?.content) || {}; } 445 catch { content = {}; } 446 447 if (!$bar.length) { isShowing = false; return; } 448 449 $text.html(esc(content?.title || 'ç³»ç»æ¶æ¯')); 450 if (content?.type === AD_NOTIFY) { 451 const nz = (v) => v == null ? '' : v; 452 if (!isInternalLink(content?.link)) { 453 $bar.attr('href', safeUrl(content?.link)); 454 $bar.attr('target', '_blank'); 455 $bar.attr('rel', 'nofollow noopener noreferrer'); 456 $bar.attr('data-event', 'ad_click'); 457 $bar.attr('data-ad_type', nz(content.ad_type)); 458 $bar.attr('data-ad_slot_key', nz(content.position)); 459 $bar.attr('data-ad_slot_name', nz(content.position_name)); 460 $bar.attr('data-ad_id', nz(content.ads_code)); 461 $bar.attr('data-page_name', "imæ¨éå ¬å"); 462 $bar.attr('data-page_key', "im_ad_notify"); 463 $bar.addClass('tjtagmanager'); 464 } else { 465 $bar.removeAttr('target').removeAttr('rel') 466 } 467 } else { 468 $bar.attr('href', MSG_CENTER_URL); 469 } 470 $bar.removeClass('hidden'); 471 472 clearTimeout(timeId); 473 timeId = setTimeout(() => { 474 $bar.addClass('hidden'); 475 // å½åè¿æ¡æ»¡ 10sï¼é´éä¸ä¸åæ¾ä¸ä¸æ¡ï¼å¯é 300ms 让éèå¨ç»èµ°å®ï¼ 476 setTimeout(showNext, 300); 477 }, 10 * 1000); 478 }; 479 $(`.${avatar_dot_class_name}`).removeClass('hidden'); 480 // 对å¤çå ¥é彿° 481 return (message) => { 482 queue.push(message); 483 if (!isShowing) showNext(); // 空é²å°±ç«å³å¼å§ï¼å¦åæéç 484 }; 485 })(); 486 487 // ç«å 龿¥ï¼ç¸å¯¹è·¯å¾æååï¼å½å页æå¼ï¼ç«å¤æ°çªå£æå¼ 488 function isInternalLink(url) { 489 if (!url) return true; 490 try { return new URL(url, location.href).hostname === location.hostname; } 491 catch (e) { return true; } 492 } 493 494 // è·¨ tab 忥ï¼å«ç tab è¿æ¶æ¯ä¸å¿æ¸ äºæªè¯»/æ äºå·²è¯»ï¼æ¬ tab 红ç¹åæ¥ç 495 window.addEventListener('storage', function (e) { 496 if (e.key === BC_KEY) syncDots(); 497 if (e.key === READ_KEY) { refreshUnread('announcement', annState.items); refreshUnread('ad', lastAds); } 498 }); 499 500 501 // æ¶å°å¹¿æ â å ¥éè½®æ + 红ç¹ç«å»äº® + éæå ¬å/广åã 502 // 红ç¹ä¸è½ä¾èµæ¥å£ï¼åå°ãæ¨éãæ¯çº¯ socket 广æä¸è½åºï¼å ¬å/å¹¿åæ¥å£æ¥ä¸å°ï¼ï¼ 503 // æä»¥å¹¿ææ¬èº«è®¡ä¸æ¡æ¬å°æªè¯»ï¼BC_KEYï¼ï¼è¿æ¶æ¯ä¸å¿æ¸ é¶ï¼è½åºå 容ä»ç±éæè®¡æ°ã 504 window.addEventListener('TJIM_SYSTEM_BROADCAST', ({ detail: { count, message } }) => { 505 console.log('[demo] æ¶å°å¹¿æï¼æªè¯»ç´¯è®¡ï¼', count, message); 506 loadLatestAnnouncement(message); 507 if (!announcementList) { // 人å¨å ¬å详æ 页åä¸è®¡ï¼éæç´æ¥å±ç¤ºå¹¶æ 已读
508 localStorage.setItem(BC_KEY, String(broadcastUnread() + 1)); 509 syncDots(); // ä¸çæ¥å£ï¼ç«å»ç¹äº® 510 } 511 if (!annState.loading) { // 卿åä¸åè·³è¿ï¼å¨éè¯·æ±æ¿å°çå·²æ¯æ°æ°æ® 512 loadAnnouncements(1); // æ¶å°æ°å¹¿æï¼åå°ç¬¬ä¸é¡µæåææ°å ¬å 513 } 514 loadAds(); 515 }); 516 517})(window,document);
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.