打开/关闭搜索
搜索
打开/关闭菜单
933
1525
112
1.4万
植物大战僵尸杂交版Wiki
导航
首页
最近更改
随机页面
MediaWiki帮助
特殊页面
上传文件
打开/关闭外观设置菜单
notifications
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。
user-interface-preferences
个人工具
创建账号
登录
查看“︁微件:PlantEditor”︁的源代码
来自植物大战僵尸杂交版Wiki
查看
阅读
查看源代码
查看历史
associated-pages
微件
讨论
更多操作
←
微件:PlantEditor
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您没有权限编辑
微件
命名空间内的页面。
您可以查看和复制此页面的源代码。
<includeonly> <div class="plant-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 { background: #2b4b2b; background-image: radial-gradient(circle at 20% 30%, #3f6e3f, #1d351d); min-height: 100vh; margin: 0; padding: 24px 16px; display: flex; justify-content: center; align-items: center; } .app-container { max-width: 1300px; width: 100%; background: rgba(22, 36, 22, 0.7); backdrop-filter: blur(8px); border: 2px solid #b9a76b; box-shadow: 0 20px 40px rgba(0,0,0,0.6), inset 0 0 0 1px #e5d7a3; border-radius: 40px; padding: 28px 24px 32px; } h1 { margin: 0 0 8px 0; font-weight: 700; font-size: 2.5rem; letter-spacing: 2px; color: #f7e9b0; text-shadow: 3px 3px 0 #1e3b1e; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; } h1 small { font-size: 1rem; background: #2c5e2c; padding: 6px 14px; border-radius: 40px; color: #f3eaca; border: 1px solid #ccb87a; box-shadow: inset 0 1px 3px #0f1f0f; } .subtitle { color: #c2d6b0; margin: 4px 0 24px 8px; font-style: italic; border-left: 5px solid #eac784; padding-left: 18px; font-size: 1.1rem; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; } .import-btn { background: #5a7a3a; border: 2px solid #c8b064; color: #f3eeca; padding: 8px 20px; border-radius: 40px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 0 #2a4018; font-size: 0.95rem; transition: all 0.1s ease; } .import-btn:active { transform: translateY(2px); box-shadow: 0 2px 0 #2a4018; } .editor-layout { display: flex; flex-wrap: wrap; gap: 24px; } .form-panel { flex: 2; min-width: 380px; background: #253b1fcc; backdrop-filter: blur(4px); border: 2px solid #b69e5c; border-radius: 32px; padding: 24px 22px; box-shadow: inset 0 0 0 1px #7a9f5e, 0 8px 0 #142010; max-height: 850px; overflow-y: auto; } .form-panel::-webkit-scrollbar { width: 8px; } .form-panel::-webkit-scrollbar-track { background: #1a2e14; border-radius: 20px; } .form-panel::-webkit-scrollbar-thumb { background: #7a9f5e; border-radius: 20px; } .infocard-sim { background: #1e2d14dd; border-radius: 24px; padding: 16px 20px; margin-bottom: 28px; border-left: 12px solid #e2bc6c; box-shadow: inset 0 0 0 1px #809b5e; } .infocard-header { display: flex; align-items: center; justify-content: space-between; color: #f3e3b0; font-weight: bold; margin-bottom: 16px; font-size: 1.3rem; } .infocard-header span { background: #9e3a1f; padding: 4px 14px; border-radius: 40px; font-size: 0.9rem; border: 1px solid #ebb45d; } .image-input-row { display: flex; align-items: center; gap: 8px; background: #1a2812aa; padding: 10px 14px; border-radius: 40px; border: 1px solid #a0c06e; margin-bottom: 16px; flex-wrap: wrap; } .image-input-row label { color: #fad98b; font-weight: 600; font-size: 0.85rem; white-space: nowrap; margin: 0; } .image-input-row input { background: #0e1a0a; border: 1px solid #716633; border-radius: 20px; padding: 6px 12px; color: #f0ebd2; 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-item { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; background: #1a2812aa; padding: 8px 12px; border-radius: 40px; border: 1px solid #7a8f4e; flex-wrap: wrap; } .attr-name { width: 80px; background: transparent; border: none; color: #fad98b; font-weight: 600; padding: 4px 0; } .attr-value { flex: 1; background: #0e1a0a; border: 1px solid #716633; border-radius: 20px; padding: 6px 12px; color: #f0ebd2; } .attr-color-select { width: 70px; background: #2a3a1e; border: 1px solid #a0904e; border-radius: 20px; padding: 5px 6px; color: #f3efd6; font-size: 0.85rem; } .attr-bold-check { display: flex; align-items: center; gap: 4px; color: #eedbaa; font-size: 0.85rem; white-space: nowrap; } .attr-bold-check input { width: 18px; height: 18px; accent-color: #c99f2e; } .attr-remove-btn { background: #7a2e1e; border: 1px solid #cc6b4e; color: #ffd8c8; border-radius: 30px; width: 30px; height: 30px; font-weight: bold; cursor: pointer; font-size: 16px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 0 #3a1a0e; } .add-attr-btn { background: #3b6e2b; border: 1px solid #a0c06e; color: #f3eeca; padding: 8px 18px; border-radius: 40px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 0 #1f3416; margin-top: 8px; display: inline-block; } .input-group { margin-bottom: 24px; } label { display: block; color: #efe2b2; font-weight: 600; margin-bottom: 6px; font-size: 1rem; } input, textarea { width: 100%; background: #1a2812; border: 2px solid #716633; border-radius: 24px; padding: 12px 18px; color: #f3efd6; font-size: 1rem; outline: none; box-shadow: inset 0 3px 8px #0c1409; } input:focus, textarea:focus { border-color: #eac784; box-shadow: 0 0 0 3px #6d8c4e88; } textarea { min-height: 100px; resize: vertical; line-height: 1.5; } .row-2col { display: flex; gap: 16px; flex-wrap: wrap; } .row-2col > div { flex: 1 1 160px; } .gallery-row, .video-row { display: flex; align-items: flex-end; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; } .gallery-row .gallery-fields, .video-row .video-fields { display: flex; flex: 1; gap: 8px; flex-wrap: wrap; } .btn-icon { background: #4f3f1e; border: 1px solid #c8b064; color: #fbeba4; border-radius: 30px; padding: 6px 16px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 0 #232b0e; font-size: 0.9rem; } .btn-primary { background: #c99f2e; border: none; color: #1b2f0e; font-weight: 800; padding: 14px 24px; border-radius: 60px; font-size: 1.2rem; box-shadow: 0 8px 0 #6f4f16; border: 1px solid #fbe593; cursor: pointer; width: 100%; margin-top: 20px; transition: all 0.1s ease; } .btn-primary:active { transform: translateY(4px); box-shadow: 0 4px 0 #6f4f16; } .preview-panel { flex: 3; min-width: 380px; background: #1a2a14e0; backdrop-filter: blur(4px); border: 2px solid #b69e5c; border-radius: 32px; padding: 20px 18px; box-shadow: inset 0 0 0 1px #7a9f5e, 0 8px 0 #142010; display: flex; flex-direction: column; } .preview-header { display: flex; gap: 12px; align-items: center; margin-bottom: 18px; flex-wrap: wrap; } .preview-header h2 { margin: 0; color: #eeddaa; font-size: 1.8rem; text-shadow: 2px 2px 0 #1b341b; } .preview-actions { margin-left: auto; display: flex; gap: 10px; } .copy-btn, .paste-btn { background: #385e2a; border: 1px solid #ccb164; color: #f3eeca; padding: 10px 20px; border-radius: 40px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 0 #1f3416; transition: all 0.1s ease; } .paste-btn { background: #5a4a2a; border-color: #c8b864; } .copy-btn:active, .paste-btn:active { transform: translateY(2px); box-shadow: 0 2px 0 #1f3416; } .wiki-output { background: #0e1d0a; border-radius: 20px; padding: 18px 20px; border: 2px solid #b6a154; box-shadow: inset 0 0 10px #030803; font-family: 'Courier New', monospace; white-space: pre-wrap; word-break: break-word; color: #d4dba8; font-size: 0.95rem; line-height: 1.6; max-height: 500px; overflow: auto; flex: 1; } .note { margin-top: 16px; color: #b9bb7e; font-size: 0.9rem; } .top-link { text-align: center; margin: 0 0 16px 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 16px; } .top-link a { color: #ff8888; 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 { background: #1e2d14; border: 3px solid #b9a76b; border-radius: 32px; padding: 28px; max-width: 700px; width: 90%; max-height: 80vh; box-shadow: 0 20px 40px black; } .modal h3 { color: #f7e9b0; margin: 0 0 16px 0; } .modal p { color: #c0b880; margin-bottom: 12px; } .modal textarea { width: 100%; min-height: 300px; background: #0e1a0a; border: 2px solid #a0904e; color: #f0ebd2; font-family: 'Courier New', monospace; font-size: 0.9rem; } .modal-actions { display: flex; gap: 16px; margin-top: 20px; justify-content: flex-end; } .modal-btn { padding: 12px 28px; border-radius: 40px; font-weight: bold; cursor: pointer; border: none; font-size: 1rem; } .modal-btn.primary { background: #c99f2e; color: #1b2f0e; box-shadow: 0 4px 0 #6f4f16; } .modal-btn.cancel { background: #4a3a2a; color: #e0d0b0; box-shadow: 0 4px 0 #2a1a10; } .video-section { background: #1e2d14aa; border-radius: 20px; padding: 14px 18px; margin-bottom: 24px; border: 1px solid #a0904e; } .video-header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; } .video-header span { color: #fad98b; font-weight: bold; } </style> </head> <body> <h1>🌻🌱 植物 · Wiki编辑器 <small>杂交版植物</small></h1> <div class="subtitle"> <span>填写数据,一键生成标准Wiki文本</span> <button class="import-btn" id="importBtn">📥 导入现有源码</button> </div> <div class="editor-layout"> <div class="form-panel" id="formPanel"> <div class="infocard-sim"> <div class="infocard-header"> <span>📋 Infocard 属性编辑器</span> <span style="background:#5a3a1e;">right|图片=xxx|图片尺寸=xx|属性=...</span> </div> <div class="image-input-row"> <label>🖼️ 图片=</label> <input type="text" id="infocardImage" value="豌豆向日葵.png" placeholder="文件名"> <label>图片尺寸=</label> <input type="text" id="infocardImageSize" value="80px" placeholder="80px" class="size-input"> </div> <div id="attrEditorContainer" class="attr-editor"></div> <button type="button" id="addAttrBtn" class="add-attr-btn">➕ 添加属性项</button> </div> <div class="input-group"> <label>🏷️ 植物稀有度/分类</label> <input type="text" id="rarityInput" value="白卡植物"> </div> <div class="input-group"> <label>🌿 植物主描述</label> <input type="text" id="descLine" value="攻产兼备的基础植物,梦开始的地方!"> </div> <div class="input-group"> <label>🖼️ 皮肤 · 画廊</label> <div id="galleryContainer"> <div class="gallery-row"> <div class="gallery-fields"> <input type="text" class="skinFile" value="豌豆向日葵皮肤1.png" placeholder="文件名" style="flex:2;"> <input type="text" class="skinCaption" value="天使与恶魔" placeholder="标题" style="flex:1.5;"> <input type="text" class="skinLink" value="" placeholder="link=" style="flex:1;"> </div> <button type="button" class="btn-icon remove-gallery-btn">✕</button> </div> </div> <div style="margin-top:10px;"><button type="button" id="addGalleryBtn" class="btn-icon" style="background:#3b6e2b;">➕ 添加皮肤项</button></div> </div> <!-- ★ 新增视频演示区域 --> <div class="video-section"> <div class="video-header"><span>🎬 视频演示</span></div> <div id="videoContainer"> <div class="video-row"> <div class="video-fields"> <input type="text" class="videoBv" value="BV1SEE3zyEVX" placeholder="BV号" style="flex:2;"> <input type="text" class="videoWidth" value="320" placeholder="宽" style="flex:1;"> <input type="text" class="videoHeight" value="180" placeholder="高" style="flex:1;"> </div> <button type="button" class="btn-icon remove-video-btn">✕</button> </div> </div> <div style="margin-top:10px;"><button type="button" id="addVideoBtn" class="btn-icon" style="background:#3b6e2b;">➕ 添加视频项</button></div> <div style="color:#b9bb7e; font-size:0.8rem; margin-top:6px;">使用BiliVideo部件,填写BV号与尺寸</div> </div> <div class="row-2col"> <div class="input-group"><label>🔓 解锁方式</label><input type="text" id="unlockInput" value="初始解锁"></div> <div class="input-group"><label>🏷️ 别名(每行一个)</label><textarea id="aliasInput" rows="2">①带妹上分 ②带妹射手</textarea></div> </div> <div class="input-group"><label>✨ 特点(每行一个)</label><textarea id="featuresListInput" rows="3">生产阳光,向敌人射出豌豆</textarea></div> <div class="input-group"><label>📜 宝开语</label><textarea id="poptalkInput" rows="5">杂交植物们来自于和双子向日葵所诞生的同一个实验室。 "但这不代表我们就是兄弟了," 双子向日葵说, "他们的诞生简直就是一场恐怖的悲剧!"</textarea></div> <button class="btn-primary" id="generateBtn">🌱 立即生成 Wiki 文本</button> </div> <div class="preview-panel"> <div class="preview-header"> <h2>📄 Wiki输出</h2> <div class="preview-actions"> <button class="paste-btn" id="pasteToImportBtn">📋 从预览导入</button> <button class="copy-btn" id="copyBtn">📋 复制代码</button> </div> </div> <div class="wiki-output" id="wikiOutput"></div> <div class="note">⚡ 实时生成。可导入现有源码或从预览导入。</div> </div> </div> </div> <div class="modal-overlay" id="importModal"> <div class="modal"> <h3>📥 导入 Wiki 源码</h3> <p>粘贴现有的植物 Wiki 文本</p> <textarea id="importTextarea" placeholder="在此粘贴 Wiki 源码..."></textarea> <div class="modal-actions"> <button class="modal-btn cancel" id="cancelImportBtn">取消</button> <button class="modal-btn primary" id="confirmImportBtn">解析并导入</button> </div> </div> </div> <script> (function() { const COLOR_OPTIONS = [ { value: '', label: '默认' },{ value: 'red', label: '红色' },{ value: 'blue', label: '蓝色' }, { value: 'green', label: '绿色' },{ value: 'orange', label: '橙色' },{ value: 'purple', label: '紫色' }, { value: 'gold', label: '金色' },{ value: 'brown', label: '棕色' } ]; const COLOR_MAP = Object.fromEntries(COLOR_OPTIONS.filter(o=>o.value).map(o=>[o.value,o.value])); const DEFAULT_ATTRS = [ { name: '价格', value: '125阳光', color: '', bold: false }, { name: '冷却', value: '7.5秒', color: '', bold: false }, { name: '韧性', value: '300', color: 'red', bold: true }, { name: '生产', value: '25阳光/25s', color: 'red', bold: true }, { name: '威力', value: '20/1.5秒', color: 'red', bold: true }, { name: '范围', value: '前方一行', color: 'red', bold: true }, { name: '特点', value: '每25秒生产25阳光', color: 'red', bold: true }, { name: '上线版本', value: 'v0.1', color: '', bold: false } ]; const attrContainer = document.getElementById('attrEditorContainer'); const infocardImage = document.getElementById('infocardImage'); const infocardImageSize = document.getElementById('infocardImageSize'); const rarityInp = document.getElementById('rarityInput'); const descLine = document.getElementById('descLine'); const unlockInp = document.getElementById('unlockInput'); const aliasArea = document.getElementById('aliasInput'); const featuresArea = document.getElementById('featuresListInput'); const poptalkArea = document.getElementById('poptalkInput'); const galleryContainer = document.getElementById('galleryContainer'); const videoContainer = document.getElementById('videoContainer'); const wikiOutputDiv = document.getElementById('wikiOutput'); const importModal = document.getElementById('importModal'); const importTextarea = document.getElementById('importTextarea'); function createColorSelect(sel='') { const s = document.createElement('select'); s.className='attr-color-select'; COLOR_OPTIONS.forEach(o => { const op = document.createElement('option'); op.value=o.value; op.textContent=o.label; if(o.value===sel) op.selected=true; s.appendChild(op); }); return s; } function createBoldCheck(chk=false) { const d = document.createElement('div'); d.className='attr-bold-check'; d.innerHTML = `<input type="checkbox" ${chk?'checked':''}><span>加粗</span>`; return d; } function createAttrItem(d={name:'',value:'',color:'',bold:false}) { const div = document.createElement('div'); div.className='attr-item'; const ni = document.createElement('input'); ni.type='text'; ni.className='attr-name'; ni.placeholder='属性名'; ni.value=d.name||''; const vi = document.createElement('input'); vi.type='text'; vi.className='attr-value'; vi.placeholder='属性值'; vi.value=d.value||''; const cs = createColorSelect(d.color||''); const bc = createBoldCheck(d.bold||false); const cb = bc.querySelector('input'); const rb = document.createElement('button'); rb.type='button'; rb.className='attr-remove-btn'; rb.textContent='✕'; rb.addEventListener('click',()=>{ if(attrContainer.children.length>1){ div.remove(); refreshPreview(); } else alert('至少保留一个属性项'); }); div.append(ni,vi,cs,bc,rb); ni.addEventListener('input',refreshPreview); vi.addEventListener('input',refreshPreview); cs.addEventListener('change',refreshPreview); cb.addEventListener('change',refreshPreview); return div; } function setAttrItems(a){ attrContainer.innerHTML=''; a.forEach(x=>attrContainer.appendChild(createAttrItem(x))); } function collectAttrs(){ const a=[]; attrContainer.querySelectorAll('.attr-item').forEach(item=>{ const n=item.querySelector('.attr-name').value.trim(); const v=item.querySelector('.attr-value').value.trim(); if(!n&&!v) return; a.push({name:n||'?',value:v||'',color:item.querySelector('.attr-color-select').value,bold:item.querySelector('.attr-bold-check input').checked}); }); return a; } function buildInfocard() { const img = infocardImage.value.trim() || '豌豆向日葵.png'; const sz = infocardImageSize.value.trim() || '80px'; const attrs = collectAttrs(); const parts = attrs.map(a => { let v = a.value; if(a.bold) v = `'''${v}'''`; if(a.color) v = `<font color=${a.color}>${v}</font>`; return `${a.name}:${v}`; }); return `{{Infocard|right|图片=${img}|图片尺寸=${sz}|属性=${parts.join(',')}}}`; } function collectGalleryItems(){ const items=[]; galleryContainer.querySelectorAll('.gallery-row').forEach(row=>{ const f=row.querySelector('.skinFile'); if(!f) return; const file=f.value.trim(), cap=row.querySelector('.skinCaption')?.value.trim()||'', link=row.querySelector('.skinLink')?.value.trim()||''; if(!file&&!cap&&!link) return; let line=file; if(cap) line+=`|${cap}`; if(link) line+=`|link=${link}`; items.push(line); }); return items; } function collectVideoItems(){ const items=[]; videoContainer.querySelectorAll('.video-row').forEach(row=>{ const bvInput = row.querySelector('.videoBv'); if(!bvInput) return; const bv = bvInput.value.trim(); const width = row.querySelector('.videoWidth')?.value.trim() || '320'; const height = row.querySelector('.videoHeight')?.value.trim() || '180'; if(!bv) return; items.push({ bv, width, height }); }); return items; } function buildWikiText(){ const infocard = buildInfocard(); const rarity = rarityInp.value.trim() || '白卡植物'; const desc = descLine.value.trim() || '攻产兼备的基础植物,梦开始的地方!'; const gItems = collectGalleryItems(); const gBlock = gItems.length>0 ? gItems.join('\n') : '豌豆向日葵皮肤1.png|天使与恶魔|link='; const videoItems = collectVideoItems(); let videoBlock = ''; if (videoItems.length > 0) { videoBlock = videoItems.map(v => `{{#widget:BiliVideo|bv=${v.bv}|width=${v.width}|height=${v.height}}}`).join('\n'); } else { videoBlock = '{{#widget:BiliVideo|bv=BV1SEE3zyEVX|width=320|height=180}}'; } const unlock = unlockInp.value.trim() || '初始解锁'; const alias = aliasArea.value.trim().split('\n').filter(l=>l.trim()).map(l=>`* ${l.trim()}`).join('\n'); const feat = featuresArea.value.trim().split('\n').filter(l=>l.trim()).map(l=>`* ${l.trim()}`).join('\n'); const pop = poptalkArea.value.split('\n').map(l=>{ const t=l.trim(); return t?`'''${t}'''`:''; }).join('\n'); return `{{返回植物列表}} ${infocard} 《植物大战僵尸杂交版》中的${rarity} ${desc} <div style="display: flex; justify-content: center;"> <div style="width: fit-content; min-width: 50%;"> == 皮肤 == <hr/> <gallery> ${gBlock} </gallery> ==视频演示== <hr/> ${videoBlock} == 解锁方式 == <hr/> <font color=blue>'''${unlock}'''</font> ==别名== <hr/> ${alias} == 特点 == <hr/> ${feat} == 宝开语 == <hr/> ${pop} </div> </div>`; } function refreshPreview(){ const t = buildWikiText(); wikiOutputDiv.innerHTML = t.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); } function addGalleryRow(file='',caption='',link=''){ const div=document.createElement('div'); div.className='gallery-row'; div.innerHTML=`<div class="gallery-fields"><input type="text" class="skinFile" value="${file.replace(/"/g,'"')}" placeholder="文件名" style="flex:2;"><input type="text" class="skinCaption" value="${caption.replace(/"/g,'"')}" placeholder="标题" style="flex:1.5;"><input type="text" class="skinLink" value="${link.replace(/"/g,'"')}" placeholder="link=" style="flex:1;"></div><button type="button" class="btn-icon remove-gallery-btn">✕</button>`; galleryContainer.appendChild(div); div.querySelector('.remove-gallery-btn').addEventListener('click',function(){ if(galleryContainer.children.length>1){ div.remove(); refreshPreview(); } else alert('至少保留一项皮肤'); }); div.querySelectorAll('input').forEach(i=>i.addEventListener('input',refreshPreview)); refreshPreview(); } function addVideoRow(bv='', width='320', height='180'){ const div=document.createElement('div'); div.className='video-row'; div.innerHTML=`<div class="video-fields"><input type="text" class="videoBv" value="${bv.replace(/"/g,'"')}" placeholder="BV号" style="flex:2;"><input type="text" class="videoWidth" value="${width}" placeholder="宽" style="flex:1;"><input type="text" class="videoHeight" value="${height}" placeholder="高" style="flex:1;"></div><button type="button" class="btn-icon remove-video-btn">✕</button>`; videoContainer.appendChild(div); div.querySelector('.remove-video-btn').addEventListener('click',function(){ if(videoContainer.children.length>1){ div.remove(); refreshPreview(); } else alert('至少保留一项视频'); }); div.querySelectorAll('input').forEach(i=>i.addEventListener('input',refreshPreview)); refreshPreview(); } function clearGallery(){ while(galleryContainer.children.length>0) galleryContainer.removeChild(galleryContainer.firstChild); } function setGalleryItems(items){ clearGallery(); if(items.length===0) addGalleryRow('','',''); else items.forEach(i=>addGalleryRow(i.file,i.caption,i.link)); } function clearVideo(){ while(videoContainer.children.length>0) videoContainer.removeChild(videoContainer.firstChild); } function setVideoItems(items){ clearVideo(); if(items.length===0) addVideoRow('','320','180'); else items.forEach(v=>addVideoRow(v.bv, v.width, v.height)); } function parseWikiSource(src){ try { let img='豌豆向日葵.png', sz='80px'; const attrs=[]; const im = src.match(/{{Infocard\|right\|图片=([^|]+)\|图片尺寸=([^|]+)\|属性=([^}]+)}}/); 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]; } attrs.push({name,value,color,bold}); }); } const rarityM=src.match(/《植物大战僵尸杂交版》中的([^\n]+)/); const rarity=rarityM?rarityM[1].trim():'白卡植物'; const descM=src.match(/《植物大战僵尸杂交版》中的[^\n]+\n([^\n<]+)/); const desc=descM?descM[1].trim():''; const gItems=[]; const gm=src.match(/<gallery>\s*([\s\S]*?)\s*<\/gallery>/); if(gm){ gm[1].trim().split('\n').forEach(l=>{ l=l.trim(); if(!l) return; const p=l.split('|'); gItems.push({file:p[0]||'',caption:p[1]||'',link:p[2]&&p[2].startsWith('link=')?p[2].substring(5):''}); }); } const videoItems=[]; const videoRegex = /{{#widget:BiliVideo\|bv=([^|]+)\|width=(\d+)\|height=(\d+)}}/g; let vm; while((vm=videoRegex.exec(src))!==null){ videoItems.push({bv:vm[1], width:vm[2], height:vm[3]}); } const unlockM=src.match(/== 解锁方式 ==\s*<hr\/>\s*<font color=blue>'''([^']+)'''<\/font>/); const unlock=unlockM?unlockM[1]:''; const aliasL=[], featL=[]; const as=src.match(/==别名==\s*<hr\/>\s*([\s\S]*?)(?=\n==|$)/); if(as) as[1].split('\n').forEach(l=>{ const m=l.match(/^\*\s*(.+)/); if(m) aliasL.push(m[1]); }); const fs=src.match(/== 特点 ==\s*<hr\/>\s*([\s\S]*?)(?=\n==|$)/); if(fs) fs[1].split('\n').forEach(l=>{ const m=l.match(/^\*\s*(.+)/); if(m) featL.push(m[1]); }); const popL=[]; const ps=src.match(/== 宝开语 ==\s*<hr\/>\s*([\s\S]*?)(?=\s*<\/div>|$)/); if(ps) ps[1].split('\n').forEach(l=>{ const m=l.match(/^'''(.+)'''$/); if(m) popL.push(m[1]); else if(l.trim()) popL.push(l.trim()); }); return {image:img,imageSize:sz,attrs:attrs.length>0?attrs:DEFAULT_ATTRS,rarity,desc,galleryItems:gItems,videoItems:videoItems,unlock,aliasLines:aliasL,featureLines:featL,poptalkLines:popL}; } catch(e){ console.error(e); return null; } } 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.rarity) rarityInp.value=d.rarity; if(d.desc) descLine.value=d.desc; if(d.galleryItems&&d.galleryItems.length>0) setGalleryItems(d.galleryItems); if(d.videoItems&&d.videoItems.length>0) setVideoItems(d.videoItems); if(d.unlock) unlockInp.value=d.unlock; if(d.aliasLines&&d.aliasLines.length>0) aliasArea.value=d.aliasLines.join('\n'); if(d.featureLines&&d.featureLines.length>0) featuresArea.value=d.featureLines.join('\n'); if(d.poptalkLines&&d.poptalkLines.length>0) poptalkArea.value=d.poptalkLines.join('\n'); refreshPreview(); } function importFromSource(src){ const d=parseWikiSource(src); if(d){ applyParsedData(d); alert('✅ 导入成功!'); } else alert('❌ 解析失败'); } function bindEvents(){ document.getElementById('addAttrBtn').addEventListener('click',()=>{ attrContainer.appendChild(createAttrItem()); refreshPreview(); }); document.getElementById('addGalleryBtn').addEventListener('click',()=>addGalleryRow('','','')); document.getElementById('addVideoBtn').addEventListener('click',()=>addVideoRow('','320','180')); infocardImage.addEventListener('input',refreshPreview); infocardImageSize.addEventListener('input',refreshPreview); [rarityInp,descLine,unlockInp,aliasArea,featuresArea,poptalkArea].forEach(i=>i.addEventListener('input',refreshPreview)); document.getElementById('generateBtn').addEventListener('click',refreshPreview); document.getElementById('copyBtn').addEventListener('click',async()=>{ try{ await navigator.clipboard.writeText(buildWikiText()); alert('✅ 已复制'); } catch{ alert('❌ 复制失败'); } }); galleryContainer.addEventListener('input',e=>{ if(e.target.classList.contains('skinFile')||e.target.classList.contains('skinCaption')||e.target.classList.contains('skinLink')) refreshPreview(); }); videoContainer.addEventListener('input',e=>{ if(e.target.classList.contains('videoBv')||e.target.classList.contains('videoWidth')||e.target.classList.contains('videoHeight')) refreshPreview(); }); document.getElementById('importBtn').addEventListener('click',()=>{ importTextarea.value=''; importModal.style.display='flex'; }); 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('pasteToImportBtn').addEventListener('click',()=>importFromSource(buildWikiText())); importModal.addEventListener('click',e=>{ if(e.target===importModal) importModal.style.display='none'; }); } function init(){ attrContainer.innerHTML=''; DEFAULT_ATTRS.forEach(a=>attrContainer.appendChild(createAttrItem(a))); clearGallery(); addGalleryRow('豌豆向日葵皮肤1.png','天使与恶魔',''); clearVideo(); addVideoRow('BV1SEE3zyEVX','320','180'); bindEvents(); refreshPreview(); } init(); })(); </script> </body> </html> </div> </includeonly>
返回
微件:PlantEditor
。
查看“︁微件:PlantEditor”︁的源代码
来自植物大战僵尸杂交版Wiki