(function () { try { if (window.__QQLH_HOME_POPUP_LOADED) return; window.__QQLH_HOME_POPUP_LOADED = true; var API = '/plugin/QQLianghao/Api/popupData'; function now() { return Date.now ? Date.now() : new Date().getTime(); } function escapeHtml(s) { s = s == null ? '' : String(s); return s .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } function nl2br(s) { return escapeHtml(s).replace(/\r\n|\r|\n/g, '
'); } function getDayKey() { var d = new Date(); var y = d.getFullYear(); var m = ('0' + (d.getMonth() + 1)).slice(-2); var da = ('0' + d.getDate()).slice(-2); return y + '-' + m + '-' + da; } function storageGet(k) { try { return localStorage.getItem(k); } catch (e) { return null; } } function storageSet(k, v) { try { localStorage.setItem(k, v); } catch (e) {} } function shouldShow(cfg) { if (!cfg || !cfg.enable) return false; // 频率控制: // every = 每次进入页面都弹 // daily = 每天弹一次 // once = 永久仅一次 var key = 'qqlh_home_popup_' + String(cfg.cache_ver || '0'); var freq = cfg.frequency || 'every'; if (freq === 'every') return true; if (freq === 'once') return !storageGet(key); if (freq === 'daily') { var today = getDayKey(); return storageGet(key) !== today; } return true; } // 只在“域名主页”展示(严禁在文章/公告/新闻/FAQ 等页面弹出) // 兼容:history 模式 + hash 模式。 // 规则: // 1) 只要 URL(含 hash)里包含 /article /news /notice /faq /help /question /settle 等关键词,一律不弹 // 2) 允许的首页: // - history: pathname 为 / 或 /index 或 /index.html // - hash: pathname 为 / 或 /index*,且 hash 为 '' '#/' '#/index' '#/home' '#/shop' '#/goods' function hasArticleLikeDom() { try { // 文章详情/公告/新闻等页面通常带 Vant 顶部导航,标题常见为“文章详情/公告详情”等 var t = document.querySelector('.van-nav-bar__title'); if (t) { var s = String(t.textContent || '').toLowerCase(); if (s.indexOf('文章') !== -1 || s.indexOf('公告') !== -1 || s.indexOf('新闻') !== -1 || s.indexOf('常见') !== -1 || s.indexOf('问题') !== -1) { return true; } } // 文章页结构常见:.container .header .category var cat = document.querySelector('.container .header .category'); if (cat) { var c = String(cat.textContent || '').toLowerCase(); if (c.indexOf('公告') !== -1 || c.indexOf('新闻') !== -1 || c.indexOf('常见') !== -1 || c.indexOf('问题') !== -1 || c.indexOf('结算') !== -1) { return true; } } } catch (e) {} return false; } function isHomePage() { try { var href = String(location.href || '').toLowerCase(); // DOM 级黑名单:只要识别到文章/公告页结构,直接不弹 if (hasArticleLikeDom()) return false; // 黑名单:文章、公告、新闻、常见问题、结算公告 等 var deny = [ '/article', '#/article', '/news', '#/news', '/notice', '#/notice', '/announcement', '#/announcement', '/faq', '#/faq', '/help', '#/help', '/question', '#/question', '/settle', '#/settle', '/settlement', '#/settlement', '/gonggao', '#/gonggao' ]; for (var i = 0; i < deny.length; i++) { if (href.indexOf(deny[i]) !== -1) return false; } var pth = (location.pathname || '/').toLowerCase(); // history 模式:只允许根路径(注意:如果站点是 /article/8 这种真实路径,这里会直接 return false) if (!(pth === '/' || pth === '' || pth === '/index' || pth === '/index.html')) return false; var h = (location.hash || '').toLowerCase(); if (!h) return true; // 归一化 hash h = h.replace(/^#/, ''); if (h === '' || h === '/') return true; // 允许的“首页路由”集合(很多主题首页是 shop/goods 列表页) var allow = ['/index', '/home', '/shop', '/goods', '/']; for (var j = 0; j < allow.length; j++) { if (h === allow[j]) return true; } // 其他 hash 路由一律不弹 return false; } catch (e) { return false; } } function markShown(cfg) { if (!cfg) return; var key = 'qqlh_home_popup_' + String(cfg.cache_ver || '0'); var freq = cfg.frequency || 'every'; if (freq === 'once') storageSet(key, '1'); if (freq === 'daily') storageSet(key, getDayKey()); } function hidePageLoading() { try { var el = document.querySelector('.page-loading'); if (el) el.style.display = 'none'; } catch (e) {} } function injectStyle() { if (document.getElementById('qqlh_home_popup_style')) return; var style = document.createElement('style'); style.id = 'qqlh_home_popup_style'; style.textContent = '.qqlh-popup-overlay,.qqlh-popup-overlay *{box-sizing:border-box}' + '.qqlh-popup-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5);display:flex;justify-content:center;align-items:center;z-index:999999;opacity:0;visibility:hidden;transition:all .25s ease}' + '.qqlh-popup-overlay.active{opacity:1;visibility:visible}' + '.qqlh-popup-container{width:92%;max-width:520px;background:#fff;border-radius:16px;overflow:hidden;position:relative;transform:translateY(16px);transition:transform .25s ease;box-shadow:0 10px 25px rgba(0,0,0,.22)}' + '.qqlh-popup-overlay.active .qqlh-popup-container{transform:translateY(0)}' + '.qqlh-popup-close{position:absolute;top:14px;right:14px;width:32px;height:32px;border-radius:50%;background:rgba(255,255,255,.88);display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:10;font-size:22px;line-height:1;color:#333;transition:all .2s ease}' + '.qqlh-popup-close:hover{background:#fff;transform:scale(1.08)}' + '.qqlh-popup-image{width:100%;height:200px;background:#f3f4f6;object-fit:cover;display:block}' + '.qqlh-popup-content{padding:22px 20px 10px 20px;text-align:center}' + '.qqlh-popup-title{font-size:18px;font-weight:700;margin:0 0 10px 0;color:#111}' + '.qqlh-popup-message{font-size:14px;color:#555;line-height:1.7;margin:0}' + // Buttons: desktop 3 per row; mobile 2 per row. Use !important to defeat theme overrides. '.qqlh-popup-overlay .qqlh-popup-buttons{display:grid !important;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;padding:16px 20px 20px 20px;align-items:stretch}' + '.qqlh-popup-overlay .qqlh-popup-btn{display:block;min-width:0;width:100% !important;max-width:100% !important;padding:12px 10px;border:none;border-radius:12px;font-size:15px;cursor:pointer;transition:all .18s ease;box-shadow:0 6px 16px rgba(0,0,0,.08);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}' + '.qqlh-popup-btn:hover{transform:translateY(-1px)}' + '.qqlh-popup-btn:active{transform:translateY(0)}' + '.qqlh-popup-overlay .qqlh-popup-btn.primary{background:linear-gradient(135deg,#34d399,#10b981);color:#fff}' + '.qqlh-popup-overlay .qqlh-popup-btn.secondary{background:linear-gradient(135deg,#60a5fa,#3b82f6);color:#fff}' + // Close button fixed: always spans full row '.qqlh-popup-overlay .qqlh-popup-btn.close{background:#f3f4f6;color:#333;box-shadow:none;grid-column:1/-1}' + '@media(max-width:480px){.qqlh-popup-image{height:180px}.qqlh-popup-overlay .qqlh-popup-buttons{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:14px 14px 18px 14px}.qqlh-popup-overlay .qqlh-popup-btn{font-size:13px;padding:10px 6px}}'; document.head.appendChild(style); } function buildAndShow(cfg) { injectStyle(); hidePageLoading(); // overlay var overlay = document.createElement('div'); overlay.className = 'qqlh-popup-overlay'; var container = document.createElement('div'); container.className = 'qqlh-popup-container'; var closeX = document.createElement('div'); closeX.className = 'qqlh-popup-close'; closeX.innerHTML = '×'; // image var img = document.createElement('img'); img.className = 'qqlh-popup-image'; if (cfg.image_url) { img.src = cfg.image_url; } else { // 没有图就隐藏 img.style.display = 'none'; } var content = document.createElement('div'); content.className = 'qqlh-popup-content'; var title = document.createElement('div'); title.className = 'qqlh-popup-title'; title.innerHTML = escapeHtml(cfg.title || ''); if (cfg.title_color) { try { title.style.setProperty('color', String(cfg.title_color), 'important'); } catch(e) { title.style.color = String(cfg.title_color); } } var msg = document.createElement('div'); msg.className = 'qqlh-popup-message'; msg.innerHTML = nl2br(cfg.message || ''); if (cfg.message_color) { try { msg.style.setProperty('color', String(cfg.message_color), 'important'); } catch(e) { msg.style.color = String(cfg.message_color); } } content.appendChild(title); content.appendChild(msg); var buttonsWrap = document.createElement('div'); buttonsWrap.className = 'qqlh-popup-buttons'; // 用 inline + !important 强压主题全局样式,避免被主题覆盖成单列 try { buttonsWrap.style.setProperty('display','grid','important'); buttonsWrap.style.setProperty('align-items','stretch','important'); buttonsWrap.style.setProperty('grid-auto-flow','row','important'); } catch (e) {} var btns = cfg.buttons || []; if (!Array.isArray(btns)) btns = []; function close() { try { overlay.classList.remove('active'); setTimeout(function () { try { overlay.remove(); } catch (e) { if (overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay); } }, 250); } catch (e) {} } // 可变按钮:最多 8 个 for (var i = 0; i < btns.length; i++) { var b = btns[i] || {}; if (!b.text || !b.link) continue; var btn = document.createElement('button'); btn.className = 'qqlh-popup-btn ' + (i === 0 ? 'primary' : 'secondary'); btn.textContent = String(b.text); // 如果后台配置了自定义颜色,则直接使用自定义色(不走默认渐变) if (b.bg) { try { btn.style.setProperty('background', String(b.bg), 'important'); } catch(e) { btn.style.background = String(b.bg); } } if (b.color) { try { btn.style.setProperty('color', String(b.color), 'important'); } catch(e) { btn.style.color = String(b.color); } } (function (link) { btn.addEventListener('click', function () { try { window.location.href = link; } catch (e) {} close(); }); })(String(b.link)); buttonsWrap.appendChild(btn); } // 固定关闭按钮 var btnClose = document.createElement('button'); btnClose.className = 'qqlh-popup-btn close'; btnClose.textContent = '关闭'; btnClose.addEventListener('click', close); buttonsWrap.appendChild(btnClose); closeX.addEventListener('click', close); overlay.addEventListener('click', function (e) { if (e && e.target === overlay) close(); }); document.addEventListener('keydown', function (e) { if (e && e.key === 'Escape') close(); }); container.appendChild(closeX); container.appendChild(img); container.appendChild(content); container.appendChild(buttonsWrap); overlay.appendChild(container); document.body.appendChild(overlay); function applyCols(){ try { var isMobile = window.matchMedia && window.matchMedia('(max-width: 480px)').matches; buttonsWrap.style.setProperty('grid-template-columns', isMobile ? 'repeat(2, minmax(0, 1fr))' : 'repeat(3, minmax(0, 1fr))', 'important'); buttonsWrap.style.setProperty('gap', isMobile ? '8px' : '10px', 'important'); } catch (e) {} } // 按当前屏幕宽度设置列数 applyCols(); try { window.addEventListener('resize', applyCols); } catch(e) {} setTimeout(function () { overlay.classList.add('active'); }, 50); markShown(cfg); } function removePopupIfAny() { try { var ex = document.querySelector('.qqlh-popup-overlay'); if (ex) { try { ex.remove(); } catch (e) { if (ex.parentNode) ex.parentNode.removeChild(ex); } } } catch (e) {} } function run() { try { // 只在首页展示,文章/公告/新闻等页面一律不弹;如已存在弹窗则立刻移除 if (!isHomePage()) { removePopupIfAny(); return; } fetch(API + '?v=' + now(), { method: 'GET', credentials: 'include', cache: 'no-store' }) .then(function (r) { return r.json(); }) .then(function (res) { var cfg = (res && res.data) ? res.data : null; if (!cfg) return; if (!shouldShow(cfg)) return; buildAndShow(cfg); }) .catch(function () {}); } catch (e) {} } // SPA 路由切换时也要生效:进入文章页立即移除,不要再弹 function attachRouteWatch() { try { var last = String(location.href || ''); function tick() { var cur = String(location.href || ''); if (cur === last) return; last = cur; // 只要切到非首页(含文章页),立即移除并不再弹 if (!isHomePage()) { removePopupIfAny(); return; } // 切回首页且满足频率时再弹 fetch(API + '?v=' + now(), { method: 'GET', credentials: 'include', cache: 'no-store' }) .then(function (r) { return r.json(); }) .then(function (res) { var cfg = (res && res.data) ? res.data : null; if (!cfg) return; if (!shouldShow(cfg)) return; buildAndShow(cfg); }) .catch(function () {}); } window.addEventListener('hashchange', tick); window.addEventListener('popstate', tick); // 某些框架不会触发 popstate/hashchange,这里加一个轻量轮询兜底 setInterval(tick, 800); } catch (e) {} } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function(){ run(); attachRouteWatch(); }); } else { run(); attachRouteWatch(); } } catch (e) {} })();