在这个老哥的自定义头https://www.nodeseek.com/post-516869-1 Komari应用哪吒v1主题的流量进度条代码实现,基础进行修改。
增加了右下角显示访问者IP 服务商 浏览器等信息,并能根据页面亮色,暗色主题变换
供小白使用 设置 站点 自定义头 “De鸡窝”及个人配置请自己修改。
留个备份

<script>(function() {  // 配置  var CONFIG = {    interval: 60000,    apiUrl: '/api/rpc2',    trafficTolerance: 0.10  };  // 注入样式  var style = document.createElement('style');  style.textContent = `    .server-footer-name>div:first-child{visibility:hidden!important}    .server-footer-theme{display:none!important}    /* 自定义描述样式 - 绿色70%透明度 */    .custom-desc {      color: rgba(34, 197, 94, 0.7) !important;    }    /* 访客信息面板样式 - 自动跟随页面主题 */    #visitor-info-panel {      position: fixed;      bottom: 20px;      right: 20px;      border-radius: 12px;      padding: 16px;      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;      font-size: 12px;      line-height: 1.4;      z-index: 9999;      backdrop-filter: blur(10px);      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);      min-width: 220px;      max-width: 280px;      transition: all 0.3s ease;      opacity: 0.9;      border: 1px solid rgba(226, 232, 240, 0.8);      background: rgba(255, 255, 255, 0.95);      color: #1e293b;    }        /* 暗色主题样式 */    .dark-theme #visitor-info-panel,    body.dark #visitor-info-panel,    html[data-theme="dark"] #visitor-info-panel,    html.dark #visitor-info-panel,    .dark #visitor-info-panel,    [data-mode="dark"] #visitor-info-panel,    [class*="dark"] #visitor-info-panel,    [class*="dark-mode"] #visitor-info-panel,    #visitor-info-panel.dark-mode {      background: rgba(15, 23, 42, 0.95);      border-color: rgba(148, 163, 184, 0.3);      color: #f1f5f9;      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);    }        /* 亮色主题样式 - 确保优先级 */    .light-theme #visitor-info-panel,    body.light #visitor-info-panel,    html[data-theme="light"] #visitor-info-panel,    html.light #visitor-info-panel,    .light #visitor-info-panel,    [data-mode="light"] #visitor-info-panel,    [class*="light"] #visitor-info-panel,    [class*="light-mode"] #visitor-info-panel,    #visitor-info-panel.light-mode {      background: rgba(255, 255, 255, 0.95) !important;      border-color: rgba(226, 232, 240, 0.8) !important;      color: #1e293b !important;      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15) !important;    }        /* 跟随系统主题的媒体查询 */    @media (prefers-color-scheme: dark) {      :root:not(.light-theme):not(.light) #visitor-info-panel,      body:not(.light-theme):not(.light) #visitor-info-panel,      html:not(.light-theme):not(.light) #visitor-info-panel,      :not([data-theme="light"]) #visitor-info-panel {        background: rgba(15, 23, 42, 0.95);        border-color: rgba(148, 163, 184, 0.3);        color: #f1f5f9;        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);      }    }        #visitor-info-panel:hover {      opacity: 1;      transform: translateY(-2px);      box-shadow: 0 12px 40px rgba(0, 0, 0, 0.2);    }        .dark-theme #visitor-info-panel:hover,    body.dark #visitor-info-panel:hover,    html[data-theme="dark"] #visitor-info-panel:hover,    html.dark #visitor-info-panel:hover {      box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);    }        .visitor-header {      display: flex;      justify-content: space-between;      align-items: center;      margin-bottom: 12px;      padding-bottom: 8px;      border-bottom: 1px solid rgba(226, 232, 240, 0.6);    }        .dark-theme .visitor-header,    body.dark .visitor-header,    html[data-theme="dark"] .visitor-header,    html.dark .visitor-header {      border-bottom-color: rgba(148, 163, 184, 0.3);    }        .visitor-title {      font-weight: 600;      font-size: 14px;      display: flex;      align-items: center;      gap: 6px;      color: #3b82f6;    }        .dark-theme .visitor-title,    body.dark .visitor-title,    html[data-theme="dark"] .visitor-title,    html.dark .visitor-title {      color: #60a5fa;    }        .visitor-title i {      font-size: 16px;    }        .visitor-toggle {      background: none;      border: none;      cursor: pointer;      font-size: 18px;      padding: 2px 6px;      border-radius: 4px;      transition: all 0.2s;      color: #64748b;    }        .dark-theme .visitor-toggle,    body.dark .visitor-toggle,    html[data-theme="dark"] .visitor-toggle,    html.dark .visitor-toggle {      color: #94a3b8;    }        .visitor-toggle:hover {      background: rgba(59, 130, 246, 0.1);      color: #3b82f6;    }        .dark-theme .visitor-toggle:hover,    body.dark .visitor-toggle:hover,    html[data-theme="dark"] .visitor-toggle:hover,    html.dark .visitor-toggle:hover {      background: rgba(96, 165, 250, 0.1);      color: #60a5fa;    }        .visitor-content {      display: block;    }        .visitor-content.hidden {      display: none;    }        .visitor-row {      display: flex;      justify-content: space-between;      margin-bottom: 8px;      align-items: flex-start;    }        .visitor-label {      min-width: 60px;      font-weight: 500;      color: #64748b;    }        .dark-theme .visitor-label,    body.dark .visitor-label,    html[data-theme="dark"] .visitor-label,    html.dark .visitor-label {      color: #94a3b8;    }        .visitor-value {      text-align: right;      flex: 1;      word-break: break-word;      max-width: 150px;      color: #334155;    }        .dark-theme .visitor-value,    body.dark .visitor-value,    html[data-theme="dark"] .visitor-value,    html.dark .visitor-value {      color: #e2e8f0;    }        /* 特定值的颜色 */    .visitor-ip {      font-weight: 600;      font-family: 'Monaco', 'Consolas', monospace;      font-size: 11px;      color: #059669;    }        .dark-theme .visitor-ip,    body.dark .visitor-ip,    html[data-theme="dark"] .visitor-ip,    html.dark .visitor-ip {      color: #34d399;    }        .visitor-isp {      color: #d97706;    }        .dark-theme .visitor-isp,    body.dark .visitor-isp,    html[data-theme="dark"] .visitor-isp,    html.dark .visitor-isp {      color: #fbbf24;    }        .visitor-location {      color: #7c3aed;    }        .dark-theme .visitor-location,    body.dark .visitor-location,    html[data-theme="dark"] .visitor-location,    html.dark .visitor-location {      color: #a78bfa;    }        .visitor-browser {      color: #db2777;    }        .dark-theme .visitor-browser,    body.dark .visitor-browser,    html[data-theme="dark"] .visitor-browser,    html.dark .visitor-browser {      color: #f472b6;    }        .visitor-os {      color: #1d4ed8;    }        .dark-theme .visitor-os,    body.dark .visitor-os,    html[data-theme="dark"] .visitor-os,    html.dark .visitor-os {      color: #60a5fa;    }        .visitor-refresh-btn {      margin-top: 12px;      padding: 6px 12px;      background: linear-gradient(135deg, #3b82f6, #8b5cf6);      color: white;      border: none;      border-radius: 6px;      font-size: 11px;      font-weight: 500;      cursor: pointer;      width: 100%;      transition: all 0.2s;    }        .visitor-refresh-btn:hover {      background: linear-gradient(135deg, #2563eb, #7c3aed);      transform: translateY(-1px);    }        .visitor-refresh-btn:active {      transform: translateY(0);    }        .visitor-copy-btn {      background: rgba(100, 116, 139, 0.15);      border: none;      cursor: pointer;      padding: 2px 6px;      border-radius: 4px;      margin-left: 4px;      font-size: 10px;      transition: all 0.2s;      color: #64748b;    }        .dark-theme .visitor-copy-btn,    body.dark .visitor-copy-btn,    html[data-theme="dark"] .visitor-copy-btn,    html.dark .visitor-copy-btn {      background: rgba(148, 163, 184, 0.2);      color: #94a3b8;    }        .visitor-copy-btn:hover {      background: rgba(59, 130, 246, 0.2);      color: #3b82f6;    }        .dark-theme .visitor-copy-btn:hover,    body.dark .visitor-copy-btn:hover,    html[data-theme="dark"] .visitor-copy-btn:hover,    html.dark .visitor-copy-btn:hover {      background: rgba(96, 165, 250, 0.2);      color: #60a5fa;    }  `;  document.head.appendChild(style);  // 全局配置  window.CustomDesc = "De 鸡窝";  window.ShowNetTransfer = true;  window.DisableAnimatedMan = true;  window.FixedTopServerName = true;  // 工具函数  var UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'];  var UNIT_MAP = { KIB: 1024, MIB: 1048576, GIB: 1073741824, TIB: 1099511627776 };  var CYCLE_MAP = { 30: '月', 92: '季', 184: '半年', 365: '年', 730: '二年', 1095: '三年', 1825: '五年' };  function formatBytes(bytes) {    if (!bytes) return { value: '0', unit: 'B' };    var i = Math.floor(Math.log(bytes) / Math.log(1024));    return { value: (bytes / Math.pow(1024, i)).toFixed(2), unit: UNITS[i] };  }  function formatTime(s) {    if (!s) return 'N/A';    try {      return new Date(s).toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', hour: '2-digit', minute: '2-digit', second: '2-digit' });    } catch (e) { return 'N/A'; }  }  function getCycleText(c) {    if (!c || c <= 0) return c === -1 || c === 0 ? '一次性' : '年';    for (var days in CYCLE_MAP) {      if (Math.abs(c - days) <= 3) return CYCLE_MAP[days];    }    var y = Math.round(c / 365);    return y >= 1 && y <= 10 ? y + '年' : '年';  }  function calcResetDays(expiredAt) {    if (!expiredAt) return 'N/A';    try {      var day = new Date(expiredAt).getDate(), now = new Date();      var reset = new Date(now.getFullYear(), now.getMonth(), day);      if (reset <= now) reset.setMonth(reset.getMonth() + 1);      return Math.ceil((reset - now) / 86400000) + '日';    } catch (e) { return 'N/A'; }  }  function parseTraffic(text) {    var m = text.match(/([\d.]+)\s*(GiB|MiB|TiB|KiB)/i);    return m ? parseFloat(m[1]) * (UNIT_MAP[m[2].toUpperCase()] || 1) : null;  }  function normName(n) { return n.toUpperCase().replace(/[^A-Z0-9-]/g, ''); }  function getColor(p) { return 'hsl(' + ((100 - p) * 1.4) + ',70%,50%)'; }  // 渲染器  var barCache = new Map();  function createBar(d) {    var uf = formatBytes(d.used), tf = formatBytes(d.limit);    var pc = Math.min(100, d.used / d.limit * 100).toFixed(2);    var div = document.createElement('div');    div.className = 'space-y-1.5 traffic-bar';    div.dataset.uuid = d.uuid;    div.style.width = '100%';    div.innerHTML =       '<div class="flex items-center justify-between">' +        '<div class="flex items-baseline gap-1">' +          '<span class="text-[10px] font-medium text-neutral-800 dark:text-neutral-200 used-val">' + uf.value + '</span>' +          '<span class="text-[10px] font-medium text-neutral-800 dark:text-neutral-200 used-unit">' + uf.unit + '</span>' +          '<span class="text-[10px] text-neutral-500 dark:text-neutral-400">/ ' + tf.value + ' ' + tf.unit + '</span>' +        '</div>' +        '<div class="text-[10px] font-medium text-neutral-600 dark:text-neutral-300 percent-val">' + pc + '%</div>' +      '</div>' +      '<div class="relative h-1.5" style="width:100%">' +        '<div class="absolute inset-0 bg-neutral-100 dark:bg-neutral-800 rounded-full"></div>' +        '<div class="absolute inset-0 rounded-full transition-all duration-300 progress-bar" style="width:' + pc + '%;background-color:' + getColor(parseFloat(pc)) + '"></div>' +      '</div>' +      '<div class="flex items-center justify-between">' +        '<div class="text-[10px] text-neutral-500 dark:text-neutral-400 update-time">更新于: ' + formatTime(d.next_update) + '</div>' +        '<div class="text-[10px] text-neutral-500 dark:text-neutral-400 reset-date">距离流量重置: ' + d.reset_date + '</div>' +      '</div>';    return div;  }  function updateBar(el, d) {    var uf = formatBytes(d.used);    var pc = Math.min(100, d.used / d.limit * 100).toFixed(2);    el.querySelector('.used-val').textContent = uf.value;    el.querySelector('.used-unit').textContent = uf.unit;    el.querySelector('.percent-val').textContent = pc + '%';    el.querySelector('.update-time').textContent = '更新于: ' + formatTime(d.next_update);    el.querySelector('.reset-date').textContent = '距离流量重置: ' + d.reset_date;    var bar = el.querySelector('.progress-bar');    bar.style.width = pc + '%';    bar.style.backgroundColor = getColor(parseFloat(pc));  }  function fixPrice(container, d) {    if (!d.price || d.billing_cycle == null) return;    var text = '价格: ' + (d.currency || '$') + d.price + '/' + getCycleText(d.billing_cycle);    var ps = container.getElementsByTagName('p');    for (var i = 0; i < ps.length; i++) {      if (ps[i].textContent.indexOf('价格:') !== -1) ps[i].textContent = text;    }  }  function getCardTraffic(container) {    var divs = container.querySelectorAll('.inline-flex');    var up = null, down = null;    for (var i = 0; i < divs.length; i++) {      var t = divs[i].textContent;      if (t.indexOf('上传') !== -1) up = parseTraffic(t);      else if (t.indexOf('下载') !== -1) down = parseTraffic(t);    }    return up && down ? { up: up, down: down } : null;  }  function matchCard(candidates, d) {    if (candidates.length === 1) return candidates[0];    var best = null, bestDiff = Infinity;    for (var i = 0; i < candidates.length; i++) {      var traffic = getCardTraffic(candidates[i].closest('div'));      if (!traffic) continue;      var upDiff = Math.abs(traffic.up - d.net_total_up) / Math.max(d.net_total_up, 1);      var downDiff = Math.abs(traffic.down - d.net_total_down) / Math.max(d.net_total_down, 1);      if (upDiff < CONFIG.trafficTolerance && downDiff < CONFIG.trafficTolerance) {        var avg = (upDiff + downDiff) / 2;        if (avg < bestDiff) { best = candidates[i]; bestDiff = avg; }      }    }    return best || candidates[0];  }  // 应用自定义描述样式  function applyCustomDescStyle() {    var elements = document.querySelectorAll('*');    for (var i = 0; i < elements.length; i++) {      var el = elements[i];      if (el.textContent && el.textContent.trim() === 'De 鸡窝') {        el.classList.add('custom-desc');      }    }  }  function render(list) {    var sections = document.querySelectorAll('section.grid.items-center.gap-2');    var used = new Set();    // 应用自定义描述样式    applyCustomDescStyle();    for (var i = 0; i < list.length; i++) {      var d = list[i];      if (!d.limit || !d.used) continue;      var norm = normName(d.name);      var candidates = [];      for (var j = 0; j < sections.length; j++) {        if (used.has(sections[j])) continue;        var nameEl = sections[j].querySelector('p');        if (nameEl && normName(nameEl.textContent.trim()) === norm) candidates.push(sections[j]);      }      if (!candidates.length) continue;      var target = matchCard(candidates, d);      used.add(target);      var container = target.closest('div');      fixPrice(container, d);      // 找到上传下载的 section 作为插入点      var uploadDownloadSec = null;      var allSections = container.querySelectorAll('section.flex.items-center.w-full.justify-between.gap-1');      for (var k = 0; k < allSections.length; k++) {        if (allSections[k].textContent.indexOf('上传:') !== -1 && allSections[k].textContent.indexOf('下载:') !== -1) {          uploadDownloadSec = allSections[k];          break;        }      }            if (!uploadDownloadSec) continue;      // 检查是否已存在进度条(防止重复)      var existingBar = container.querySelector('.traffic-bar[data-uuid="' + d.uuid + '"]');            if (existingBar) {        // 已存在,只更新数据        updateBar(existingBar, d);      } else {        // 不存在,创建新的        var bar = createBar(d);        uploadDownloadSec.parentNode.insertBefore(bar, uploadDownloadSec.nextSibling);        barCache.set(d.uuid, bar);      }    }  }  // 数据管理  var dataCache = null, loading = false;  function rpc(method, params) {    return fetch(CONFIG.apiUrl, {      method: 'POST',      headers: { 'Content-Type': 'application/json' },      credentials: 'include',      body: JSON.stringify({ id: Date.now(), method: method, params: params || {}, jsonrpc: '2.0' })    }).then(function(r) { return r.json(); });  }  function calcUsed(up, down, type) {    if (type === 'max') return Math.max(up, down);    if (type === 'min') return Math.min(up, down);    if (type === 'up') return up;    if (type === 'down') return down;    return up + down;  }  function fetchData(cb) {    var now = Date.now();    if (dataCache && now - dataCache.time < CONFIG.interval) { cb(dataCache.data); return; }    if (loading) return;    loading = true;    rpc('common:getNodes').then(function(res) {      var nodes = Object.values(res.result || res.data || {});      return Promise.all(nodes.map(function(n) {        return rpc('common:getNodeRecentStatus', { uuid: n.uuid, limit: 1 }).then(function(sr) {          var rec = ((sr.result || sr.data || {}).records || [])[0] || {};          var up = rec.net_total_up || 0, down = rec.net_total_down || 0;          return {            name: n.name, uuid: n.uuid,            limit: n.traffic_limit || 0,            used: calcUsed(up, down, n.traffic_limit_type || 'sum'),            next_update: rec.time,            reset_date: calcResetDays(n.expired_at),            price: n.price, currency: n.currency, billing_cycle: n.billing_cycle,            net_total_up: up, net_total_down: down          };        }).catch(function() {          return {            name: n.name, uuid: n.uuid, limit: n.traffic_limit || 0, used: 0,            next_update: null, reset_date: calcResetDays(n.expired_at),            price: n.price, currency: n.currency, billing_cycle: n.billing_cycle,            net_total_up: 0, net_total_down: 0          };        });      }));    }).then(function(data) {      dataCache = { time: now, data: data };      cb(data);    }).finally(function() { loading = false; });  }  // 访客信息功能  var visitorData = null;  function detectBrowser() {    var ua = navigator.userAgent;    var browser = "未知浏览器";        if (ua.indexOf("Edg") > -1) browser = "Microsoft Edge";    else if (ua.indexOf("Chrome") > -1) browser = "Google Chrome";    else if (ua.indexOf("Firefox") > -1) browser = "Mozilla Firefox";    else if (ua.indexOf("Safari") > -1) browser = "Apple Safari";    else if (ua.indexOf("Opera") > -1) browser = "Opera";    else if (ua.indexOf("Trident") > -1 || ua.indexOf("MSIE") > -1) browser = "Internet Explorer";        return browser;  }  function detectOS() {    var ua = navigator.userAgent;    var os = "未知系统";        if (ua.indexOf("Win") > -1) {      if (ua.indexOf("Windows NT 10.0") > -1) os = "Windows 10/11";      else if (ua.indexOf("Windows NT 6.3") > -1) os = "Windows 8.1";      else if (ua.indexOf("Windows NT 6.2") > -1) os = "Windows 8";      else if (ua.indexOf("Windows NT 6.1") > -1) os = "Windows 7";      else if (ua.indexOf("Windows NT 6.0") > -1) os = "Windows Vista";      else os = "Windows";    } else if (ua.indexOf("Mac") > -1) {      os = "macOS";    } else if (ua.indexOf("Linux") > -1) {      os = "Linux";    } else if (ua.indexOf("Android") > -1) {      os = "Android";    } else if (ua.indexOf("iOS") > -1 || ua.indexOf("iPhone") > -1 || ua.indexOf("iPad") > -1) {      os = "iOS";    }        return os;  }  function detectScreen() {    return window.screen.width + "×" + window.screen.height;  }  function getLocalTime() {    return new Date().toLocaleString('zh-CN');  }  function copyToClipboard(text) {    navigator.clipboard.writeText(text).then(function() {      var originalText = event.target.textContent;      event.target.textContent = '已复制';      setTimeout(function() {        event.target.textContent = originalText;      }, 2000);    }).catch(function(err) {      console.error('复制失败:', err);    });  }  async function fetchVisitorInfo() {    try {      // 尝试从多个IP API获取信息      const ipApis = [        'https://api.ipify.org?format=json',        'https://api64.ipify.org?format=json',        'https://ipapi.co/json/'      ];            let ipData = null;      for (const api of ipApis) {        try {          const response = await fetch(api);          if (response.ok) {            ipData = await response.json();            break;          }        } catch (e) {          continue;        }      }            // 如果获取失败,使用备用方案      if (!ipData || !ipData.ip) {        return {          ip: '获取中...',          isp: '未知',          city: '未知',          region: '未知',          country: '未知',          timezone: '未知'        };      }            // 使用ipapi.co获取详细信息      if (ipData && ipData.ip) {        try {          const detailResponse = await fetch(`https://ipapi.co/${ipData.ip}/json/`);          if (detailResponse.ok) {            const details = await detailResponse.json();            return {              ip: ipData.ip,              isp: details.org || details.asn || '未知',              city: details.city || '未知',              region: details.region || '未知',              country: details.country_name || '未知',              timezone: details.timezone || '未知'            };          }        } catch (e) {          // 如果详细API失败,至少返回IP        }      }            return {        ip: ipData.ip || '获取中...',        isp: '未知',        city: '未知',        region: '未知',        country: '未知',        timezone: '未知'      };          } catch (error) {      console.error('获取访客信息失败:', error);      return {        ip: '获取失败',        isp: '未知',        city: '未知',        region: '未知',        country: '未知',        timezone: '未知'      };    }  }  // 检测当前页面主题  function detectPageTheme() {    // 常见主题类名检测    var root = document.documentElement;    var body = document.body;        // 检查常见暗色主题类名    var darkClasses = ['dark', 'dark-mode', 'dark-theme', 'darkMode', 'theme-dark'];    var lightClasses = ['light', 'light-mode', 'light-theme', 'lightMode', 'theme-light'];        // 检查 body 和 html 的类名    for (var i = 0; i < darkClasses.length; i++) {      if (body.classList.contains(darkClasses[i]) || root.classList.contains(darkClasses[i])) {        return 'dark';      }      if (body.classList.contains(lightClasses[i]) || root.classList.contains(lightClasses[i])) {        return 'light';      }    }        // 检查 data-theme 属性    var rootTheme = root.getAttribute('data-theme');    var bodyTheme = body.getAttribute('data-theme');        if (rootTheme === 'dark' || bodyTheme === 'dark') return 'dark';    if (rootTheme === 'light' || bodyTheme === 'light') return 'light';        // 检查 data-mode 属性    var rootMode = root.getAttribute('data-mode');    var bodyMode = body.getAttribute('data-mode');        if (rootMode === 'dark' || bodyMode === 'dark') return 'dark';    if (rootMode === 'light' || bodyMode === 'light') return 'light';        // 检查是否有 dark 相关的类名(部分匹配)    var allClasses = body.className + ' ' + root.className;    if (allClasses.includes('dark') && !allClasses.includes('light')) return 'dark';    if (allClasses.includes('light') && !allClasses.includes('dark')) return 'light';        // 检查系统主题偏好    if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {      return 'dark';    }        return 'light'; // 默认为亮色主题  }  // 观察页面主题变化  function observeThemeChanges() {    var observer = new MutationObserver(function(mutations) {      mutations.forEach(function(mutation) {        if (mutation.type === 'attributes' &&             (mutation.attributeName === 'class' || mutation.attributeName === 'data-theme' || mutation.attributeName === 'data-mode')) {          // 主题可能已更改,但我们依赖CSS选择器自动处理        }      });    });        // 观察html和body元素    observer.observe(document.documentElement, {       attributes: true,       attributeFilter: ['class', 'data-theme', 'data-mode']     });        observer.observe(document.body, {       attributes: true,       attributeFilter: ['class', 'data-theme', 'data-mode']     });        // 监听系统主题变化    if (window.matchMedia) {      var darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');      darkModeMediaQuery.addListener(function(e) {        // 系统主题变化时,如果页面没有明确设置主题,则跟随系统        if (!document.documentElement.classList.contains('dark') &&             !document.documentElement.classList.contains('light') &&            !document.body.classList.contains('dark') &&             !document.body.classList.contains('light') &&            !document.documentElement.getAttribute('data-theme') &&            !document.body.getAttribute('data-theme')) {          // 我们的CSS媒体查询会自动处理        }      });    }  }  function createVisitorPanel() {    var panel = document.createElement('div');    panel.id = 'visitor-info-panel';        panel.innerHTML = `      <div class="visitor-header">        <div class="visitor-title">          <span>🌐 访客信息</span>        </div>        <button class="visitor-toggle" title="隐藏/显示">−</button>      </div>      <div class="visitor-content">        <div class="visitor-row">          <span class="visitor-label">IP地址:</span>          <span class="visitor-value visitor-ip">获取中...</span>          <button class="visitor-copy-btn" onclick="copyToClipboard(this.previousElementSibling.textContent)">复制</button>        </div>        <div class="visitor-row">          <span class="visitor-label">网络服务商:</span>          <span class="visitor-value visitor-isp">获取中...</span>        </div>        <div class="visitor-row">          <span class="visitor-label">位置:</span>          <span class="visitor-value visitor-location">获取中...</span>        </div>        <div class="visitor-row">          <span class="visitor-label">浏览器:</span>          <span class="visitor-value visitor-browser">${detectBrowser()}</span>        </div>        <div class="visitor-row">          <span class="visitor-label">操作系统:</span>          <span class="visitor-value visitor-os">${detectOS()}</span>        </div>        <div class="visitor-row">          <span class="visitor-label">屏幕分辨率:</span>          <span class="visitor-value">${detectScreen()}</span>        </div>        <div class="visitor-row">          <span class="visitor-label">本地时间:</span>          <span class="visitor-value">${getLocalTime()}</span>        </div>        <button class="visitor-refresh-btn" onclick="refreshVisitorInfo()">          🔄 刷新信息        </button>      </div>    `;        document.body.appendChild(panel);        // 添加显示/隐藏事件    panel.querySelector('.visitor-toggle').addEventListener('click', function() {      var content = panel.querySelector('.visitor-content');      content.classList.toggle('hidden');      this.textContent = content.classList.contains('hidden') ? '+' : '−';    });        // 添加拖动功能    var isDragging = false;    var offsetX, offsetY;        panel.addEventListener('mousedown', function(e) {      if (e.target.closest('.visitor-toggle') ||           e.target.closest('.visitor-copy-btn') ||           e.target.closest('.visitor-refresh-btn')) {        return;      }      isDragging = true;      offsetX = e.clientX - panel.getBoundingClientRect().left;      offsetY = e.clientY - panel.getBoundingClientRect().top;      panel.style.cursor = 'grabbing';    });        document.addEventListener('mousemove', function(e) {      if (!isDragging) return;      e.preventDefault();      var x = e.clientX - offsetX;      var y = e.clientY - offsetY;            // 限制在窗口范围内      var maxX = window.innerWidth - panel.offsetWidth;      var maxY = window.innerHeight - panel.offsetHeight;      x = Math.max(0, Math.min(x, maxX));      y = Math.max(0, Math.min(y, maxY));            panel.style.left = x + 'px';      panel.style.right = 'auto';      panel.style.bottom = y + 'px';      panel.style.top = 'auto';    });        document.addEventListener('mouseup', function() {      isDragging = false;      panel.style.cursor = 'default';    });        // 开始观察主题变化    observeThemeChanges();        // 更新访客信息    refreshVisitorInfo();  }  async function refreshVisitorInfo() {    var panel = document.getElementById('visitor-info-panel');    if (!panel) return;        // 显示加载状态    var ipElement = panel.querySelector('.visitor-ip');    ipElement.textContent = '获取中...';    panel.querySelector('.visitor-isp').textContent = '获取中...';    panel.querySelector('.visitor-location').textContent = '获取中...';        try {      const visitorInfo = await fetchVisitorInfo();      visitorData = visitorInfo;            // 更新显示      panel.querySelector('.visitor-ip').textContent = visitorInfo.ip;      panel.querySelector('.visitor-isp').textContent = visitorInfo.isp;      panel.querySelector('.visitor-location').textContent = visitorInfo.city + ', ' + visitorInfo.region;            // 修正信息显示错误:操作系统和屏幕分辨率显示反了      panel.querySelectorAll('.visitor-row')[4].querySelector('.visitor-value').textContent = detectOS();      panel.querySelectorAll('.visitor-row')[5].querySelector('.visitor-value').textContent = detectScreen();          } catch (error) {      console.error('刷新访客信息失败:', error);      panel.querySelector('.visitor-ip').textContent = '获取失败';      panel.querySelector('.visitor-isp').textContent = '网络异常';      panel.querySelector('.visitor-location').textContent = '请检查网络连接';    }  }  // 将函数暴露到全局作用域  window.refreshVisitorInfo = refreshVisitorInfo;  window.copyToClipboard = copyToClipboard;  // 观察器 - 优化防止频繁触发  var observer = null, timer = null, renderPending = false;  function update() { fetchData(render); }  function scheduleRender() {    if (renderPending) return;    renderPending = true;    setTimeout(function() {      renderPending = false;      update();    }, 300);  }  function init() {    if (observer) return;        observer = new MutationObserver(scheduleRender);    observer.observe(document.body, { childList: true, subtree: true });        update();    timer = setInterval(update, CONFIG.interval);        // 创建访客信息面板    setTimeout(createVisitorPanel, 1000);        // 每分钟更新一次本地时间    setInterval(function() {      var panel = document.getElementById('visitor-info-panel');      if (panel && !panel.querySelector('.visitor-content').classList.contains('hidden')) {        var timeElement = panel.querySelectorAll('.visitor-row')[6].querySelector('.visitor-value');        if (timeElement) {          timeElement.textContent = getLocalTime();        }      }    }, 60000);        window.addEventListener('beforeunload', function() {      if (observer) observer.disconnect();      if (timer) clearInterval(timer);      barCache.clear();    }, { once: true });  }  // 启动  function tryInit() {    if (document.querySelector('section.grid[class*="grid-cols-"]')) {      requestAnimationFrame(init);    } else {      setTimeout(tryInit, 250);    }  }  if (document.readyState === 'loading') {    document.addEventListener('DOMContentLoaded', tryInit, { once: true });  } else {    tryInit();  }})();</script>