打开/关闭菜单
933
1525
112
1.4万
植物大战僵尸杂交版Wiki
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

微件:LevelEditor:修订间差异

来自植物大战僵尸杂交版Wiki
创建页面,内容为“<includeonly> <div class="level-editor-widget"> <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, maximum-scale=1.5"> <link rel="icon" type="image/x-icon" href="favicon.jpg"> <title>关卡 · Wiki编辑器</title> <style> * { box-sizing: border-box; font-family: system-ui, 'Segoe UI', Roboto, 'Helvetica Neue', 'Noto Sans', sans-serif; } body {…”
 
无编辑摘要
 
(未显示同一用户的2个中间版本)
第28行: 第28行:
     .image-input-row label { color: #b0d8e8; font-weight: 600; font-size: 0.85rem; white-space: nowrap; margin: 0; }
     .image-input-row label { color: #b0d8e8; font-weight: 600; font-size: 0.85rem; white-space: nowrap; margin: 0; }
     .image-input-row input { background: #0e1a22; border: 1px solid #5b80a0; border-radius: 20px; padding: 6px 12px; color: #d8f0ff; font-size: 0.85rem; flex: 1; min-width: 80px; }
     .image-input-row input { background: #0e1a22; border: 1px solid #5b80a0; border-radius: 20px; padding: 6px 12px; color: #d8f0ff; font-size: 0.85rem; flex: 1; min-width: 80px; }
    .image-input-row .size-input { flex: 0.4; min-width: 60px; }
     .attr-editor { margin-bottom: 20px; }
     .attr-editor { margin-bottom: 20px; }
     .attr-item { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; background: #1a2830aa; padding: 8px 12px; border-radius: 40px; border: 1px solid #6b8fa0; flex-wrap: wrap; }
     .attr-item { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; background: #1a2830aa; padding: 8px 12px; border-radius: 40px; border: 1px solid #6b8fa0; flex-wrap: wrap; }
第45行: 第44行:
     input:focus, textarea:focus { border-color: #90c8e0; box-shadow: 0 0 0 3px #60a0b888; }
     input:focus, textarea:focus { border-color: #90c8e0; box-shadow: 0 0 0 3px #60a0b888; }
     textarea { min-height: 100px; resize: vertical; line-height: 1.5; font-family: 'Courier New', monospace; font-size: 0.9rem; }
     textarea { min-height: 100px; resize: vertical; line-height: 1.5; font-family: 'Courier New', monospace; font-size: 0.9rem; }
    input[type="color"] { width: 36px; height: 30px; padding: 2px; border-radius: 8px; cursor: pointer; border: 1px solid #5b80a0; background: transparent; }
     .event-item { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; background: #1a2a36; padding: 6px 12px; border-radius: 30px; border: 1px solid #4a7088; flex-wrap: wrap; }
     .event-item { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; background: #1a2a36; padding: 6px 12px; border-radius: 30px; border: 1px solid #4a7088; flex-wrap: wrap; }
     .event-item input { flex: 1; background: #0e1822; border: 1px solid #4a6880; border-radius: 20px; padding: 5px 12px; font-size: 0.9rem; min-width: 120px; }
     .event-item input { flex: 1; background: #0e1822; border: 1px solid #4a6880; border-radius: 20px; padding: 5px 12px; font-size: 0.9rem; min-width: 120px; }
第51行: 第51行:
     .image-row { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
     .image-row { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
     .image-row input { flex: 1; }
     .image-row input { flex: 1; }
     .btn-icon { background: #3a5060; border: 1px solid #80b0c8; color: #d8f0f8; border-radius: 30px; padding: 6px 16px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 0 #1a2838; font-size: 0.9rem; }
     .btn-icon { background: #3a5060; border: 1px solid #80b0c8; color: #d8f0f8; border-radius: 30px; padding: 6px 16px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 0 #1a2838; font-size: 0.9rem; transition: all 0.1s; }
    .btn-icon:active { transform: translateY(2px); box-shadow: 0 2px 0 #1a2838; }
     .btn-primary { background: #80b8c8; border: none; color: #0e1a28; font-weight: 800; padding: 14px 24px; border-radius: 60px; font-size: 1.2rem; box-shadow: 0 8px 0 #4a7088; border: 1px solid #c0e8f0; cursor: pointer; width: 100%; margin-top: 20px; letter-spacing: 1px; transition: all 0.1s ease; }
     .btn-primary { background: #80b8c8; border: none; color: #0e1a28; font-weight: 800; padding: 14px 24px; border-radius: 60px; font-size: 1.2rem; box-shadow: 0 8px 0 #4a7088; border: 1px solid #c0e8f0; cursor: pointer; width: 100%; margin-top: 20px; letter-spacing: 1px; transition: all 0.1s ease; }
     .btn-primary:active { transform: translateY(4px); box-shadow: 0 4px 0 #4a7088; }
     .btn-primary:active { transform: translateY(4px); box-shadow: 0 4px 0 #4a7088; }
第67行: 第68行:
     .top-link a { color: #ffaaaa; font-weight: bold; }
     .top-link a { color: #ffaaaa; font-weight: bold; }
     .modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.7); display: none; justify-content: center; align-items: center; z-index: 1000; }
     .modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.7); display: none; justify-content: center; align-items: center; z-index: 1000; }
     .modal { background: #142028; border: 3px solid #6b90a8; border-radius: 32px; padding: 28px; max-width: 700px; width: 90%; max-height: 80vh; box-shadow: 0 20px 40px black; }
     .modal { background: #142028; border: 3px solid #6b90a8; border-radius: 32px; padding: 28px; max-width: 750px; width: 90%; max-height: 80vh; box-shadow: 0 20px 40px black; }
     .modal h3 { color: #b0d8e8; margin: 0 0 16px 0; font-size: 1.6rem; }
     .modal h3 { color: #b0d8e8; margin: 0 0 16px 0; font-size: 1.6rem; }
     .modal p { color: #80a8c0; margin-bottom: 12px; }
     .modal p { color: #80a8c0; margin-bottom: 12px; }
第77行: 第78行:
     .card-item { background: #16222caa; border-radius: 16px; padding: 10px 14px; margin-bottom: 8px; border: 1px solid #4a6880; }
     .card-item { background: #16222caa; border-radius: 16px; padding: 10px 14px; margin-bottom: 8px; border: 1px solid #4a6880; }
     .card-item .card-row { display: flex; gap: 6px; align-items: center; margin-bottom: 4px; flex-wrap: wrap; }
     .card-item .card-row { display: flex; gap: 6px; align-items: center; margin-bottom: 4px; flex-wrap: wrap; }
    .card-item .card-row:last-child { margin-bottom: 0; }
     .card-item input { font-size: 0.8rem; padding: 4px 8px; border-radius: 14px; }
     .card-item input { font-size: 0.8rem; padding: 4px 8px; border-radius: 14px; }
     .map-grid-container { background: #16222caa; border-radius: 20px; padding: 16px; border: 1px solid #4a7088; margin-bottom: 24px; }
     .map-grid-container { background: #16222caa; border-radius: 20px; padding: 16px; border: 1px solid #4a7088; margin-bottom: 24px; }
    .map-grid-scroll { overflow-x: auto; max-width: 100%; }
     .map-grid-row { display: flex; gap: 2px; margin-bottom: 2px; align-items: center; }
     .map-grid-row { display: flex; gap: 2px; margin-bottom: 2px; align-items: center; }
     .map-grid-cell { width: 48px; height: 48px; background: #11ff00; border: 1px solid #ffffff; border-radius: 4px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 0.6rem; color: #000; text-align: center; overflow: hidden; position: relative; transition: all 0.15s; }
     .map-grid-cell { width: 44px; height: 44px; border-radius: 4px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 0.55rem; color: #000; text-align: center; overflow: hidden; position: relative; transition: all 0.15s; flex-shrink: 0; }
     .map-grid-cell:hover { filter: brightness(1.3); transform: scale(1.05); z-index: 2; }
     .map-grid-cell:hover { filter: brightness(1.3); transform: scale(1.08); z-index: 2; }
    .map-grid-cell.placed { background: #4ade80; }
     .map-grid-cell.placed::after { content: '🌱'; font-size: 16px; position: absolute; pointer-events: none; }
     .map-grid-cell.placed::after { content: '🌱'; font-size: 20px; position: absolute; }
    .map-grid-cell.has-special { box-shadow: inset 0 0 0 2px gold; }
     .map-grid-label { width: 36px; color: #80b8d0; font-size: 0.7rem; text-align: center; flex-shrink: 0; }
     .map-grid-label { width: 34px; color: #80b8d0; font-size: 0.65rem; text-align: center; flex-shrink: 0; }
     .map-toolbar { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; flex-wrap: wrap; }
     .map-toolbar { display: flex; gap: 6px; align-items: center; margin-bottom: 10px; flex-wrap: wrap; }
     .map-toolbar input { width: 150px; font-size: 0.8rem; padding: 6px 10px; }
     .map-toolbar input { width: 130px; font-size: 0.78rem; padding: 5px 8px; }
     .map-toolbar button { padding: 6px 12px; font-size: 0.8rem; }
    .map-toolbar button { padding: 5px 10px; font-size: 0.78rem; }
     .cell-popup { display: none; position: fixed; background: #1a2a36; border: 2px solid #80c8e0; border-radius: 16px; padding: 12px; z-index: 100; min-width: 180px; box-shadow: 0 8px 24px rgba(0,0,0,0.6); }
    .map-toolbar .dim-label { color: #80b8d0; font-size: 0.75rem; margin: 0 2px; }
     .map-toolbar .dim-input { width: 50px; text-align: center; }
    .color-palette { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; flex-wrap: wrap; background: #0e1a22aa; padding: 8px 14px; border-radius: 16px; border: 1px solid #3a5a6a; }
    .color-palette label { font-size: 0.72rem; margin: 0; display: flex; align-items: center; gap: 3px; color: #90b8d0; }
    .color-palette input[type="color"] { width: 28px; height: 22px; padding: 1px; border-radius: 5px; cursor: pointer; border: 1px solid #5b80a0; }
    .color-palette .preset-colors { display: flex; gap: 3px; }
    .color-palette .preset-dot { width: 18px; height: 18px; border-radius: 50%; cursor: pointer; border: 1px solid #5b80a0; transition: transform 0.1s; }
    .color-palette .preset-dot:hover { transform: scale(1.3); }
     .cell-popup { display: none; position: fixed; background: #1a2a36; border: 2px solid #80c8e0; border-radius: 16px; padding: 14px; z-index: 100; min-width: 260px; box-shadow: 0 8px 24px rgba(0,0,0,0.6); }
    .cell-popup label { font-size: 0.75rem; margin-bottom: 2px; }
     .cell-popup input { font-size: 0.8rem; margin-bottom: 6px; }
     .cell-popup input { font-size: 0.8rem; margin-bottom: 6px; }
     .cell-popup button { font-size: 0.75rem; padding: 4px 10px; margin-right: 4px; }
     .cell-popup button { font-size: 0.75rem; padding: 4px 10px; margin-right: 4px; }
    .cell-popup .style-row { display: flex; gap: 4px; align-items: center; margin-bottom: 4px; }
    .cell-popup .style-row input[type="color"] { width: 28px; height: 22px; padding: 1px; }
    .cell-popup .style-row input[type="text"] { width: 80px; font-size: 0.75rem; }
     .tab-bar { display: flex; gap: 4px; margin-bottom: 16px; flex-wrap: wrap; }
     .tab-bar { display: flex; gap: 4px; margin-bottom: 16px; flex-wrap: wrap; }
     .tab-btn { padding: 8px 18px; border-radius: 30px; border: 1px solid #80b8d0; background: #1a2a36; color: #c0d8e8; cursor: pointer; font-weight: 600; font-size: 0.9rem; transition: all 0.15s; }
     .tab-btn { padding: 8px 18px; border-radius: 30px; border: 1px solid #80b8d0; background: #1a2a36; color: #c0d8e8; cursor: pointer; font-weight: 600; font-size: 0.9rem; transition: all 0.15s; }
     .tab-btn.active { background: #3a6a7a; border-color: #c0e8f0; color: #fff; box-shadow: 0 0 12px #80c8e080; }
     .tab-btn.active { background: #3a6a7a; border-color: #c0e8f0; color: #fff; box-shadow: 0 0 12px #80c8e080; }
    .preset-row { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 4px; }
    .preset-btn { font-size: 0.7rem; padding: 3px 8px; border-radius: 12px; border: 1px solid #4a7088; background: #1a2a36; color: #80b8d0; cursor: pointer; }
    .preset-btn:hover { background: #2a4a5a; color: #c0e8f0; }
    .preset-btn.active-preset { background: #3a6a7a; border-color: #c0e8f0; color: #fff; }
    .quick-style-btn { font-size: 0.65rem; padding: 2px 8px; border-radius: 10px; border: 1px solid #4a7088; background: #1a2a36; color: #80b8d0; cursor: pointer; }
    .quick-style-btn:hover { background: #4a2a2a; color: #ff8888; border-color: #ff6666; }
   </style>
   </style>
</head>
</head>
第114行: 第133行:
   <div class="editor-layout">
   <div class="editor-layout">
     <div class="form-panel" id="formPanel">
     <div class="form-panel" id="formPanel">
      <!-- 关卡大图 -->
       <div class="input-group">
       <div class="input-group">
         <label>🖼️ 关卡大图</label>
         <label>🖼️ 关卡大图</label>
第124行: 第142行:
       </div>
       </div>


      <!-- 僵尸卡片编辑器 -->
       <div class="input-group" style="background:#162228aa; border-radius:20px; padding:16px; border:1px solid #4a7088;">
       <div class="input-group" style="background:#162228aa; border-radius:20px; padding:16px; border:1px solid #4a7088;">
         <label>🧟 僵尸卡片 <i>(出现在关卡大图下方)</i></label>
         <label>🧟 僵尸卡片 <i>(出现在关卡大图下方)</i></label>
第131行: 第148行:
       </div>
       </div>


      <!-- 地图预放置编辑器 -->
       <div class="map-grid-container" id="mapGridEditor">
       <div class="map-grid-container" id="mapGridEditor">
         <label style="margin-bottom:8px;">🗺️ 地图预放置 <i>(点击格子放置/编辑植物,右键清除)</i></label>
         <label style="margin-bottom:4px;">🗺️ 地图预放置 <i>(点击格子编辑完整样式,右键清除植物)</i></label>
       
        <div class="color-palette">
          <label>🎨 背景色:<input type="color" id="gridBg" value="#1a6b0a" title="表格背景色"></label>
          <label>格子色:<input type="color" id="gridCell" value="#11ff00" title="默认格子背景色"></label>
          <label>边框色:<input type="color" id="gridBorder" value="#d4e9cd" title="默认格子边框色"></label>
          <label>表头色:<input type="color" id="headerColor" value="#ffffff" title="表头文字颜色"></label>
          <span style="color:#6080a0; font-size:0.65rem;">预设:</span>
          <div class="preset-colors">
            <span class="preset-dot" data-bg="#1a6b0a" data-cell="#11ff00" data-border="#d4e9cd" data-header="#ffffff" style="background:#11ff00;" title="经典草地"></span>
            <span class="preset-dot" data-bg="#2d2d2d" data-cell="#3a3a3a" data-border="#555555" data-header="#cccccc" style="background:#3a3a3a;" title="暗色主题"></span>
            <span class="preset-dot" data-bg="#1a3a2a" data-cell="#2d5a3d" data-border="#4a8a5a" data-header="#c0e0c0" style="background:#2d5a3d;" title="深绿"></span>
            <span class="preset-dot" data-bg="#3a2a1a" data-cell="#6b4a2a" data-border="#8a6a4a" data-header="#e0c090" style="background:#6b4a2a;" title="沙漠"></span>
            <span class="preset-dot" data-bg="#1a1a3a" data-cell="#2a2a5a" data-border="#4a4a8a" data-header="#c0c0ff" style="background:#2a2a5a;" title="暗夜"></span>
          </div>
        </div>
 
         <div class="map-toolbar">
         <div class="map-toolbar">
           <span style="color:#80b8d0; font-size:0.8rem;">当前植物:</span>
           <span style="color:#80b8d0; font-size:0.75rem;">预设:</span>
           <input type="text" id="currentPlantFile" value="豌豆射手.png" placeholder="文件名">
           <div class="preset-row">
           <input type="text" id="currentPlantLink" value="豌豆射手" placeholder="链接" style="width:100px;">
            <button class="preset-btn active-preset" data-rows="5" data-cols="9">5×9</button>
           <button type="button" class="btn-icon" id="clearMapBtn">清空地图</button>
            <button class="preset-btn" data-rows="6" data-cols="9">6×9</button>
           <button type="button" class="btn-icon" id="resetMapBtn">重置默认</button>
            <button class="preset-btn" data-rows="7" data-cols="11">7×11</button>
            <button class="preset-btn" data-rows="5" data-cols="7">5×7</button>
            <button class="preset-btn" data-rows="3" data-cols="5">3×5</button>
          </div>
          <span class="dim-label">行:</span><input type="number" id="mapRows" class="dim-input" value="5" min="1" max="15">
           <span class="dim-label">列:</span><input type="number" id="mapCols" class="dim-input" value="9" min="1" max="15">
           <button type="button" class="btn-icon" id="applySizeBtn">应用</button>
          <input type="text" id="currentPlantFile" value="豌豆射手.png" placeholder="植物文件" style="width:100px;">
          <input type="text" id="currentPlantLink" value="豌豆射手" placeholder="链接" style="width:80px;">
           <button type="button" class="btn-icon" id="clearMapBtn">清空</button>
         </div>
         </div>
         <div id="mapGrid"></div>
         <div class="map-grid-scroll"><div id="mapGrid"></div></div>
       </div>
       </div>


      <!-- Infocard -->
       <div class="infocard-sim">
       <div class="infocard-sim">
         <div class="infocard-header">
         <div class="infocard-header">
第162行: 第202行:
       <div class="section-divider"></div>
       <div class="section-divider"></div>


      <!-- 事件标签页 -->
       <div class="tab-bar">
       <div class="tab-bar">
         <button class="tab-btn active" data-tab="init">初始化</button>
         <button class="tab-btn active" data-tab="init">初始化</button>
第171行: 第210行:
       <div id="tabInit" class="tab-content">
       <div id="tabInit" class="tab-content">
         <div class="input-group">
         <div class="input-group">
           <label>📋 地图行为 - 初始化 <i>(每行一个事件,写"无"表示无事件)</i></label>
           <label>📋 地图行为 - 初始化</label>
           <div id="initEventsContainer"></div>
           <div id="initEventsContainer"></div>
           <button type="button" id="addInitEventBtn" class="add-event-btn">➕ 添加初始化事件</button>
           <button type="button" id="addInitEventBtn" class="add-event-btn">➕ 添加初始化事件</button>
第178行: 第217行:
       <div id="tabPrepare" class="tab-content" style="display:none;">
       <div id="tabPrepare" class="tab-content" style="display:none;">
         <div class="input-group">
         <div class="input-group">
           <label>📋 地图行为 - 准备阶段 <i>(每行一个事件)</i></label>
           <label>📋 地图行为 - 准备阶段</label>
           <div id="prepareEventsContainer"></div>
           <div id="prepareEventsContainer"></div>
           <button type="button" id="addPrepareEventBtn" class="add-event-btn">➕ 添加准备阶段事件</button>
           <button type="button" id="addPrepareEventBtn" class="add-event-btn">➕ 添加准备阶段事件</button>
第185行: 第224行:
       <div id="tabStart" class="tab-content" style="display:none;">
       <div id="tabStart" class="tab-content" style="display:none;">
         <div class="input-group">
         <div class="input-group">
           <label>📋 地图行为 - 开始后行为 <i>(每行一个事件)</i></label>
           <label>📋 地图行为 - 开始后行为</label>
           <div id="startEventsContainer"></div>
           <div id="startEventsContainer"></div>
           <button type="button" id="addStartEventBtn" class="add-event-btn">➕ 添加开始后事件</button>
           <button type="button" id="addStartEventBtn" class="add-event-btn">➕ 添加开始后事件</button>
第193行: 第232行:
       <div class="section-divider"></div>
       <div class="section-divider"></div>


      <!-- 通关奖励 -->
       <div class="input-group">
       <div class="input-group">
         <label>🎁 通关奖励 <i>(图片文件名 | 链接)</i></label>
         <label>🎁 通关奖励</label>
         <div id="rewardsContainer"></div>
         <div id="rewardsContainer"></div>
         <button type="button" id="addRewardBtn" class="add-event-btn">➕ 添加奖励</button>
         <button type="button" id="addRewardBtn" class="add-event-btn">➕ 添加奖励</button>
       </div>
       </div>


      <!-- 困难模式图片 -->
       <div class="input-group">
       <div class="input-group">
         <label>🖼️ 困难模式图片 <i>(可选)</i></label>
         <label>🖼️ 困难模式图片 <i>(可选)</i></label>
第222行: 第259行:
       </div>
       </div>
       <div class="wiki-output" id="wikiOutput"></div>
       <div class="wiki-output" id="wikiOutput"></div>
       <div class="note">⚡ 基于左侧表单实时生成。点击地图格子放置植物,右键清除。</div>
       <div class="note">⚡ 实时生成。点击格子编辑完整样式(支持特殊边框如红线),右键清除植物。</div>
     </div>
     </div>
   </div>
   </div>
第229行: 第266行:
<!-- 格子编辑弹窗 -->
<!-- 格子编辑弹窗 -->
<div class="cell-popup" id="cellPopup">
<div class="cell-popup" id="cellPopup">
   <label style="color:#b0d8e8; font-size:0.8rem;">植物文件名</label>
   <label style="color:#b0d8e8;">🪴 植物</label>
   <input type="text" id="popupFile" placeholder="xxx.png">
   <input type="text" id="popupFile" placeholder="文件名 (xxx.png)">
   <label style="color:#b0d8e8; font-size:0.8rem;">链接</label>
  <input type="text" id="popupLink" placeholder="链接 (植物名)">
  <input type="text" id="popupLink" placeholder="植物名">
   <div style="border-top:1px solid #3a5a6a; margin:8px 0; padding-top:6px;">
   <div style="display:flex; gap:6px; margin-top:8px; justify-content:flex-end;">
    <label style="color:#b0d8e8; font-size:0.75rem;">🎨 单元格样式 <i style="font-size:0.65rem;">(额外CSS,如 border-right:4px solid red)</i></label>
     <button type="button" class="btn-icon" id="popupClear">清除</button>
    <div class="style-row">
      <input type="color" id="popupCellBg" value="#11ff00" title="背景色">
      <input type="color" id="popupCellBorder" value="#d4e9cd" title="边框色">
    </div>
    <input type="text" id="popupExtraStyle" placeholder="额外样式,如 border-right:4px solid red" style="font-size:0.75rem;">
    <div style="display:flex; gap:4px; margin-top:4px; flex-wrap:wrap;">
      <button type="button" class="quick-style-btn" data-style="border-right:4px solid red">右红线</button>
      <button type="button" class="quick-style-btn" data-style="border-left:4px solid blue">左蓝线</button>
      <button type="button" class="quick-style-btn" data-style="border-bottom:4px solid gold">下金线</button>
      <button type="button" class="quick-style-btn" data-style="border:3px solid orange">橙框</button>
      <button type="button" class="quick-style-btn" data-style="">清除特殊</button>
    </div>
  </div>
   <div style="display:flex; gap:6px; margin-top:10px; justify-content:flex-end;">
     <button type="button" class="btn-icon" id="popupClear">清除格子</button>
     <button type="button" class="btn-icon" id="popupSave" style="background:#3a6a7a;">保存</button>
     <button type="button" class="btn-icon" id="popupSave" style="background:#3a6a7a;">保存</button>
   </div>
   </div>
第287行: 第338行:
   ];
   ];


   // 地图数据: 5行 × 9列, 存储 {file, link} 或 null
   // 地图数据:每个格子 {file, link, cellBg, cellBorder, extraStyle}
   let mapData = Array.from({length:5}, ()=>Array.from({length:9}, ()=>null));
  let mapRows = 5, mapCols = 9;
   let mapData = [];
  let gridBg = '#1a6b0a', gridCellColor = '#11ff00', gridBorderColor = '#d4e9cd', headerColor = '#ffffff';
 
  function initMapData() { mapData = Array.from({length:mapRows}, ()=>Array.from({length:mapCols}, ()=>null)); }
  initMapData();


   const attrContainer = document.getElementById('attrEditorContainer');
   const attrContainer = document.getElementById('attrEditorContainer');
第310行: 第366行:
   const mapGrid = document.getElementById('mapGrid');
   const mapGrid = document.getElementById('mapGrid');
   const cellPopup = document.getElementById('cellPopup');
   const cellPopup = document.getElementById('cellPopup');
  const mapRowsInput = document.getElementById('mapRows');
  const mapColsInput = document.getElementById('mapCols');
  const gridBgInput = document.getElementById('gridBg');
  const gridCellInput = document.getElementById('gridCell');
  const gridBorderInput = document.getElementById('gridBorder');
  const headerColorInput = document.getElementById('headerColor');
   let currentEditRow = -1, currentEditCol = -1;
   let currentEditRow = -1, currentEditCol = -1;


第350行: 第412行:


   // ========== 地图预放置 ==========
   // ========== 地图预放置 ==========
  function updateGridColors() {
    gridBg = gridBgInput.value || '#1a6b0a';
    gridCellColor = gridCellInput.value || '#11ff00';
    gridBorderColor = gridBorderInput.value || '#d4e9cd';
    headerColor = headerColorInput.value || '#ffffff';
    renderMapGrid();
    refreshPreview();
  }
  function applyColorPreset(bg, cell, border, header) {
    gridBgInput.value = bg; gridCellInput.value = cell;
    gridBorderInput.value = border; headerColorInput.value = header||'#ffffff';
    updateGridColors();
  }
  function resizeMap(newRows, newCols) {
    const oldData = mapData;
    mapRows = newRows; mapCols = newCols;
    mapData = Array.from({length:mapRows}, (_,r)=>Array.from({length:mapCols}, (_,c)=>(r<oldData.length && c<oldData[0].length ? oldData[r][c] : null)));
    mapRowsInput.value = mapRows; mapColsInput.value = mapCols;
    renderMapGrid(); refreshPreview();
  }
   function renderMapGrid() {
   function renderMapGrid() {
     mapGrid.innerHTML = '';
     mapGrid.innerHTML = '';
    // 表头
     const headerRow = document.createElement('div'); headerRow.className='map-grid-row';
     const headerRow = document.createElement('div'); headerRow.className='map-grid-row';
     headerRow.innerHTML = '<div class="map-grid-label"></div>';
     headerRow.innerHTML = '<div class="map-grid-label"></div>';
     for(let c=1;c<=9;c++) headerRow.innerHTML += `<div class="map-grid-label">列${c}</div>`;
     for(let c=1;c<=mapCols;c++) headerRow.innerHTML += `<div class="map-grid-label" style="color:${headerColor}">列${c}</div>`;
     mapGrid.appendChild(headerRow);
     mapGrid.appendChild(headerRow);
    // 行
     for(let r=0;r<mapRows;r++) {
     for(let r=0;r<5;r++) {
       const row = document.createElement('div'); row.className='map-grid-row';
       const row = document.createElement('div'); row.className='map-grid-row';
       row.innerHTML = `<div class="map-grid-label">行${r+1}</div>`;
       row.innerHTML = `<div class="map-grid-label" style="color:${headerColor}">行${r+1}</div>`;
       for(let c=0;c<9;c++) {
       for(let c=0;c<mapCols;c++) {
        const d = mapData[r][c];
         const cell = document.createElement('div');
         const cell = document.createElement('div');
         cell.className = 'map-grid-cell';
         cell.className = 'map-grid-cell';
         if(mapData[r][c]) {
        const cbg = d?.cellBg || gridCellColor;
           cell.classList.add('placed');
        const cbd = d?.cellBorder || gridBorderColor;
           cell.title = mapData[r][c].file;
        cell.style.background = cbg;
        cell.style.border = `2px solid ${cbd}`;
         if(d?.extraStyle) {
           cell.style.cssText += ';' + d.extraStyle;
           cell.classList.add('has-special');
         }
         }
        if(d?.file) { cell.classList.add('placed'); cell.title = d.file; }
         cell.addEventListener('click',()=>openCellPopup(r,c));
         cell.addEventListener('click',()=>openCellPopup(r,c));
         cell.addEventListener('contextmenu',(e)=>{ e.preventDefault(); mapData[r][c]=null; renderMapGrid(); refreshPreview(); });
         cell.addEventListener('contextmenu',(e)=>{ e.preventDefault(); mapData[r][c]=null; renderMapGrid(); refreshPreview(); });
第378行: 第464行:
     currentEditRow = r; currentEditCol = c;
     currentEditRow = r; currentEditCol = c;
     const d = mapData[r][c];
     const d = mapData[r][c];
     document.getElementById('popupFile').value = d ? d.file : '';
     document.getElementById('popupFile').value = d?.file || '';
     document.getElementById('popupLink').value = d ? d.link : '';
     document.getElementById('popupLink').value = d?.link || '';
    document.getElementById('popupCellBg').value = d?.cellBg || gridCellColor;
    document.getElementById('popupCellBorder').value = d?.cellBorder || gridBorderColor;
    document.getElementById('popupExtraStyle').value = d?.extraStyle || '';
     cellPopup.style.display = 'block';
     cellPopup.style.display = 'block';
    // 定位弹窗
     const cells = mapGrid.querySelectorAll('.map-grid-cell');
     const cells = mapGrid.querySelectorAll('.map-grid-cell');
     const idx = r*9 + c + 9; // +9 for header row
     const idx = r*mapCols + c + mapCols;
     if(cells[idx]) {
     if(cells[idx]) {
       const rect = cells[idx].getBoundingClientRect();
       const rect = cells[idx].getBoundingClientRect();
       cellPopup.style.left = Math.min(rect.right+8, window.innerWidth-220)+'px';
       cellPopup.style.left = Math.min(rect.right+8, window.innerWidth-290)+'px';
       cellPopup.style.top = Math.min(rect.top, window.innerHeight-200)+'px';
       cellPopup.style.top = Math.min(rect.top, window.innerHeight-380)+'px';
     }
     }
   }
   }
第394行: 第482行:
     const file = document.getElementById('popupFile').value.trim();
     const file = document.getElementById('popupFile').value.trim();
     const link = document.getElementById('popupLink').value.trim();
     const link = document.getElementById('popupLink').value.trim();
    const cellBg = document.getElementById('popupCellBg').value;
    const cellBorder = document.getElementById('popupCellBorder').value;
    const extraStyle = document.getElementById('popupExtraStyle').value.trim();
     if(file) {
     if(file) {
       mapData[currentEditRow][currentEditCol] = {file, link: link||file.replace('.png','')};
       mapData[currentEditRow][currentEditCol] = {file, link: link||file.replace('.png',''), cellBg, cellBorder, extraStyle};
    } else if(cellBg!==gridCellColor || cellBorder!==gridBorderColor || extraStyle) {
      mapData[currentEditRow][currentEditCol] = {file:'', link:'', cellBg, cellBorder, extraStyle};
     } else {
     } else {
       mapData[currentEditRow][currentEditCol] = null;
       mapData[currentEditRow][currentEditCol] = null;
     }
     }
     cellPopup.style.display = 'none';
     cellPopup.style.display = 'none';
     renderMapGrid();
     renderMapGrid(); refreshPreview();
    refreshPreview();
   }
   }
   function clearMap() { mapData = Array.from({length:5},()=>Array.from({length:9},()=>null)); renderMapGrid(); refreshPreview(); }
   function clearMap() { initMapData(); renderMapGrid(); refreshPreview(); }
   function buildMapTable() {
   function buildMapTable() {
    let hasAny = false;
     let table = `\n== 地图预放置 ==\n{| style="width:100%;max-width:900px;table-layout:fixed;text-align:center;background:${gridBg};border-collapse:collapse;"\n|-\n! !!`;
    for(let r=0;r<5;r++) for(let c=0;c<9;c++) if(mapData[r][c]) hasAny=true;
    for(let c=1;c<=mapCols;c++) table += ` <font color=${headerColor}>列${c}</font> !!`;
    if(!hasAny) return '';
    table = table.slice(0,-2) + '\n';
     let table = `\n== 地图预放置 ==\n{| style="width:100%;max-width:900px;table-layout:fixed;text-align:center;background:#1a6b0a;border-collapse:collapse;"\n|-\n! !! 列1 !! 列2 !! 列3 !! 列4 !! 列5 !! 列6 !! 列7 !! 列8 !! 列9 \n`;
     for(let r=0;r<mapRows;r++) {
     for(let r=0;r<5;r++) {
       table += `|-\n! <font color=${headerColor}>行${r+1}</font>\n`;
       table += `|-\n! 行${r+1}\n`;
       for(let c=0;c<mapCols;c++) {
       for(let c=0;c<9;c++) {
         const d = mapData[r][c];
         const d = mapData[r][c];
         const content = d ? `[[文件:${d.file}|50px|link=${d.link}]]` : '';
        const cbg = d?.cellBg || gridCellColor;
         table += `| style="height:80px;border:2px solid #ffffff;background:#11ff00;" | ${content}\n`;
        const cbd = d?.cellBorder || gridBorderColor;
        let styleStr = `height:80px;border:2px solid ${cbd};background:${cbg}`;
        if(d?.extraStyle) styleStr += ';' + d.extraStyle;
         const content = (d?.file) ? `[[文件:${d.file}|50px|link=${d.link}]]` : '';
         table += `| style="${styleStr}" | ${content}\n`;
       }
       }
     }
     }
第421行: 第516行:
   }
   }
   function parseMapTable(src) {
   function parseMapTable(src) {
    mapData = Array.from({length:5},()=>Array.from({length:9},()=>null));
     const tableMatch = src.match(/== 地图预放置 ==\s*\n\{\|[\s\S]*?\n\|\}/);
     const tableMatch = src.match(/== 地图预放置 ==\s*\n\{\|[\s\S]*?\n\|\}/);
     if(!tableMatch) return;
     if(!tableMatch) { initMapData(); renderMapGrid(); return; }
    const bgMatch = tableMatch[0].match(/background:([#\w]+)/);
    if(bgMatch) { gridBg = bgMatch[1]; gridBgInput.value = gridBg; }
    const hcMatch = tableMatch[0].match(/<font color=([^>]+)>列1<\/font>/);
    if(hcMatch) { headerColor = hcMatch[1]; headerColorInput.value = headerColor; }
    const headerMatch = tableMatch[0].match(/! !!([\s\S]*?)\n\|-/);
    let cols = 9;
    if(headerMatch) { const colHeaders = headerMatch[1].match(/列\d+/g); if(colHeaders) cols = colHeaders.length; }
     const rows = tableMatch[0].split('\n|-\n');
     const rows = tableMatch[0].split('\n|-\n');
     let rowIdx = -1;
     const rowMatches = rows.filter(r=>/<font color=[^>]*>行\d/.test(r));
     rows.forEach(row => {
    const newRows = rowMatches.length;
      const rm = row.match(/! 行(\d)/);
     if(newRows>0 && cols>0) {
      if(rm) { rowIdx = parseInt(rm[1])-1; return; }
      mapRows = newRows; mapCols = cols;
      if(rowIdx<0||rowIdx>=5) return;
      mapRowsInput.value = mapRows; mapColsInput.value = mapCols;
      const cells = [...row.matchAll(/\| style="[^"]*" \| (.*?)(?=\n|$)/g)];
      initMapData();
      cells.forEach((m,ci) => {
      rowMatches.forEach(row => {
        if(ci>=9) return;
        const rm = row.match(/<font color=[^>]*>行(\d+)<\/font>/);
        const content = m[1].trim();
        if(!rm) return;
        const fm = content.match(/\[\[文件:([^|]+)\|[^|]+\|link=([^\]]+)\]\]/);
        const rowIdx = parseInt(rm[1])-1;
        if(fm) mapData[rowIdx][ci] = {file:fm[1], link:fm[2]};
        if(rowIdx<0||rowIdx>=mapRows) return;
        const cells = [...row.matchAll(/\| style="([^"]*)" \| (.*?)(?=\n|$)/g)];
        cells.forEach((m,ci) => {
          if(ci>=mapCols) return;
          const styleStr = m[1];
          const cbg = styleStr.match(/background:([#\w]+)/);
          const cbd = styleStr.match(/border:2px solid ([#\w]+)/);
          // 提取额外样式(排除height, border, background)
          let extra = styleStr.replace(/height:[^;]+;?/,'').replace(/border:2px solid [#\w]+;?/,'').replace(/background:[#\w]+;?/,'').trim();
          if(extra.endsWith(';')) extra = extra.slice(0,-1);
          if(cbg) gridCellColor = cbg[1];
          if(cbd) gridBorderColor = cbd[1];
          const content = m[2].trim();
          const fm = content.match(/\[\[文件:([^|]+)\|[^|]+\|link=([^\]]+)\]\]/);
          if(fm || extra) {
            mapData[rowIdx][ci] = {
              file: fm?fm[1]:'',
              link: fm?fm[2]:'',
              cellBg: cbg?cbg[1]:gridCellColor,
              cellBorder: cbd?cbd[1]:gridBorderColor,
              extraStyle: extra
            };
          }
        });
       });
       });
     });
      gridCellInput.value = gridCellColor;
      gridBorderInput.value = gridBorderColor;
     }
    renderMapGrid();
   }
   }


   // ========== 僵尸卡片 ==========
   // ========== 卡片/事件/奖励 ==========
   function createCardItem(d) {
   function createCardItem(d) {
     d = d || { image:'', name:'', health:'', speed:'', type:'', version:'', color:'linear-gradient(135deg, #E8E0F0, #D1C4E9)', border:'#7E57C2' };
     d = d || { image:'', name:'', health:'', speed:'', type:'', version:'', color:'linear-gradient(135deg, #E8E0F0, #D1C4E9)', border:'#7E57C2' };
     const div = document.createElement('div'); div.className='card-item';
     const div = document.createElement('div'); div.className='card-item';
     div.innerHTML = `
     div.innerHTML = `<div class="card-row"><input type="text" class="card-image" value="${d.image||''}" placeholder="图片" style="flex:1.5;"><input type="text" class="card-name" value="${d.name||''}" placeholder="名称" style="flex:1;"><input type="text" class="card-health" value="${d.health||''}" placeholder="血量" style="flex:1;"><button type="button" class="event-remove-btn card-remove">✕</button></div><div class="card-row"><input type="text" class="card-speed" value="${d.speed||''}" placeholder="速度" style="flex:0.8;"><input type="text" class="card-type" value="${d.type||''}" placeholder="类型" style="flex:0.8;"><input type="text" class="card-version" value="${d.version||''}" placeholder="版本" style="flex:0.6;"><input type="text" class="card-color" value="${d.color||''}" placeholder="渐变" style="flex:2;"><input type="text" class="card-border" value="${d.border||''}" placeholder="边框" style="flex:1;"></div>`;
      <div class="card-row">
        <input type="text" class="card-image" value="${d.image||''}" placeholder="图片" style="flex:1.5; min-width:80px;">
        <input type="text" class="card-name" value="${d.name||''}" placeholder="名称" style="flex:1; min-width:60px;">
        <input type="text" class="card-health" value="${d.health||''}" placeholder="血量" style="flex:1; min-width:60px;">
        <button type="button" class="event-remove-btn card-remove">✕</button>
      </div>
      <div class="card-row">
        <input type="text" class="card-speed" value="${d.speed||''}" placeholder="速度" style="flex:0.8;">
        <input type="text" class="card-type" value="${d.type||''}" placeholder="类型" style="flex:0.8;">
        <input type="text" class="card-version" value="${d.version||''}" placeholder="版本" style="flex:0.6;">
        <input type="text" class="card-color" value="${d.color||''}" placeholder="渐变" style="flex:2;">
        <input type="text" class="card-border" value="${d.border||''}" placeholder="边框" style="flex:1;">
      </div>`;
     cardsContainer.appendChild(div);
     cardsContainer.appendChild(div);
     div.querySelector('.card-remove').addEventListener('click',()=>{ if(cardsContainer.children.length>1){ div.remove(); refreshPreview(); } else alert('至少保留一个卡片'); });
     div.querySelector('.card-remove').addEventListener('click',()=>{ if(cardsContainer.children.length>1){ div.remove(); refreshPreview(); } else alert('至少保留一个卡片'); });
第466行: 第580行:
     cardsContainer.querySelectorAll('.card-item').forEach(item => {
     cardsContainer.querySelectorAll('.card-item').forEach(item => {
       cards.push({
       cards.push({
         image: item.querySelector('.card-image')?.value.trim()||'',
         image: item.querySelector('.card-image')?.value.trim()||'', name: item.querySelector('.card-name')?.value.trim()||'',
        name: item.querySelector('.card-name')?.value.trim()||'',
         health: item.querySelector('.card-health')?.value.trim()||'', speed: item.querySelector('.card-speed')?.value.trim()||'',
         health: item.querySelector('.card-health')?.value.trim()||'',
         type: item.querySelector('.card-type')?.value.trim()||'', version: item.querySelector('.card-version')?.value.trim()||'',
        speed: item.querySelector('.card-speed')?.value.trim()||'',
         color: item.querySelector('.card-color')?.value.trim()||'', border: item.querySelector('.card-border')?.value.trim()||''
         type: item.querySelector('.card-type')?.value.trim()||'',
        version: item.querySelector('.card-version')?.value.trim()||'',
         color: item.querySelector('.card-color')?.value.trim()||'',
        border: item.querySelector('.card-border')?.value.trim()||''
       });
       });
     });
     });
     return cards;
     return cards;
   }
   }
  // ========== 事件 ==========
   function collectEvents(container, cls) {
   function collectEvents(container, cls) {
     const e = [];
     const e = [];
第491行: 第599行:
     const rb = document.createElement('button'); rb.type='button'; rb.className='event-remove-btn'; rb.textContent='✕';
     const rb = document.createElement('button'); rb.type='button'; rb.className='event-remove-btn'; rb.textContent='✕';
     rb.addEventListener('click', ()=>{ if(container.children.length>1){ div.remove(); refreshPreview(); } else alert('至少保留一项'); });
     rb.addEventListener('click', ()=>{ if(container.children.length>1){ div.remove(); refreshPreview(); } else alert('至少保留一项'); });
     div.append(inp, rb);
     div.append(inp, rb); container.appendChild(div);
    container.appendChild(div);
   }
   }
  // ========== 奖励 ==========
   function collectRewards() {
   function collectRewards() {
     const r = [];
     const r = [];
第511行: 第616行:
     const rb = document.createElement('button'); rb.type='button'; rb.className='event-remove-btn reward-remove'; rb.textContent='✕';
     const rb = document.createElement('button'); rb.type='button'; rb.className='event-remove-btn reward-remove'; rb.textContent='✕';
     rb.addEventListener('click', ()=>{ if(rewardsContainer.children.length>1){ div.remove(); refreshPreview(); } else alert('至少保留一项奖励'); });
     rb.addEventListener('click', ()=>{ if(rewardsContainer.children.length>1){ div.remove(); refreshPreview(); } else alert('至少保留一项奖励'); });
     div.append(fi, li, rb);
     div.append(fi, li, rb); rewardsContainer.appendChild(div);
    rewardsContainer.appendChild(div);
   }
   }
   function clearContainer(c) { while(c.children.length>0) c.removeChild(c.firstChild); }
   function clearContainer(c) { while(c.children.length>0) c.removeChild(c.firstChild); }


   // ========== 构建Wiki文本 ==========
   // ========== 构建Wiki ==========
   function buildInfocard() {
   function buildInfocard() {
     const img = infocardImage.value.trim() || '豌豆进化.png';
     const img = infocardImage.value.trim() || '豌豆进化.png';
     const sz = infocardImageSize.value.trim() || '200px';
     const sz = infocardImageSize.value.trim() || '200px';
     const attrs = collectAttrs();
     const attrs = collectAttrs();
    // 自动添加地图预放置属性
     const preplaced = [];
     const preplaced = [];
     for(let r=0;r<5;r++) for(let c=0;c<9;c++) if(mapData[r][c]) preplaced.push(`${mapData[r][c].link}(位置:第${r+1}行第${c+1}列)`);
     for(let r=0;r<mapRows;r++) for(let c=0;c<mapCols;c++) if(mapData[r][c]?.file) preplaced.push(`${mapData[r][c].link}(位置:第${r+1}行第${c+1}列)`);
     if(preplaced.length>0 && !attrs.some(a=>a.name==='地图预放置')) {
     if(preplaced.length>0 && !attrs.some(a=>a.name==='地图预放置')) attrs.push({name:'地图预放置', value:preplaced.join('<br>'), color:'red', bold:true});
      attrs.push({name:'地图预放置', value:preplaced.join('<br>'), color:'red', bold:true});
    }
     const parts = attrs.map(a => {
     const parts = attrs.map(a => {
       let v = a.value;
       let v = a.value; if(a.bold) v = `'''${v}'''`; if(a.color) v = `<font color=${a.color}>${v}</font>`;
      if(a.bold) v = `'''${v}'''`;
      if(a.color) v = `<font color=${a.color}>${v}</font>`;
       return `${a.name}:${v}`;
       return `${a.name}:${v}`;
     });
     });
     return `{{Infocard|图片=${img}|图片尺寸=${sz}|属性=${parts.join(',')}}}`;
     return `{{Infocard|图片=${img}|图片尺寸=${sz}|属性=${parts.join(',')}}}`;
   }
   }
   function buildCardsBlock() {
   function buildCardsBlock() {
     const cards = collectCards();
     const cards = collectCards();
     if (cards.length === 0) return '';
     if (cards.length === 0) return '';
     const lines = cards.map(c => {
     const lines = cards.map(c => `{{Card|image=[[文件:${c.image}|75px|${c.name}|link=${c.name}]]|name=${c.name}|health=${c.health}|speed=${c.speed}|type=${c.type}|version=${c.version}|color=${c.color}|border=${c.border}}}`);
      return `{{Card|image=[[文件:${c.image}|75px|${c.name}|link=${c.name}]]|name=${c.name}|health=${c.health}|speed=${c.speed}|type=${c.type}|version=${c.version}|color=${c.color}|border=${c.border}}}`;
    });
     return `<div style="float:left" class="pvzhe-card-container">\n${lines.join('\n')}\n</div>`;
     return `<div style="float:left" class="pvzhe-card-container">\n${lines.join('\n')}\n</div>`;
   }
   }
   function buildWikiText() {
   function buildWikiText() {
     const infocard = buildInfocard();
     const infocard = buildInfocard();
     const mf = mapImageFile.value.trim() || '射击模式.png';
     const mf = mapImageFile.value.trim()||'射击模式.png', mw = mapImageWidth.value.trim()||'350px', ml = mapImageLink.value.trim()||'射击模式';
    const mw = mapImageWidth.value.trim() || '350px';
     const cardsBlock = buildCardsBlock(), mapTable = buildMapTable();
    const ml = mapImageLink.value.trim() || '射击模式';
     const initE = collectEvents(initEventsContainer,'init-event'), prepE = collectEvents(prepareEventsContainer,'prepare-event'), startE = collectEvents(startEventsContainer,'start-event');
     const cardsBlock = buildCardsBlock();
    const mapTable = buildMapTable();
     const initE = collectEvents(initEventsContainer, 'init-event');
    const prepE = collectEvents(prepareEventsContainer, 'prepare-event');
    const startE = collectEvents(startEventsContainer, 'start-event');
     const rewards = collectRewards();
     const rewards = collectRewards();
     const hf = hardModeFile.value.trim(), hw = hardModeWidth.value.trim()||'250px', hl = hardModeLink.value.trim();
     const hf=hardModeFile.value.trim(), hw=hardModeWidth.value.trim()||'250px', hl=hardModeLink.value.trim();
 
     let es='';
    // 事件部分
     if(initE.length>0||prepE.length>0||startE.length>0){es='== 事件 ==\n';es+='=== 地图行为(初始化) ===\n<hr/>\n';if(initE.length===0||(initE.length===1&&initE[0]==='无'))es+='*无\n';else initE.forEach(e=>es+=`*${e}<br>\n`);es+='=== 地图行为(准备阶段) ===\n<hr/>\n';if(prepE.length===0||(prepE.length===1&&prepE[0]==='无'))es+='*无\n';else prepE.forEach(e=>es+=`*${e}\n`);es+='=== 地图行为(开始后行为) ===\n<hr/>\n';if(startE.length===0||(startE.length===1&&startE[0]==='无'))es+='*无\n';else startE.forEach(e=>es+=`*${e}<br>\n`);}
     let es = '';
     let rs='';if(rewards.length>0||hf){rs='== 通关奖励 ==\n<div style="display:flex; align-items:center;">\n';rewards.forEach(r=>rs+=`[[文件:${r.file}|link=${r.link||r.file}]]\n`);if(hf){rs+=`<div style="flex:1; display:flex; justify-content:center;">\n[[File:${hf}|${hw}|link=${hl||''}]]\n</div>\n`;}rs+='</div>\n';}
     if(initE.length>0 || prepE.length>0 || startE.length>0) {
     let headerBlock=`{{返回关卡列表}}\n<div style="float:right; margin-left:0px; width:100%; max-width:650px; overflow:hidden; display:flex; align-items:center;">\n<div style="float:right;width:100%;">\n<div style="display: flex; justify-content: flex-end;">\n[[File:${mf}|${mw}|link=${ml}]]\n</div>`;
      es = '== 事件 ==\n';
     if(cardsBlock) headerBlock+='\n'+cardsBlock;
      es += `=== 地图行为(初始化) ===\n<hr/>\n`;
     if(mapTable) headerBlock+='\n'+mapTable;
      if(initE.length===0 || (initE.length===1 && initE[0]==='无')) es += '*无\n';
     headerBlock+='\n</div>\n</div>';
      else initE.forEach(e=>es+=`*${e}<br>\n`);
     return `${headerBlock}\n${infocard}\n${es}${rs}`;
      es += `=== 地图行为(准备阶段) ===\n<hr/>\n`;
      if(prepE.length===0 || (prepE.length===1 && prepE[0]==='无')) es += '*无\n';
      else prepE.forEach(e=>es+=`*${e}\n`);
      es += `=== 地图行为(开始后行为) ===\n<hr/>\n`;
      if(startE.length===0 || (startE.length===1 && startE[0]==='无')) es += '*无\n';
      else startE.forEach(e=>es+=`*${e}<br>\n`);
    }
 
    // 奖励部分
     let rs = '';
    if(rewards.length>0 || hf) {
      rs = `== 通关奖励 ==\n<div style="display:flex; align-items:center;">\n`;
      rewards.forEach(r=>rs+=`[[文件:${r.file}|link=${r.link||r.file}]]\n`);
      if(hf) { rs += `<div style="flex:1; display:flex; justify-content:center;">\n[[File:${hf}|${hw}|link=${hl||''}]]\n</div>\n`; }
      rs += `</div>\n`;
    }
 
    // 大图+卡片+地图预放置区域
     let headerBlock = `{{返回关卡列表}}
<div style="float:right; margin-left:0px; width:100%; max-width:650px; overflow:hidden; display:flex; align-items:center;">
<div style="float:right;width:100%;">
<div style="display: flex; justify-content: flex-end;">
[[File:${mf}|${mw}|link=${ml}]]
</div>`;
 
     if (cardsBlock) headerBlock += `\n${cardsBlock}`;
     if (mapTable) headerBlock += `\n${mapTable}`;
     headerBlock += `\n</div>\n</div>`;
 
     return `${headerBlock}
${infocard}
${es}${rs}`;
   }
   }
  function refreshPreview(){const t=buildWikiText();wikiOutputDiv.innerHTML=t.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}


   function refreshPreview() {
  // ========== 导入 ==========
    const t = buildWikiText();
   function parseWikiSource(src){try{let img='豌豆进化.png',sz='200px';const attrs=[];const im=src.match(/{{Infocard\|图片=([^|]+)\|图片尺寸=([^|]+)\|属性=([^}]+)}}/);if(im){img=im[1].trim();sz=im[2].trim();const attrStr=im[3];const parts=[];let depth=0,cur='';for(let i=0;i<attrStr.length;i++){const ch=attrStr[i];if(ch==='<')depth++;if(ch==='>')depth--;if(ch===','&&depth===0){parts.push(cur);cur='';}else cur+=ch;}if(cur)parts.push(cur);parts.forEach(p=>{const ci=p.indexOf(':');if(ci===-1)return;const name=p.substring(0,ci).trim();let value=p.substring(ci+1).trim();let color='',bold=false;const fm=value.match(/<font color=([^>]+)>(.*?)<\/font>/i);if(fm){const cn=fm[1].replace(/['"]/g,'');if(COLOR_MAP[cn])color=cn;value=fm[2];}const bm=value.match(/^'''(.+)'''$/);if(bm){bold=true;value=bm[1];}if(name!=='地图预放置')attrs.push({name,value,color,bold});});}let mf='射击模式.png',mw='350px',ml='射击模式';const fm=src.match(/\[\[File:([^|]+)\|([^|]+)\|link=([^\]]+)\]\]/);if(fm){mf=fm[1];mw=fm[2];ml=fm[3];}const cards=[];const cardRegex=/{{Card\|image=\[\[文件:([^|]+)\|[^|]+\|([^|]+)\|link=([^\]]+)\]\]\|name=([^|]+)\|health=([^|]*)\|speed=([^|]*)\|type=([^|]*)\|version=([^|]*)\|color=([^|]+)\|border=([^}]+)}}/g;let cm;while((cm=cardRegex.exec(src))!==null){cards.push({image:cm[1],name:cm[4],health:cm[5],speed:cm[6],type:cm[7],version:cm[8],color:cm[9],border:cm[10]});}const initE=[],prepE=[],startE=[];const is=src.match(/=== 地图行为(初始化) ===\s*<hr\/>\s*([\s\S]*?)(?====|$)/);if(is){const ms=is[1].matchAll(/\*([^<\n]*)/g);for(const m of ms){const v=m[1].trim();if(v&&v!=='无')initE.push(v);}}const ps=src.match(/=== 地图行为(准备阶段) ===\s*<hr\/>\s*([\s\S]*?)(?====|$)/);if(ps){const ms=ps[1].matchAll(/\*([^\n]*)/g);for(const m of ms){const v=m[1].trim();if(v&&v!=='无')prepE.push(v);}}const ss=src.match(/=== 地图行为(开始后行为) ===\s*<hr\/>\s*([\s\S]*?)(?====|$)/);if(ss){const ms=ss[1].matchAll(/\*([^<\n]*)/g);for(const m of ms){const v=m[1].trim();if(v&&v!=='无')startE.push(v);}}const rewards=[];const rs=src.match(/== 通关奖励 ==\s*([\s\S]*?)(?=\n\n|$)/);if(rs){const ms=rs[1].matchAll(/\[\[文件:([^|]+)\|link=([^\]]+)\]\]/g);for(const m of ms)rewards.push({file:m[1],link:m[2]});}let hf='',hw='250px',hl='';if(rs){const ms=rs[1].matchAll(/\[\[File:([^|]+)\|([^|]+)\|link=([^\]]+)\]\]/g);const arr=Array.from(ms);if(arr.length>1){hf=arr[1][1];hw=arr[1][2];hl=arr[1][3];}}return{image:img,imageSize:sz,attrs:attrs.length>0?attrs:DEFAULT_ATTRS,mapFile:mf,mapWidth:mw,mapLink:ml,cards:cards,initEvents:initE,prepareEvents:prepE,startEvents:startE,rewards,hardFile:hf,hardWidth:hw,hardLink:hl};}catch(e){console.error(e);return null;}}
    wikiOutputDiv.innerHTML = t.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
  function applyParsedData(d){if(!d)return;if(d.image)infocardImage.value=d.image;if(d.imageSize)infocardImageSize.value=d.imageSize;if(d.attrs&&d.attrs.length>0)setAttrItems(d.attrs);if(d.mapFile)mapImageFile.value=d.mapFile;if(d.mapWidth)mapImageWidth.value=d.mapWidth;if(d.mapLink)mapImageLink.value=d.mapLink;if(d.cards&&d.cards.length>0){clearContainer(cardsContainer);d.cards.forEach(c=>createCardItem(c));}if(d.initEvents!==undefined){clearContainer(initEventsContainer);if(d.initEvents.length===0)createEventItem(initEventsContainer,'init-event','无');else d.initEvents.forEach(e=>createEventItem(initEventsContainer,'init-event',e));}if(d.prepareEvents!==undefined){clearContainer(prepareEventsContainer);if(d.prepareEvents.length===0)createEventItem(prepareEventsContainer,'prepare-event','无');else d.prepareEvents.forEach(e=>createEventItem(prepareEventsContainer,'prepare-event',e));}if(d.startEvents!==undefined){clearContainer(startEventsContainer);if(d.startEvents.length===0)createEventItem(startEventsContainer,'start-event','无');else d.startEvents.forEach(e=>createEventItem(startEventsContainer,'start-event',e));}if(d.rewards&&d.rewards.length>0){clearContainer(rewardsContainer);d.rewards.forEach(r=>createRewardItem(r.file,r.link));}if(d.hardFile)hardModeFile.value=d.hardFile;if(d.hardWidth)hardModeWidth.value=d.hardWidth;if(d.hardLink)hardModeLink.value=d.hardLink;const src=importTextarea.value;if(src)parseMapTable(src);else{updateGridColors();renderMapGrid();}refreshPreview();}
  }
  function importFromSource(src){const d=parseWikiSource(src);if(d){importTextarea.value=src;applyParsedData(d);alert('✅ 导入成功!');}else alert('❌ 解析失败');}
 
  // ========== 解析导入 ==========
  function parseWikiSource(src) {
    try {
      let img='豌豆进化.png', sz='200px';
      const attrs=[];
      const im = src.match(/{{Infocard\|图片=([^|]+)\|图片尺寸=([^|]+)\|属性=([^}]+)}}/);
      if(im) {
        img=im[1].trim(); sz=im[2].trim();
        const attrStr=im[3];
        const parts=[]; let depth=0, cur='';
        for(let i=0;i<attrStr.length;i++){ const ch=attrStr[i]; if(ch==='<') depth++; if(ch==='>') depth--; if(ch===','&&depth===0){ parts.push(cur); cur=''; } else cur+=ch; }
        if(cur) parts.push(cur);
        parts.forEach(p=>{
          const ci=p.indexOf(':'); if(ci===-1) return;
          const name=p.substring(0,ci).trim(); let value=p.substring(ci+1).trim();
          let color='', bold=false;
          const fm=value.match(/<font color=([^>]+)>(.*?)<\/font>/i);
          if(fm){ const cn=fm[1].replace(/['"]/g,''); if(COLOR_MAP[cn]) color=cn; value=fm[2]; }
          const bm=value.match(/^'''(.+)'''$/);
          if(bm){ bold=true; value=bm[1]; }
          if(name!=='地图预放置') attrs.push({name,value,color,bold}); // 跳过地图预放置,由地图编辑器处理
        });
      }
      let mf='射击模式.png', mw='350px', ml='射击模式';
      const fm=src.match(/\[\[File:([^|]+)\|([^|]+)\|link=([^\]]+)\]\]/);
      if(fm){ mf=fm[1]; mw=fm[2]; ml=fm[3]; }
      const cards=[];
      const cardRegex = /{{Card\|image=\[\[文件:([^|]+)\|[^|]+\|([^|]+)\|link=([^\]]+)\]\]\|name=([^|]+)\|health=([^|]*)\|speed=([^|]*)\|type=([^|]*)\|version=([^|]*)\|color=([^|]+)\|border=([^}]+)}}/g;
      let cm;
      while((cm=cardRegex.exec(src))!==null){
        cards.push({image:cm[1], name:cm[4], health:cm[5], speed:cm[6], type:cm[7], version:cm[8], color:cm[9], border:cm[10]});
      }
      const initE=[], prepE=[], startE=[];
      const is=src.match(/=== 地图行为(初始化) ===\s*<hr\/>\s*([\s\S]*?)(?====|$)/);
      if(is){ const ms=is[1].matchAll(/\*([^<\n]*)/g); for(const m of ms){ const v=m[1].trim(); if(v&&v!=='无') initE.push(v); } }
      const ps=src.match(/=== 地图行为(准备阶段) ===\s*<hr\/>\s*([\s\S]*?)(?====|$)/);
      if(ps){ const ms=ps[1].matchAll(/\*([^\n]*)/g); for(const m of ms){ const v=m[1].trim(); if(v&&v!=='') prepE.push(v); } }
      const ss=src.match(/=== 地图行为(开始后行为) ===\s*<hr\/>\s*([\s\S]*?)(?====|$)/);
      if(ss){ const ms=ss[1].matchAll(/\*([^<\n]*)/g); for(const m of ms){ const v=m[1].trim(); if(v&&v!=='无') startE.push(v); } }
      const rewards=[];
      const rs=src.match(/== 通关奖励 ==\s*([\s\S]*?)(?=\n\n|$)/);
      if(rs){ const ms=rs[1].matchAll(/\[\[文件:([^|]+)\|link=([^\]]+)\]\]/g); for(const m of ms) rewards.push({file:m[1],link:m[2]}); }
      let hf='', hw='250px', hl='';
      if(rs){ const ms=rs[1].matchAll(/\[\[File:([^|]+)\|([^|]+)\|link=([^\]]+)\]\]/g); const arr=Array.from(ms); if(arr.length>1){ hf=arr[1][1]; hw=arr[1][2]; hl=arr[1][3]; } }
      return {image:img,imageSize:sz,attrs:attrs.length>0?attrs:DEFAULT_ATTRS,mapFile:mf,mapWidth:mw,mapLink:ml,cards:cards,initEvents:initE,prepareEvents:prepE,startEvents:startE,rewards,hardFile:hf,hardWidth:hw,hardLink:hl};
    } catch(e){ console.error(e); return null; }
  }


  function applyParsedData(d) {
   function bindEvents(){
    if(!d) return;
     document.getElementById('addAttrBtn').addEventListener('click',()=>{attrContainer.appendChild(createAttrItem());refreshPreview();});
    if(d.image) infocardImage.value=d.image;
     document.getElementById('addCardBtn').addEventListener('click',()=>{createCardItem();refreshPreview();});
    if(d.imageSize) infocardImageSize.value=d.imageSize;
     document.getElementById('addInitEventBtn').addEventListener('click',()=>{createEventItem(initEventsContainer,'init-event','');refreshPreview();});
    if(d.attrs&&d.attrs.length>0) setAttrItems(d.attrs);
     document.getElementById('addPrepareEventBtn').addEventListener('click',()=>{createEventItem(prepareEventsContainer,'prepare-event','');refreshPreview();});
    if(d.mapFile) mapImageFile.value=d.mapFile;
     document.getElementById('addStartEventBtn').addEventListener('click',()=>{createEventItem(startEventsContainer,'start-event','');refreshPreview();});
    if(d.mapWidth) mapImageWidth.value=d.mapWidth;
     document.getElementById('addRewardBtn').addEventListener('click',()=>{createRewardItem('','');refreshPreview();});
    if(d.mapLink) mapImageLink.value=d.mapLink;
     infocardImage.addEventListener('input',refreshPreview);infocardImageSize.addEventListener('input',refreshPreview);
    if(d.cards&&d.cards.length>0){ clearContainer(cardsContainer); d.cards.forEach(c=>createCardItem(c)); }
    if(d.initEvents!==undefined){ clearContainer(initEventsContainer); if(d.initEvents.length===0) createEventItem(initEventsContainer,'init-event','无'); else d.initEvents.forEach(e=>createEventItem(initEventsContainer,'init-event',e)); }
    if(d.prepareEvents!==undefined){ clearContainer(prepareEventsContainer); if(d.prepareEvents.length===0) createEventItem(prepareEventsContainer,'prepare-event','无'); else d.prepareEvents.forEach(e=>createEventItem(prepareEventsContainer,'prepare-event',e)); }
    if(d.startEvents!==undefined){ clearContainer(startEventsContainer); if(d.startEvents.length===0) createEventItem(startEventsContainer,'start-event','无'); else d.startEvents.forEach(e=>createEventItem(startEventsContainer,'start-event',e)); }
    if(d.rewards&&d.rewards.length>0){ clearContainer(rewardsContainer); d.rewards.forEach(r=>createRewardItem(r.file,r.link)); }
    if(d.hardFile) hardModeFile.value=d.hardFile;
    if(d.hardWidth) hardModeWidth.value=d.hardWidth;
    if(d.hardLink) hardModeLink.value=d.hardLink;
    // 解析地图表格
    const src = importTextarea.value;
    if(src) parseMapTable(src);
    renderMapGrid();
    refreshPreview();
  }
 
  function importFromSource(src){
    const d=parseWikiSource(src);
    if(d){
      importTextarea.value = src; // 暂存用于地图解析
      applyParsedData(d);
      alert('✅ 导入成功!');
    } else alert('❌ 解析失败');
  }
 
   function bindEvents() {
     document.getElementById('addAttrBtn').addEventListener('click',()=>{ attrContainer.appendChild(createAttrItem()); refreshPreview(); });
     document.getElementById('addCardBtn').addEventListener('click',()=>{ createCardItem(); refreshPreview(); });
     document.getElementById('addInitEventBtn').addEventListener('click',()=>{ createEventItem(initEventsContainer,'init-event',''); refreshPreview(); });
     document.getElementById('addPrepareEventBtn').addEventListener('click',()=>{ createEventItem(prepareEventsContainer,'prepare-event',''); refreshPreview(); });
     document.getElementById('addStartEventBtn').addEventListener('click',()=>{ createEventItem(startEventsContainer,'start-event',''); refreshPreview(); });
     document.getElementById('addRewardBtn').addEventListener('click',()=>{ createRewardItem('',''); refreshPreview(); });
     infocardImage.addEventListener('input',refreshPreview);
    infocardImageSize.addEventListener('input',refreshPreview);
     [mapImageFile,mapImageWidth,mapImageLink,hardModeFile,hardModeWidth,hardModeLink].forEach(i=>i.addEventListener('input',refreshPreview));
     [mapImageFile,mapImageWidth,mapImageLink,hardModeFile,hardModeWidth,hardModeLink].forEach(i=>i.addEventListener('input',refreshPreview));
     document.getElementById('generateBtn').addEventListener('click',refreshPreview);
     document.getElementById('generateBtn').addEventListener('click',refreshPreview);
     document.getElementById('copyBtn').addEventListener('click',async()=>{ try{ await navigator.clipboard.writeText(buildWikiText()); alert('✅ 已复制'); } catch{ alert('❌ 复制失败'); } });
     document.getElementById('copyBtn').addEventListener('click',async()=>{try{await navigator.clipboard.writeText(buildWikiText());alert('✅ 已复制');}catch{alert('❌ 复制失败');}});
     formPanel.addEventListener('input',e=>{ if(e.target.tagName==='INPUT'||e.target.tagName==='TEXTAREA') refreshPreview(); });
     formPanel.addEventListener('input',e=>{if(e.target.tagName==='INPUT'||e.target.tagName==='TEXTAREA')refreshPreview();});
     document.getElementById('importBtn').addEventListener('click',()=>{ importTextarea.value=''; importModal.style.display='flex'; });
     document.getElementById('importBtn').addEventListener('click',()=>{importTextarea.value='';importModal.style.display='flex';});
     document.getElementById('cancelImportBtn').addEventListener('click',()=>importModal.style.display='none');
     document.getElementById('cancelImportBtn').addEventListener('click',()=>importModal.style.display='none');
     document.getElementById('confirmImportBtn').addEventListener('click',()=>{ const s=importTextarea.value.trim(); if(s){ importFromSource(s); importModal.style.display='none'; } else alert('请粘贴源码'); });
     document.getElementById('confirmImportBtn').addEventListener('click',()=>{const s=importTextarea.value.trim();if(s){importFromSource(s);importModal.style.display='none';}else alert('请粘贴源码');});
     document.getElementById('pasteToImportBtn').addEventListener('click',()=>importFromSource(buildWikiText()));
     document.getElementById('pasteToImportBtn').addEventListener('click',()=>importFromSource(buildWikiText()));
     importModal.addEventListener('click',e=>{ if(e.target===importModal) importModal.style.display='none'; });
     importModal.addEventListener('click',e=>{if(e.target===importModal)importModal.style.display='none';});
     // 地图工具栏
     document.getElementById('applySizeBtn').addEventListener('click',()=>{let nr=parseInt(mapRowsInput.value)||5;let nc=parseInt(mapColsInput.value)||9;nr=Math.max(1,Math.min(15,nr));nc=Math.max(1,Math.min(15,nc));resizeMap(nr,nc);});
    document.querySelectorAll('.preset-btn').forEach(btn=>{btn.addEventListener('click',()=>{document.querySelectorAll('.preset-btn').forEach(b=>b.classList.remove('active-preset'));btn.classList.add('active-preset');const nr=parseInt(btn.dataset.rows);const nc=parseInt(btn.dataset.cols);if(nr&&nc)resizeMap(nr,nc);});});
    gridBgInput.addEventListener('input',updateGridColors);gridCellInput.addEventListener('input',updateGridColors);gridBorderInput.addEventListener('input',updateGridColors);headerColorInput.addEventListener('input',updateGridColors);
    document.querySelectorAll('.preset-dot').forEach(dot=>{dot.addEventListener('click',()=>{applyColorPreset(dot.dataset.bg,dot.dataset.cell,dot.dataset.border,dot.dataset.header);});});
     document.getElementById('clearMapBtn').addEventListener('click',clearMap);
     document.getElementById('clearMapBtn').addEventListener('click',clearMap);
    document.getElementById('resetMapBtn').addEventListener('click',()=>{
      mapData = Array.from({length:5},()=>Array.from({length:9},()=>null));
      mapData[2][0] = {file:'豌豆射手.png', link:'豌豆射手'};
      renderMapGrid();
      refreshPreview();
    });
    // 弹窗
     document.getElementById('popupSave').addEventListener('click',saveCellPopup);
     document.getElementById('popupSave').addEventListener('click',saveCellPopup);
     document.getElementById('popupClear').addEventListener('click',()=>{
     document.getElementById('popupClear').addEventListener('click',()=>{if(currentEditRow>=0){mapData[currentEditRow][currentEditCol]=null;renderMapGrid();refreshPreview();}cellPopup.style.display='none';});
      if(currentEditRow>=0){ mapData[currentEditRow][currentEditCol]=null; renderMapGrid(); refreshPreview(); }
     document.querySelectorAll('.quick-style-btn').forEach(btn=>{btn.addEventListener('click',()=>{document.getElementById('popupExtraStyle').value=btn.dataset.style;});});
      cellPopup.style.display='none';
     document.addEventListener('click',(e)=>{if(!cellPopup.contains(e.target)&&!e.target.classList.contains('map-grid-cell'))cellPopup.style.display='none';});
     });
     document.querySelectorAll('.tab-btn').forEach(btn=>{btn.addEventListener('click',()=>{document.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active'));btn.classList.add('active');const tab=btn.dataset.tab;document.getElementById('tabInit').style.display=tab==='init'?'block':'none';document.getElementById('tabPrepare').style.display=tab==='prepare'?'block':'none';document.getElementById('tabStart').style.display=tab==='start'?'block':'none';});});
     document.addEventListener('click',(e)=>{ if(!cellPopup.contains(e.target) && !e.target.classList.contains('map-grid-cell')) cellPopup.style.display='none'; });
    // 标签页
     document.querySelectorAll('.tab-btn').forEach(btn=>{
      btn.addEventListener('click',()=>{
        document.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active'));
        btn.classList.add('active');
        const tab=btn.dataset.tab;
        document.getElementById('tabInit').style.display = tab==='init'?'block':'none';
        document.getElementById('tabPrepare').style.display = tab==='prepare'?'block':'none';
        document.getElementById('tabStart').style.display = tab==='start'?'block':'none';
      });
    });
   }
   }


   function init(){
   function init(){
     setAttrItems(DEFAULT_ATTRS);
     setAttrItems(DEFAULT_ATTRS);clearContainer(cardsContainer);DEFAULT_CARDS.forEach(c=>createCardItem(c));
    clearContainer(cardsContainer);
     clearContainer(initEventsContainer);createEventItem(initEventsContainer,'init-event','无');
    DEFAULT_CARDS.forEach(c=>createCardItem(c));
     clearContainer(prepareEventsContainer);createEventItem(prepareEventsContainer,'prepare-event','无');
     clearContainer(initEventsContainer);
     clearContainer(startEventsContainer);createEventItem(startEventsContainer,'start-event','无');
    createEventItem(initEventsContainer,'init-event','无');
     clearContainer(rewardsContainer);createRewardItem('钱袋子.png','钱袋子');
     clearContainer(prepareEventsContainer);
     initMapData();mapData[2][0]={file:'豌豆射手.png',link:'豌豆射手',cellBg:gridCellColor,cellBorder:gridBorderColor,extraStyle:''};
    createEventItem(prepareEventsContainer,'prepare-event','无');
     renderMapGrid();bindEvents();refreshPreview();
     clearContainer(startEventsContainer);
    createEventItem(startEventsContainer,'start-event','无');
     clearContainer(rewardsContainer);
    createRewardItem('钱袋子.png', '钱袋子');
     mapData[2][0] = {file:'豌豆射手.png', link:'豌豆射手'};
     renderMapGrid();
    bindEvents();
    refreshPreview();
   }
   }
   init();
   init();

2026年7月14日 (二) 02:05的最新版本