{"id":31,"date":"2026-04-16T06:03:50","date_gmt":"2026-04-15T22:03:50","guid":{"rendered":"http:\/\/www.longlegmxd.com\/?page_id=31"},"modified":"2026-04-20T21:12:32","modified_gmt":"2026-04-20T13:12:32","slug":"%e5%9c%b0%e5%9b%be%e5%9b%be%e9%89%b4","status":"publish","type":"post","link":"https:\/\/www.longlegmxd.com\/index.php\/2026\/04\/16\/%e5%9c%b0%e5%9b%be%e5%9b%be%e9%89%b4\/","title":{"rendered":"\u5730\u56fe\u56fe\u9274"},"content":{"rendered":"\n<div style=\"max-width:1200px;margin:auto;padding:20px;\">\n  <h2 style=\"margin-bottom:20px;\">\u5730\u56fe\u56fe\u9274<\/h2>\n\n  <input \n    id=\"search-map\" \n    placeholder=\"\u641c\u7d22\u5730\u56fe...\" \n    style=\"\n      width:100%;\n      padding:12px;\n      border-radius:8px;\n      border:1px solid #ddd;\n      margin-bottom:20px;\n      font-size:16px;\n    \"\n  >\n\n  <div id=\"map-list\"><\/div>\n<\/div>\n\n<script>\nlet mapsData = [];\nlet monstersData = [];\nlet mapMeta = {};\nlet openMap = null;\n\nfunction padMapId(id) {\n  return String(id).padStart(9, '0');\n}\n\nfunction getMapImg(map) {\n  if (!map.id && map.id !== 0) return \"\";\n  return `\/data\/maps\/${padMapId(map.id)}.img.png`;\n}\n\nfunction getMonsterImg(monster) {\n  return monster.thumbnail ? `\/data\/${monster.thumbnail}` : \"\";\n}\n\nfunction extractMaps(monsters) {\n  const mapDict = {};\n  monsters.forEach(monster => {\n    (monster.maps || []).forEach(map => {\n      if (!mapDict[map.name]) {\n        mapDict[map.name] = map;\n      }\n    });\n  });\n  return Object.values(mapDict);\n}\n\nfunction goMonster(id) {\n  window.location.href = `\/index.php\/\u602a\u7269\u56fe\u9274\/?open=${id}`;\n}\n\nfunction goMapByName(name) {\n  if (!name) return;\n  openMap = name;\n  renderFilteredMaps();\n  setTimeout(() => {\n    const cards = document.querySelectorAll(\"[data-map-name]\");\n    cards.forEach(card => {\n      if (card.dataset.mapName === name) {\n        card.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n      }\n    });\n  }, 100);\n}\n\nfunction renderMaps(data) {\n  const container = document.getElementById('map-list');\n  container.innerHTML = '';\n\n  if (!data.length) {\n    container.innerHTML = '<div>\u6ca1\u6709\u627e\u5230\u5730\u56fe<\/div>';\n    return;\n  }\n\n  data.forEach(map => {\n    const meta = mapMeta[map.name] || {};\n\n    const card = document.createElement('div');\n    card.dataset.mapName = map.name;\n    card.style.border = '1px solid #ddd';\n    card.style.borderRadius = '10px';\n    card.style.marginBottom = '12px';\n    card.style.background = '#fff';\n    card.style.cursor = 'pointer';\n    card.style.padding = '14px';\n\n    card.innerHTML = `\n      <div style=\"font-size:18px;font-weight:700;\">\n        ${map.name}\n      <\/div>\n    `;\n\n    card.onclick = () => {\n      if (openMap === map.name) {\n        openMap = null;\n      } else {\n        openMap = map.name;\n      }\n      renderFilteredMaps();\n    };\n\n    container.appendChild(card);\n\n    if (openMap === map.name) {\n      const detail = document.createElement('div');\n      detail.style.padding = '18px';\n      detail.style.background = '#f8f3ea';\n      detail.style.borderTop = '1px solid #eee';\n      detail.style.borderBottomLeftRadius = '10px';\n      detail.style.borderBottomRightRadius = '10px';\n\n      const monsters = monstersData.filter(monster =>\n        (monster.maps || []).some(mp => mp.name === map.name)\n      );\n\n      const mapImg = getMapImg(map);\n\n      const monstersHtml = monsters.map(monster => {\n        const img = getMonsterImg(monster);\n        return `\n          <div class=\"monster-card\"\n               data-name=\"${monster.name}\"\n               data-level=\"${monster.level ?? '-'}\"\n               data-hp=\"${monster.hp ?? '-'}\"\n               data-exp=\"${monster.exp ?? '-'}\"\n               data-patk=\"${monster.PADamage ?? '-'}\"\n               data-pdef=\"${monster.PDDamage ?? '-'}\"\n               data-mdef=\"${monster.MDDamage ?? '-'}\"\n               data-avoid=\"${monster.eva ?? '-'}\"\n               style=\"\n                 display:flex;\n                 align-items:center;\n                 gap:10px;\n                 padding:8px 10px;\n                 border:1px solid #d8c7a6;\n                 border-radius:6px;\n                 background:#fff8ea;\n                 cursor:pointer;\n                 position:relative;\n               \"\n               onclick=\"goMonster(${monster.id})\"\n          >\n            <img decoding=\"async\" src=\"${img}\" style=\"\n              width:34px;\n              height:34px;\n              object-fit:contain;\n              image-rendering:pixelated;\n            \" onerror=\"this.style.display='none'\">\n\n            <div>\n              <div>${monster.name}<\/div>\n              <div style=\"font-size:12px;color:#888;\">Lv.${monster.level}<\/div>\n            <\/div>\n          <\/div>\n        `;\n      }).join('');\n\n      detail.innerHTML = `\n        <div style=\"display:grid;grid-template-columns:1.2fr 1fr;gap:20px;align-items:start;\">\n          \n          <div>\n            <div style=\"font-weight:700;margin-bottom:10px;\">\u5730\u56fe\u9884\u89c8<\/div>\n            <div style=\"\n              background:#fff;\n              border:1px solid #ddd;\n              border-radius:8px;\n              padding:10px;\n              min-height:180px;\n              display:flex;\n              align-items:center;\n              justify-content:center;\n            \">\n              <img decoding=\"async\" src=\"${mapImg}\" \n                   style=\"max-width:100%;max-height:320px;object-fit:contain;cursor:zoom-in;\"\n                   onclick=\"openMapPreview('${mapImg}')\"\n                   onerror=\"this.parentNode.innerHTML='\u6682\u65e0\u5730\u56fe\u56fe\u7247';\">\n            <\/div>\n\n            <div style=\"margin-top:14px;display:flex;gap:10px;flex-wrap:wrap;\">\n              ${meta.bgm ? `<div style=\"padding:6px 10px;border:1px solid #d8c7a6;border-radius:6px;background:#fff8ea;\">${meta.bgm}<\/div>` : ''}\n              ${meta.mob_rate ? `<div style=\"padding:6px 10px;border:1px solid #d8c7a6;border-radius:6px;background:#fff8ea;\">Mob Rate ${meta.mob_rate}<\/div>` : ''}\n              ${meta.return_town ? `<div style=\"padding:6px 10px;border:1px solid #d8c7a6;border-radius:6px;background:#fff8ea;\">Return ${meta.return_town}<\/div>` : ''}\n            <\/div>\n\n            <div style=\"margin-top:16px;display:flex;gap:12px;flex-wrap:wrap;\">\n              ${meta.prev_map ? `\n                <button onclick=\"event.stopPropagation(); goMapByName('${meta.prev_map.name.replace(\/'\/g, \"\\\\'\")}')\"\n                  style=\"padding:8px 12px;border:1px solid #d8c7a6;border-radius:6px;background:#fff;cursor:pointer;\">\n                  \u2190 ${meta.prev_map.name}\n                <\/button>` : ''}\n\n              ${meta.next_map ? `\n                <button onclick=\"event.stopPropagation(); goMapByName('${meta.next_map.name.replace(\/'\/g, \"\\\\'\")}')\"\n                  style=\"padding:8px 12px;border:1px solid #d8c7a6;border-radius:6px;background:#fff;cursor:pointer;\">\n                  \u2192 ${meta.next_map.name}\n                <\/button>` : ''}\n            <\/div>\n          <\/div>\n\n          <div>\n            <div style=\"font-weight:700;margin-bottom:10px;\">\u602a\u7269\u5217\u8868<\/div>\n            <div style=\"\n              display:grid;\n              grid-template-columns:repeat(auto-fill,minmax(230px,1fr));\n              gap:10px;\n            \">\n              ${monstersHtml || '\u6682\u65e0\u602a\u7269'}\n            <\/div>\n          <\/div>\n\n        <\/div>\n      `;\n\n      container.appendChild(detail);\n    }\n  });\n\n  bindMonsterTooltip();\n}\n\nfunction bindMonsterTooltip() {\n  document.querySelectorAll('.monster-card').forEach(card => {\n    card.onmouseenter = function() {\n      let tip = document.createElement('div');\n      tip.className = 'monster-tip';\n      tip.style = `\n        position:absolute;\n        left:50%;\n        top:110%;\n        transform:translateX(-50%);\n        background:#fff8ea;\n        border:1px solid #d8c7a6;\n        border-radius:10px;\n        padding:12px;\n        min-width:180px;\n        box-shadow:0 4px 14px rgba(0,0,0,0.15);\n        z-index:999;\n      `;\n      tip.innerHTML = `\n        <div style=\"font-weight:700;margin-bottom:8px;\">${this.dataset.name}<\/div>\n        <div>Lv. ${this.dataset.level}<\/div>\n        <div>HP ${this.dataset.hp}<\/div>\n        <div>EXP ${this.dataset.exp}<\/div>\n        <div>P.ATK ${this.dataset.patk}<\/div>\n        <div>P.DEF ${this.dataset.pdef}<\/div>\n        <div>M.DEF ${this.dataset.mdef}<\/div>\n        <div>AVOID ${this.dataset.avoid}<\/div>\n      `;\n      this.appendChild(tip);\n    };\n\n    card.onmouseleave = function() {\n      const tip = this.querySelector('.monster-tip');\n      if (tip) tip.remove();\n    };\n  });\n}\n\nfunction openMapPreview(src) {\n  let modal = document.getElementById('map-preview-modal');\n\n  if (!modal) {\n    modal = document.createElement('div');\n    modal.id = 'map-preview-modal';\n    modal.style = `\n      position:fixed;\n      inset:0;\n      background:rgba(0,0,0,0.75);\n      display:flex;\n      align-items:center;\n      justify-content:center;\n      z-index:99999;\n      padding:20px;\n    `;\n    modal.onclick = () => modal.remove();\n\n    const img = document.createElement('img');\n    img.id = 'map-preview-img';\n    img.style = `\n      max-width:95vw;\n      max-height:95vh;\n      background:#fff;\n      border-radius:8px;\n      box-shadow:0 0 20px rgba(0,0,0,0.5);\n    `;\n    img.onclick = e => e.stopPropagation();\n\n    modal.appendChild(img);\n    document.body.appendChild(modal);\n  }\n\n  document.getElementById('map-preview-img').src = src;\n}\n\nfunction renderFilteredMaps() {\n  const keyword = document.getElementById('search-map').value.toLowerCase();\n  const filtered = mapsData.filter(map =>\n    map.name.toLowerCase().includes(keyword)\n  );\n  renderMaps(filtered);\n}\n\ndocument.getElementById('search-map').addEventListener('input', renderFilteredMaps);\n\nPromise.all([\n  fetch('\/data\/monsters.json').then(res => res.json()),\n  fetch('\/data\/map_meta.json').then(res => res.json()).catch(() => ({}))\n])\n.then(([monsterData, metaData]) => {\n  monstersData = monsterData.monsters || [];\n  mapMeta = metaData || {};\n  mapsData = extractMaps(monstersData);\n  renderMaps(mapsData);\n})\n.catch(err => {\n  document.getElementById('map-list').innerHTML = '\u5730\u56fe\u6570\u636e\u52a0\u8f7d\u5931\u8d25';\n  console.error(err);\n});\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>\u5730\u56fe\u56fe\u9274<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[],"tags":[],"class_list":["post-31","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/www.longlegmxd.com\/index.php\/wp-json\/wp\/v2\/posts\/31","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.longlegmxd.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.longlegmxd.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.longlegmxd.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.longlegmxd.com\/index.php\/wp-json\/wp\/v2\/comments?post=31"}],"version-history":[{"count":6,"href":"https:\/\/www.longlegmxd.com\/index.php\/wp-json\/wp\/v2\/posts\/31\/revisions"}],"predecessor-version":[{"id":39,"href":"https:\/\/www.longlegmxd.com\/index.php\/wp-json\/wp\/v2\/posts\/31\/revisions\/39"}],"wp:attachment":[{"href":"https:\/\/www.longlegmxd.com\/index.php\/wp-json\/wp\/v2\/media?parent=31"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.longlegmxd.com\/index.php\/wp-json\/wp\/v2\/categories?post=31"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.longlegmxd.com\/index.php\/wp-json\/wp\/v2\/tags?post=31"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}