<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>阿尔比恩战役报告 - Albion Battles</title>
<link rel="icon" href="http://zhanbao.albion.ufo110.net/east/css/favicon.png">
<style>
  :root {
    --bg:#0f131a; --surface:#1a1d24; --surface2:#292d33; --border:#3c3f43;
    --text:#e9ebf0; --muted:#a4a9b3; --muted2:#6a6f76;
    --accent:#34c3ff; --accent-d:#169de0;
    --pink:#e02983; --green:#29e09d; --cyan:#29cee0; --amber:#ffd152;
  }
  * { box-sizing:border-box; }
  html,body { margin:0; padding:0; }
  body {
    background:var(--bg); color:var(--text); font-size:14px; line-height:1.5;
    font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue","PingFang SC","Microsoft YaHei",sans-serif;
    -webkit-font-smoothing:antialiased; overflow-x:hidden;
  }
  a { color:var(--accent); text-decoration:none; }
  a:hover { color:var(--accent-d); }

  .hero {
    background-color:#12161d;
    background-image:url("http://zhanbao.albion.ufo110.net/east/css/bg.jpg");
    background-size:cover; background-position:center;
    border-bottom:1px solid var(--border); padding:22px 0 18px;
  }
  .hero-in { max-width:1200px; margin:0 auto; padding:0 16px; }
  .hero h1 { margin:0 0 4px; font-size:22px; font-weight:500; letter-spacing:.5px;
             text-shadow:0 1px 6px rgba(0,0,0,.75); }
  .hero .sub { margin:0 0 14px; font-size:12.5px; color:var(--muted);
               text-shadow:0 1px 4px rgba(0,0,0,.8); }
  .bar { display:flex; flex-wrap:wrap; gap:8px; align-items:center; }
  .seg { display:inline-flex; border:1px solid var(--border); border-radius:6px; overflow:hidden;
         background:rgba(15,19,26,.72); }
  .seg button { border:0; border-radius:0; background:transparent; }
  .seg button + button { border-left:1px solid var(--border); }
  button, select, input {
    font:inherit; font-size:13px; color:var(--text);
    background:rgba(15,19,26,.72); border:1px solid var(--border);
    border-radius:6px; padding:6px 12px; outline:none;
  }
  button { cursor:pointer; transition:all .15s; }
  button:hover { border-color:var(--muted2); color:#fff; }
  button.on { background:var(--accent-d); border-color:var(--accent); color:#fff; }
  select { padding-right:6px; }
  input { width:200px; }
  input::placeholder { color:var(--muted2); }
  input:focus, select:focus { border-color:var(--accent); }
  .live { display:inline-flex; align-items:center; gap:6px; font-size:12px; color:var(--muted); margin-left:auto; }
  .dot { width:7px; height:7px; border-radius:50%; background:var(--green); }
  .dot.off { background:var(--muted2); }

  .wrap { max-width:1200px; margin:0 auto; padding:16px 16px 60px; }
  .msg { font-size:13px; color:var(--muted); padding:14px 2px; }
  .err { color:#f7635c; }
  .spin { display:inline-block; width:13px; height:13px; border:2px solid rgba(255,255,255,.2);
          border-top-color:var(--accent); border-radius:50%; animation:sp .8s linear infinite; vertical-align:-2px; }
  @keyframes sp { to { transform:rotate(360deg); } }

  .card { background:var(--surface); border:1px solid var(--border); border-left:3px solid var(--cyan);
          border-radius:6px; padding:11px 14px; margin-bottom:9px; transition:all .18s; }
  .card:hover { border-color:var(--muted2); background:#1e222a; }
  .card.sort-fame { border-left-color:var(--green); }
  .card.sort-kills { border-left-color:var(--pink); }
  .card.open { border-color:var(--accent); }
  .row1 { display:flex; flex-wrap:wrap; gap:12px; align-items:baseline; cursor:pointer; }
  .time { font-size:12.5px; color:var(--muted); min-width:118px; font-variant-numeric:tabular-nums; }
  .fame { font-size:15px; color:var(--green); font-variant-numeric:tabular-nums; }
  .kills { font-size:15px; color:var(--pink); font-variant-numeric:tabular-nums; }
  .pill { font-size:12px; color:var(--muted); background:var(--surface2); border:1px solid var(--border);
          padding:1px 9px; border-radius:10px; }
  .bid { font-size:11.5px; color:var(--muted2); font-variant-numeric:tabular-nums; }
  .guilds { font-size:12.5px; color:var(--muted); margin-top:7px; word-break:break-all; }
  .guilds a { cursor:pointer; }
  .caret { margin-left:auto; font-size:11px; color:var(--muted2); }
  .detail { margin-top:10px; }

  /* 详情：概览 */
  .kv { display:flex; flex-wrap:wrap; gap:16px; font-size:12.5px; color:var(--muted);
        border-top:1px solid var(--border); padding-top:10px; }
  .kv b { color:var(--text); font-weight:400; }
  .sec-t { font-size:12.5px; color:var(--muted); margin:14px 0 7px; }
  .bars { display:flex; flex-direction:column; gap:5px; }
  .bar { display:flex; align-items:center; gap:10px; }
  .track { flex:0 0 62%; height:14px; background:rgba(255,255,255,.06); border-radius:4px; overflow:hidden; }
  .fill { height:14px; border-radius:4px; }
  .bar .lb { flex:1; font-size:12px; color:var(--muted); text-align:right;
             overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

  table { width:100%; border-collapse:collapse; font-size:12.5px; margin-top:8px; }
  th { text-align:left; font-weight:500; color:var(--muted); padding:7px 9px;
       background:var(--surface2); border-bottom:1px solid var(--border); white-space:nowrap; }
  td { padding:6px 9px; border-bottom:1px solid #2a2e35; color:var(--text); vertical-align:middle; }
  tbody tr:nth-child(even) { background:rgba(255,255,255,.02); }
  tbody tr:hover { background:rgba(52,195,255,.08); }
  td.num { text-align:right; font-variant-numeric:tabular-nums; }

  /* 击杀明细 */
  .kl { display:flex; flex-direction:column; gap:8px; }
  .krow { background:var(--bg); border:1px solid var(--border); border-radius:6px; padding:9px 11px; }
  .krow .kt { display:flex; flex-wrap:wrap; gap:10px; align-items:center; font-size:12.5px; }
  .krow .kt .ts { color:var(--muted2); font-variant-numeric:tabular-nums; }
  .krow .who { display:flex; flex-wrap:wrap; gap:26px; margin-top:8px; }
  .side { flex:1 1 320px; min-width:0; }
  .side .hd { display:flex; align-items:baseline; gap:8px; margin-bottom:6px; font-size:13px; }
  .side .nm { color:var(--text); }
  .side .gg { color:var(--muted); font-size:12px; }
  .side .ip { margin-left:auto; font-size:12px; color:var(--amber); font-variant-numeric:tabular-nums; }
  .gear { display:flex; flex-wrap:wrap; gap:4px; }
  .gear img { width:34px; height:34px; border-radius:4px; background:#20242b;
              border:1px solid var(--border); image-rendering:auto; }
  .vs { align-self:center; color:var(--pink); font-size:12px; padding:0 4px; }
  .empty { font-size:12px; color:var(--muted2); }

  .pager { display:flex; gap:8px; justify-content:center; align-items:center; margin-top:20px; }
  #pageInfo { font-size:12.5px; color:var(--muted); min-width:70px; text-align:center; }
  .foot { font-size:12px; color:var(--muted2); border-top:1px solid var(--border);
          margin-top:24px; padding-top:12px; line-height:1.8; }
  @media (max-width:700px) {
    input { width:100%; }
    .hero h1 { font-size:18px; }
    .time { min-width:100px; }
    .track { flex-basis:45%; }
    .live { margin-left:0; }
  }
</style>
</head>
<body>

<div class="hero">
  <div class="hero-in">
    <h1>阿尔比恩战役报告</h1>
    <p class="sub">Albion Battles · 数据源：官方 gameinfo 公开接口 · 装备图标来自 render.albiononline.com</p>
    <div class="bar">
      <div class="seg">
        <button class="srvBtn on" data-srv="sgp">亚服</button>
        <button class="srvBtn" data-srv="ams">欧服</button>
        <button class="srvBtn" data-srv="west">美服</button>
      </div>
      <div class="seg">
        <button class="sortBtn on" data-sort="recent">最新</button>
        <button class="sortBtn" data-sort="totalFame">声望最高</button>
        <button class="sortBtn" data-sort="totalKills">击杀最多</button>
      </div>
      <select id="minPlayers">
        <option value="0">全部战役</option>
        <option value="5">≥ 5 人</option>
        <option value="10" selected>≥ 10 人</option>
        <option value="20">≥ 20 人</option>
        <option value="50">≥ 50 人</option>
      </select>
      <input id="q" placeholder="搜玩家 / 公会名" autocomplete="off">
      <button id="btnSearch">搜索</button>
      <span class="live"><span class="dot" id="dot"></span><span id="liveTxt">自动刷新中</span></span>
    </div>
  </div>
</div>

<div class="wrap">
  <div id="list"></div>
  <div class="pager">
    <button id="prev">上一页</button>
    <span id="pageInfo"></span>
    <button id="next">下一页</button>
  </div>
  <div class="foot">
    本页调用同目录 api.php 转发官方接口并显示，更换服务器需一并部署 api.php。<br>
    列表为空时，请确认服务器可访问 gameinfo-sgp.albiononline.com，且 cache 目录可写。
  </div>
</div>

<script>
var API = 'api.php';
var RENDER = 'https://render.albiononline.com/v1/item/';
var SLOTS = ['MainHand','OffHand','Head','Armor','Shoes','Bag','Cape','Mount'];
var state = { server:'sgp', sort:'recent', offset:0, limit:20, minPlayers:10, guildId:'' };
var lastCount = 0, openId = null, timer = null;

function fmt(n) {
  n = n || 0;
  if (n >= 1000000) return (n / 1000000).toFixed(1) + 'M';
  if (n >= 1000) return (n / 1000).toFixed(1) + 'K';
  return String(n);
}
function t(s) {
  if (!s) return '-';
  var d = new Date(new Date(s).getTime() + 8 * 3600 * 1000);
  function p(n) { return (n < 10 ? '0' : '') + n; }
  return p(d.getUTCMonth() + 1) + '-' + p(d.getUTCDate()) + ' '
       + p(d.getUTCHours()) + ':' + p(d.getUTCMinutes()) + ':' + p(d.getUTCSeconds());
}
function dur(a, b) {
  if (!a || !b) return '-';
  var s = Math.round((new Date(b) - new Date(a)) / 1000);
  if (s < 60) return s + ' 秒';
  if (s < 3600) return Math.floor(s / 60) + ' 分 ' + (s % 60) + ' 秒';
  return Math.floor(s / 3600) + ' 时 ' + Math.floor(s % 3600 / 60) + ' 分';
}
function esc(s) {
  return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) {
    return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c];
  });
}
function itemImg(type, q) {
  if (!type) return '';
  return '<img loading="lazy" src="' + RENDER + encodeURIComponent(type) + '.png?quality=' + (q || 0)
       + '" title="' + esc(type) + '" alt="">';
}
function gearHtml(eq) {
  if (!eq) return '<span class="empty">无装备数据</span>';
  var h = '';
  for (var i = 0; i < SLOTS.length; i++) {
    var it = eq[SLOTS[i]];
    if (it && it.Type) h += itemImg(it.Type, it.Quality);
  }
  ['Potion','Food'].forEach(function (k) {
    var it = eq[k];
    if (it && it.Type) h += itemImg(it.Type, it.Quality);
  });
  return h || '<span class="empty">无装备数据</span>';
}
function guildList(players) {
  var seen = {}, out = [];
  for (var k in players) {
    var p = players[k];
    if (p.guildName && !seen[p.guildId]) { seen[p.guildId] = 1; out.push(p); }
  }
  return out.slice(0, 8);
}

function load(keepOpen) {
  var box = document.getElementById('list');
  if (!keepOpen) box.innerHTML = '<div class="msg"><span class="spin"></span> 正在拉取战役…</div>';
  var url = API + '?action=battles&server=' + state.server
          + '&limit=' + state.limit + '&offset=' + state.offset
          + '&sort=' + state.sort + '&minPlayers=' + state.minPlayers;
  if (state.guildId) url += '&guildId=' + encodeURIComponent(state.guildId);

  fetch(url).then(function (r) { return r.json(); }).then(function (data) {
    if (data && data.error) { box.innerHTML = '<div class="msg err">' + esc(data.error) + '</div>'; return; }
    var arr = Array.isArray(data) ? data : [];
    if (!arr.length) {
      box.innerHTML = '<div class="msg">没有符合条件的战役，试试放宽参战人数或换一个服务器。</div>';
      lastCount = 0;
      document.getElementById('pageInfo').textContent = '';
      return;
    }
    lastCount = arr.length;
    var cls = state.sort === 'totalFame' ? ' sort-fame' : (state.sort === 'totalKills' ? ' sort-kills' : '');
    var html = '';
    arr.forEach(function (b) {
      var players = b.players || {};
      var n = Object.keys(players).length;
      var guilds = guildList(players).map(function (p) {
        return '<a data-gid="' + esc(p.guildId) + '">' + esc(p.guildName) + '</a>';
      }).join(' · ');
      html += '<div class="card' + cls + '" data-id="' + b.id + '">'
        + '<div class="row1">'
        + '<span class="time">' + t(b.startTime) + '</span>'
        + '<span class="fame">' + fmt(b.totalFame) + ' 声望</span>'
        + '<span class="kills">' + (b.totalKills || 0) + ' 击杀</span>'
        + '<span class="pill">' + n + ' 人</span>'
        + '<span class="pill">' + dur(b.startTime, b.endTime) + '</span>'
        + '<span class="bid">#' + b.id + '</span>'
        + '<span class="caret">展开 ▾</span>'
        + '</div>'
        + (guilds ? '<div class="guilds">参战公会：' + guilds + '</div>' : '')
        + '<div class="detail" id="d' + b.id + '"></div>'
        + '</div>';
    });
    box.innerHTML = html;

    box.querySelectorAll('.row1').forEach(function (el) {
      el.onclick = function () { toggle(el.parentNode.getAttribute('data-id'), el.parentNode); };
    });
    box.querySelectorAll('.guilds a').forEach(function (el) {
      el.onclick = function (e) {
        e.stopPropagation();
        state.guildId = el.getAttribute('data-gid');
        state.offset = 0;
        load();
      };
    });
    document.getElementById('pageInfo').textContent = '第 ' + (Math.floor(state.offset / state.limit) + 1) + ' 页';
    if (openId) {
      var card = box.querySelector('.card[data-id="' + openId + '"]');
      if (card) { card.classList.add('open'); loadDetail(openId); }
    }
  }).catch(function (e) {
    box.innerHTML = '<div class="msg err">请求失败：' + esc(e.message) + '</div>';
  });
}

function toggle(id, card) {
  if (openId === String(id)) {
    var old = document.getElementById('d' + id);
    if (old) old.innerHTML = '';
    if (card) card.classList.remove('open');
    openId = null;
    return;
  }
  var prev = document.getElementById('d' + openId);
  if (prev) prev.innerHTML = '';
  document.querySelectorAll('.card.open').forEach(function (c) { c.classList.remove('open'); });
  openId = String(id);
  if (card) card.classList.add('open');
  loadDetail(id);
}

function loadDetail(id) {
  var box = document.getElementById('d' + id);
  if (!box) return;
  box.innerHTML = '<div class="msg"><span class="spin"></span> 正在分析战役…</div>';

  var a = fetch(API + '?action=battle&server=' + state.server + '&id=' + id).then(function (r) { return r.json(); });
  var b = fetch(API + '?action=battlekills&server=' + state.server + '&id=' + id + '&limit=51')
            .then(function (r) { return r.json(); }).catch(function () { return []; });

  Promise.all([a, b]).then(function (res) {
    var bt = res[0], evs = res[1];
    if (bt && bt.error) { box.innerHTML = '<div class="msg err">' + esc(bt.error) + '</div>'; return; }

    var arr = [];
    for (var k in (bt.players || {})) arr.push(bt.players[k]);
    var kills = arr.reduce(function (s, p) { return s + (p.kills || 0); }, 0);
    var deaths = arr.reduce(function (s, p) { return s + (p.deaths || 0); }, 0);

    var gm = {};
    arr.forEach(function (p) {
      var key = p.allianceName || p.guildName || 'Unalligned';
      if (!gm[key]) gm[key] = { name: key, players: 0, kills: 0, fame: 0 };
      gm[key].players++;
      gm[key].kills += (p.kills || 0);
      gm[key].fame += (p.killFame || 0);
    });
    var gs = [];
    for (var g in gm) gs.push(gm[g]);
    function top(key, n) { return gs.slice().sort(function (x, y) { return y[key] - x[key]; }).slice(0, n); }
    function barBlock(title, list, key, color) {
      if (!list.length) return '';
      var max = list[0][key] || 1;
      var rows = list.map(function (x) {
        var w = Math.max(3, Math.round(x[key] / max * 100));
        return '<div class="bar"><span class="track"><span class="fill" style="width:' + w
             + '%;background:' + color + '"></span></span>'
             + '<span class="lb">' + esc(x.name) + ' · ' + fmt(x[key]) + '</span></div>';
      }).join('');
      return '<div class="sec-t">' + title + '</div><div class="bars">' + rows + '</div>';
    }

    var rankRows = arr.slice().sort(function (x, y) { return (y.killFame || 0) - (x.killFame || 0); })
      .slice(0, 80).map(function (p) {
        return '<tr><td>' + esc(p.name) + '</td><td>' + esc(p.guildName || '-') + '</td>'
             + '<td>' + esc(p.allianceName || '-') + '</td>'
             + '<td class="num">' + (p.kills || 0) + '</td>'
             + '<td class="num">' + (p.deaths || 0) + '</td>'
             + '<td class="num">' + fmt(p.killFame) + '</td></tr>';
      }).join('');

    var evArr = Array.isArray(evs) ? evs : [];
    var kl = evArr.slice(0, 60).map(function (e) {
      var kk = e.Killer || {}, vv = e.Victim || {};
      var n = e.numberOfParticipants || 1;
      return '<div class="krow">'
        + '<div class="kt"><span class="ts">' + t(e.TimeStamp) + '</span>'
        + '<span class="pill">' + fmt(e.TotalVictimKillFame) + ' 名望掉落</span>'
        + (n > 1 ? '<span class="pill">' + n + ' 人围杀</span>' : '')
        + (e.KillArea ? '<span class="bid">' + esc(e.KillArea) + '</span>' : '')
        + '</div>'
        + '<div class="who">'
        + '<div class="side"><div class="hd"><span class="nm">' + esc(kk.Name || '-') + '</span>'
        + '<span class="gg">' + esc(kk.GuildName || '-') + '</span>'
        + '<span class="ip">IP ' + Math.round(kk.AverageItemPower || 0) + '</span></div>'
        + '<div class="gear">' + gearHtml(kk.Equipment) + '</div></div>'
        + '<span class="vs">击杀</span>'
        + '<div class="side"><div class="hd"><span class="nm">' + esc(vv.Name || '-') + '</span>'
        + '<span class="gg">' + esc(vv.GuildName || '-') + '</span>'
        + '<span class="ip">IP ' + Math.round(vv.AverageItemPower || 0) + '</span></div>'
        + '<div class="gear">' + gearHtml(vv.Equipment) + '</div></div>'
        + '</div></div>';
    }).join('');

    box.innerHTML = '<div class="kv">'
      + '<span>开始 <b>' + t(bt.startTime) + '</b></span>'
      + '<span>结束 <b>' + t(bt.endTime) + '</b></span>'
      + '<span>持续 <b>' + dur(bt.startTime, bt.endTime) + '</b></span>'
      + '<span>参战 <b>' + arr.length + '</b> 人</span>'
      + '<span>击杀 <b>' + kills + '</b></span>'
      + '<span>阵亡 <b>' + deaths + '</b></span>'
      + '<span>总声望 <b>' + fmt(bt.totalFame) + '</b></span>'
      + '<span>击杀记录 <b>' + evArr.length + '</b> 条</span>'
      + '</div>'
      + barBlock('参战人数排名', top('players', 5), 'players', 'linear-gradient(90deg,#1d7fa0,#29cee0)')
      + barBlock('击杀排名', top('kills', 5), 'kills', 'linear-gradient(90deg,#a01d5b,#e02983)')
      + barBlock('声望排名', top('fame', 5), 'fame', 'linear-gradient(90deg,#1a9c6c,#29e09d)')
      + '<div class="sec-t">击杀明细（双方装备 · IP）</div>'
      + '<div class="kl">' + (kl || '<div class="msg">该战役暂无击杀记录</div>') + '</div>'
      + (evArr.length > 60 ? '<div class="msg">击杀过多，仅显示前 60 条</div>' : '')
      + '<div class="sec-t">参战玩家（按击杀声望排序）</div>'
      + '<table><thead><tr><th>玩家</th><th>公会</th><th>联盟</th>'
      + '<th style="text-align:right">击杀</th><th style="text-align:right">阵亡</th>'
      + '<th style="text-align:right">击杀声望</th></tr></thead><tbody>' + rankRows + '</tbody></table>'
      + (arr.length > 80 ? '<div class="msg">仅显示前 80 人，共 ' + arr.length + ' 人</div>' : '');
  }).catch(function (e) {
    box.innerHTML = '<div class="msg err">加载详情失败：' + esc(e.message) + '</div>';
  });
}

// ---------- 自动刷新：15~20 秒随机，页面隐藏时暂停 ----------
function schedule() {
  if (timer) clearTimeout(timer);
  timer = setTimeout(function () {
    if (document.hidden) { schedule(); return; }
    load(true);
    schedule();
  }, 15000 + Math.floor(Math.random() * 5000));
}
document.addEventListener('visibilitychange', function () {
  var dot = document.getElementById('dot'), txt = document.getElementById('liveTxt');
  if (document.hidden) { dot.className = 'dot off'; txt.textContent = '已暂停'; }
  else { dot.className = 'dot'; txt.textContent = '自动刷新中'; load(true); schedule(); }
});

document.querySelectorAll('.srvBtn').forEach(function (btn) {
  btn.onclick = function () {
    document.querySelectorAll('.srvBtn').forEach(function (b) { b.classList.remove('on'); });
    btn.classList.add('on');
    state.server = btn.getAttribute('data-srv');
    state.offset = 0; state.guildId = ''; openId = null;
    load(); schedule();
  };
});
document.querySelectorAll('.sortBtn').forEach(function (btn) {
  btn.onclick = function () {
    document.querySelectorAll('.sortBtn').forEach(function (b) { b.classList.remove('on'); });
    btn.classList.add('on');
    state.sort = btn.getAttribute('data-sort');
    state.offset = 0; openId = null;
    load(); schedule();
  };
});
document.getElementById('minPlayers').onchange = function () {
  state.minPlayers = parseInt(this.value, 10) || 0;
  state.offset = 0; openId = null;
  load(); schedule();
};
document.getElementById('prev').onclick = function () {
  state.offset = Math.max(0, state.offset - state.limit);
  openId = null; load(); schedule();
};
document.getElementById('next').onclick = function () {
  if (lastCount > 0) { state.offset += state.limit; openId = null; load(); schedule(); }
};
document.getElementById('q').addEventListener('keydown', function (e) {
  if (e.key === 'Enter') document.getElementById('btnSearch').click();
});
document.getElementById('btnSearch').onclick = function () {
  var q = document.getElementById('q').value.trim();
  if (!q) { state.guildId = ''; state.offset = 0; load(); return; }
  var box = document.getElementById('list');
  box.innerHTML = '<div class="msg"><span class="spin"></span> 搜索中…</div>';
  fetch(API + '?action=search&server=' + state.server + '&q=' + encodeURIComponent(q))
    .then(function (r) { return r.json(); })
    .then(function (d) {
      var g = (d && d.guilds) ? d.guilds.slice(0, 12) : [];
      var p = (d && d.players) ? d.players.slice(0, 12) : [];
      if (!g.length && !p.length) {
        box.innerHTML = '<div class="msg">没有找到「' + esc(q) + '」</div>';
        return;
      }
      var html = '<div class="card"><div style="margin-bottom:6px;color:var(--muted)">搜索结果</div>';
      g.forEach(function (x) {
        html += '<div class="guilds"><a data-gid="' + esc(x.Id) + '">' + esc(x.Name) + '</a>'
             + ' <span style="color:var(--muted2)">（公会 · 击杀声望 ' + fmt(x.KillFame) + '）</span></div>';
      });
      p.forEach(function (x) {
        html += '<div class="guilds">' + esc(x.Name)
             + ' <span style="color:var(--muted2)">（玩家）</span></div>';
      });
      box.innerHTML = html + '</div>';
      box.querySelectorAll('.guilds a').forEach(function (el) {
        el.onclick = function () {
          state.guildId = el.getAttribute('data-gid');
          state.offset = 0;
          load();
        };
      });
    });
};

load();
schedule();
</script>
</body>
</html>
