卡厄思
梦
境
菜单
首页
回到首页
WIKI工具
全站样式
全站JS
修改导航栏
测试
沙盒
可视化管理器
战斗员管理器
卡牌管理器
伙伴管理器
装备管理器
词典管理器
图鉴
战斗员
伙伴
装备
怪物卡牌
中立卡牌
词典
小工具
配队模拟器
节奏榜生成器
搜索
链入页面
相关更改
特殊页面
页面信息
最近更改
登录
微件
查看“︁TierListMaker”︁的源代码
←
微件:TierListMaker
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您没有权限编辑
微件
命名空间内的页面。
您可以查看和复制此页面的源代码。
<includeonly> <style> .tier-row { position: relative; background-color: #fafafa; border: 2px dashed transparent; transition: all 0.2s ease; display: flex; flex-wrap: wrap; gap: 5px; align-content: flex-start; padding: 5px; } .tier-row.drag-over { background-color: #e3f2fd; border-color: #2196F3; } #character-pool { position: relative; display: flex; flex-wrap: wrap; gap: 5px; align-content: flex-start; padding: 10px; } #character-pool.drag-over { background-color: #fff3e0; } .tierlist-table { width: 100%; table-layout: fixed; } .tierlist-table th { width: 100px; position: relative; } .tierlist-table td { padding: 0 !important; } .tierlist-controls { margin-bottom: 20px; display: flex; gap: 10px; } .tierlist-btn { padding: 10px 20px; font-size: 16px; color: white; border: none; border-radius: 5px; cursor: pointer; transition: all 0.2s ease; display: inline-block; text-align: center; user-select: none; } .tierlist-btn-save { background-color: #4CAF50; } .tierlist-btn-save:hover { background-color: #45a049; } .tierlist-btn-reset { background-color: #f44336; } .tierlist-btn-reset:hover { background-color: #da190b; } .tierlist-btn-add { background-color: #2196F3; } .tierlist-btn-add:hover { background-color: #0b7dda; } .tierlist-btn-edit { background-color: #ff9800; } .tierlist-btn-edit:hover { background-color: #e68900; } .tierlist-btn-edit.active { background-color: #ff5722; } .tierlist-btn:active { transform: scale(0.98); } .character-pool-container { background-color: #f9f9f9; padding: 15px; border: 2px dashed #ccc; border-radius: 5px; margin-top: 20px; } .character-pool-container h3 { margin-top: 0; color: #333; } .tier-header.editable { cursor: pointer; position: relative; } .tier-header.editable:hover::after { content: '✎'; position: absolute; right: 5px; top: 50%; transform: translateY(-50%); font-size: 16px; } .delete-row-btn { position: absolute; right: 5px; top: 50%; transform: translateY(-50%); background-color: #f44336; color: white; border: none; border-radius: 3px; padding: 3px 8px; cursor: pointer; font-size: 12px; display: none; z-index: 100; } .edit-mode .delete-row-btn { display: block; } .delete-row-btn:hover { background-color: #da190b; } .color-picker-popup { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.3); z-index: 1000; min-width: 300px; } .color-picker-popup h4 { margin-top: 0; } .color-picker-popup label { display: block; margin: 10px 0 5px 0; } .color-picker-popup input[type="text"], .color-picker-popup input[type="color"] { width: 100%; padding: 5px; margin-bottom: 10px; box-sizing: border-box; } .color-picker-popup .button-group { display: flex; gap: 10px; margin-top: 15px; } .color-picker-popup button { flex: 1; padding: 8px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; } .color-picker-popup .btn-confirm { background-color: #4CAF50; color: white; } .color-picker-popup .btn-cancel { background-color: #f44336; color: white; } .overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 999; } .avatar-frame { display: inline-block; margin: 0; } </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script> <script> (function() { 'use strict'; // 防止重复初始化 if (window.TierlistMakerInitialized) { console.log('TierlistMaker already initialized'); return; } const TierlistMaker = { draggedElement: null, sourceContainer: null, editMode: false, initRetryCount: 0, maxRetries: 10, init: function() { // 等待DOM完全加载 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this.setup()); } else { this.setup(); } }, setup: function() { // 检查角色池是否已加载 const characterPool = document.getElementById('character-pool'); const avatars = characterPool ? characterPool.querySelectorAll('.avatar-frame') : []; if (avatars.length === 0 && this.initRetryCount < this.maxRetries) { // 角色还未加载,等待后重试 this.initRetryCount++; console.log('等待角色加载...', this.initRetryCount); setTimeout(() => this.setup(), 300); return; } if (avatars.length === 0) { console.warn('未找到角色,可能加载失败'); } console.log('找到角色数量:', avatars.length); this.cleanupContainers(); this.initDragAndDrop(); this.initButtons(); // 注意:不在这里调用 loadState() }, // 清理容器中的空元素 cleanupContainers: function() { const containers = document.querySelectorAll('.tier-row, #character-pool'); containers.forEach(container => { const children = Array.from(container.childNodes); children.forEach(child => { if (child.nodeType === Node.TEXT_NODE && !child.textContent.trim()) { container.removeChild(child); } else if (child.nodeType === Node.ELEMENT_NODE) { if (!child.classList.contains('avatar-frame') && !child.querySelector('.avatar-frame') && !child.textContent.trim()) { container.removeChild(child); } } }); }); }, initDragAndDrop: function() { console.log('初始化拖拽功能...'); // 使用事件委托方式处理拖拽 const characterPool = document.getElementById('character-pool'); const tierRows = document.querySelectorAll('.tier-row'); // 为现有和未来的avatar元素添加拖拽 this.makeDraggable(characterPool); tierRows.forEach(row => this.makeDraggable(row)); // 为tier行添加拖放事件 tierRows.forEach(row => { if (!row.getAttribute('data-drop-initialized')) { row.setAttribute('data-drop-initialized', 'true'); row.addEventListener('dragover', (e) => this.handleDragOver(e, row)); row.addEventListener('drop', (e) => this.handleDrop(e, row)); row.addEventListener('dragleave', (e) => this.handleDragLeave(e, row)); } }); // 为角色池添加拖放事件 if (characterPool && !characterPool.getAttribute('data-drop-initialized')) { characterPool.setAttribute('data-drop-initialized', 'true'); characterPool.addEventListener('dragover', (e) => this.handleDragOver(e, characterPool)); characterPool.addEventListener('drop', (e) => this.handleDrop(e, characterPool)); characterPool.addEventListener('dragleave', (e) => this.handleDragLeave(e, characterPool)); } }, // 使容器内的所有avatar可拖拽 makeDraggable: function(container) { if (!container) return; const avatars = container.querySelectorAll('.avatar-frame'); avatars.forEach(avatar => { if (!avatar.getAttribute('data-drag-initialized')) { avatar.setAttribute('draggable', 'true'); avatar.setAttribute('data-drag-initialized', 'true'); avatar.addEventListener('dragstart', (e) => this.handleDragStart(e, avatar)); avatar.addEventListener('dragend', (e) => this.handleDragEnd(e, avatar)); console.log('已设置拖拽:', avatar); } }); }, handleDragStart: function(e, element) { console.log('开始拖拽:', element); this.draggedElement = element; this.sourceContainer = element.parentElement; element.classList.add('dragging'); element.style.opacity = '0.5'; e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/html', element.innerHTML); }, handleDragEnd: function(e, element) { console.log('结束拖拽:', element); element.classList.remove('dragging'); element.style.opacity = '1'; document.querySelectorAll('.drag-over').forEach(el => { el.classList.remove('drag-over'); }); this.cleanupContainers(); this.saveState(); this.draggedElement = null; this.sourceContainer = null; }, handleDragOver: function(e, element) { e.preventDefault(); e.stopPropagation(); e.dataTransfer.dropEffect = 'move'; if (!element.classList.contains('drag-over')) { element.classList.add('drag-over'); } return false; }, handleDragLeave: function(e, element) { const rect = element.getBoundingClientRect(); const x = e.clientX; const y = e.clientY; if (x <= rect.left || x >= rect.right || y <= rect.top || y >= rect.bottom) { element.classList.remove('drag-over'); } }, handleDrop: function(e, element) { e.preventDefault(); e.stopPropagation(); console.log('放置到:', element); element.classList.remove('drag-over'); if (this.draggedElement && this.draggedElement.parentElement !== element) { if (this.draggedElement.parentElement) { this.draggedElement.parentElement.removeChild(this.draggedElement); } element.appendChild(this.draggedElement); const img = this.draggedElement.querySelector('img'); if (img) { img.style.opacity = '1'; } this.cleanupContainers(); console.log('放置成功'); } return false; }, initButtons: function() { const saveBtn = document.getElementById('save-tierlist-btn'); const resetBtn = document.getElementById('reset-tierlist-btn'); const addRowBtn = document.getElementById('add-row-btn'); const editModeBtn = document.getElementById('edit-mode-btn'); if (saveBtn) { saveBtn.onclick = () => this.saveTierlist(); } if (resetBtn) { resetBtn.onclick = () => this.resetTierlist(); } if (addRowBtn) { addRowBtn.onclick = () => this.addRow(); } if (editModeBtn) { editModeBtn.onclick = () => this.toggleEditMode(); } }, toggleEditMode: function() { this.editMode = !this.editMode; const btn = document.getElementById('edit-mode-btn'); const table = document.getElementById('tierlist-table'); if (this.editMode) { btn.classList.add('active'); btn.textContent = '完成编辑'; table.classList.add('edit-mode'); document.querySelectorAll('.tier-header').forEach(header => { header.classList.add('editable'); if (!header.querySelector('.delete-row-btn')) { const deleteBtn = document.createElement('button'); deleteBtn.className = 'delete-row-btn'; deleteBtn.textContent = '删除'; deleteBtn.onclick = (e) => { e.stopPropagation(); this.deleteRow(header.parentElement); }; header.appendChild(deleteBtn); } header.onclick = () => this.editTierHeader(header); }); } else { btn.classList.remove('active'); btn.textContent = '编辑模式'; table.classList.remove('edit-mode'); document.querySelectorAll('.tier-header').forEach(header => { header.classList.remove('editable'); header.onclick = null; }); } }, editTierHeader: function(header) { const currentText = header.textContent.replace('删除', '').trim(); const currentBgColor = header.style.backgroundColor || '#000000'; const overlay = document.createElement('div'); overlay.className = 'overlay'; const popup = document.createElement('div'); popup.className = 'color-picker-popup'; popup.innerHTML = ` <h4>编辑Tier</h4> <label>Tier名称:</label> <input type="text" id="tier-name-input" value="${currentText}" maxlength="10"> <label>背景颜色:</label> <input type="color" id="tier-color-input" value="${this.rgbToHex(currentBgColor)}"> <div class="button-group"> <button class="btn-confirm">确定</button> <button class="btn-cancel">取消</button> </div> `; document.body.appendChild(overlay); document.body.appendChild(popup); const nameInput = popup.querySelector('#tier-name-input'); const colorInput = popup.querySelector('#tier-color-input'); popup.querySelector('.btn-confirm').onclick = () => { const newName = nameInput.value.trim(); const newColor = colorInput.value; if (newName) { header.setAttribute('data-tier', newName); const deleteBtn = header.querySelector('.delete-row-btn'); if (deleteBtn) deleteBtn.remove(); header.textContent = newName; header.style.backgroundColor = newColor; const newDeleteBtn = document.createElement('button'); newDeleteBtn.className = 'delete-row-btn'; newDeleteBtn.textContent = '删除'; newDeleteBtn.onclick = (e) => { e.stopPropagation(); this.deleteRow(header.parentElement); }; header.appendChild(newDeleteBtn); const row = header.parentElement.querySelector('.tier-row'); if (row) { row.setAttribute('data-tier', newName); } this.saveState(); } document.body.removeChild(overlay); document.body.removeChild(popup); }; popup.querySelector('.btn-cancel').onclick = () => { document.body.removeChild(overlay); document.body.removeChild(popup); }; overlay.onclick = () => { document.body.removeChild(overlay); document.body.removeChild(popup); }; nameInput.focus(); nameInput.select(); }, rgbToHex: function(rgb) { if (rgb.startsWith('#')) return rgb; const values = rgb.match(/\d+/g); if (!values || values.length < 3) return '#000000'; const r = parseInt(values[0]).toString(16).padStart(2, '0'); const g = parseInt(values[1]).toString(16).padStart(2, '0'); const b = parseInt(values[2]).toString(16).padStart(2, '0'); return '#' + r + g + b; }, addRow: function() { const table = document.getElementById('tierlist-table'); if (!table) return; const tbody = table.querySelector('tbody'); const newRow = document.createElement('tr'); const tierCount = document.querySelectorAll('.tier-row').length; const tierName = 'T' + (tierCount + 1); newRow.innerHTML = ` <th style="width: 100px; background-color: #9e9e9e; color: white; font-size: 20px; text-align: center" class="tier-header" data-tier="${tierName}">${tierName}</th> <td class="tier-row" data-tier="${tierName}"></td> `; tbody.appendChild(newRow); const newTierRow = newRow.querySelector('.tier-row'); newTierRow.setAttribute('data-drop-initialized', 'true'); newTierRow.addEventListener('dragover', (e) => this.handleDragOver(e, newTierRow)); newTierRow.addEventListener('drop', (e) => this.handleDrop(e, newTierRow)); newTierRow.addEventListener('dragleave', (e) => this.handleDragLeave(e, newTierRow)); if (this.editMode) { const header = newRow.querySelector('.tier-header'); header.classList.add('editable'); const deleteBtn = document.createElement('button'); deleteBtn.className = 'delete-row-btn'; deleteBtn.textContent = '删除'; deleteBtn.onclick = (e) => { e.stopPropagation(); this.deleteRow(newRow); }; header.appendChild(deleteBtn); header.onclick = () => this.editTierHeader(header); } this.saveState(); }, deleteRow: function(row) { if (!confirm('确定要删除这一行吗?行内的角色将移回角色池。')) { return; } const tierRow = row.querySelector('.tier-row'); const avatars = Array.from(tierRow.querySelectorAll('.avatar-frame')); const pool = document.getElementById('character-pool'); avatars.forEach(avatar => { pool.appendChild(avatar); }); row.remove(); this.cleanupContainers(); this.saveState(); }, saveState: function() { const state = { rows: [], pool: [] }; document.querySelectorAll('#tierlist-table tbody tr').forEach(row => { const header = row.querySelector('.tier-header'); const tierRow = row.querySelector('.tier-row'); if (!header || !tierRow) return; const rowData = { name: header.getAttribute('data-tier'), bgColor: header.style.backgroundColor, characters: [] }; tierRow.querySelectorAll('.avatar-frame').forEach(avatar => { const charId = this.getCharacterId(avatar); if (charId) { rowData.characters.push(charId); } }); state.rows.push(rowData); }); const pool = document.getElementById('character-pool'); if (pool) { pool.querySelectorAll('.avatar-frame').forEach(avatar => { const charId = this.getCharacterId(avatar); if (charId) { state.pool.push(charId); } }); } try { localStorage.setItem('tierlist-state', JSON.stringify(state)); console.log('状态已保存'); } catch (e) { console.warn('无法保存状态:', e); } }, loadState: function() { try { const stateJson = localStorage.getItem('tierlist-state'); if (!stateJson) { console.log('没有保存的状态'); return; } const state = JSON.parse(stateJson); console.log('加载保存的状态:', state); const tbody = document.querySelector('#tierlist-table tbody'); const rows = Array.from(tbody.querySelectorAll('tr')); if (state.rows && state.rows.length > 0) { rows.forEach((row, index) => { if (index >= state.rows.length) { row.remove(); } else { const header = row.querySelector('.tier-header'); const savedRow = state.rows[index]; if (header && savedRow) { header.textContent = savedRow.name; header.setAttribute('data-tier', savedRow.name); header.style.backgroundColor = savedRow.bgColor; const tierRow = row.querySelector('.tier-row'); if (tierRow) { tierRow.setAttribute('data-tier', savedRow.name); tierRow.innerHTML = ''; } } } }); for (let i = rows.length; i < state.rows.length; i++) { const savedRow = state.rows[i]; const newRow = document.createElement('tr'); newRow.innerHTML = ` <th style="width: 100px; background-color: ${savedRow.bgColor}; color: white; font-size: 20px; text-align: center" class="tier-header" data-tier="${savedRow.name}">${savedRow.name}</th> <td class="tier-row" data-tier="${savedRow.name}"></td> `; tbody.appendChild(newRow); const newTierRow = newRow.querySelector('.tier-row'); newTierRow.setAttribute('data-drop-initialized', 'true'); newTierRow.addEventListener('dragover', (e) => this.handleDragOver(e, newTierRow)); newTierRow.addEventListener('drop', (e) => this.handleDrop(e, newTierRow)); newTierRow.addEventListener('dragleave', (e) => this.handleDragLeave(e, newTierRow)); } } setTimeout(() => { state.rows.forEach((rowData, index) => { const tierRow = document.querySelectorAll('.tier-row')[index]; if (!tierRow) return; rowData.characters.forEach(charId => { const avatar = this.findAvatarById(charId); if (avatar && avatar.parentElement) { tierRow.appendChild(avatar); } }); }); this.cleanupContainers(); console.log('状态加载完成'); }, 200); } catch (e) { console.warn('无法加载状态:', e); } }, getCharacterId: function(avatar) { const img = avatar.querySelector('img'); if (img) { const src = img.getAttribute('src'); if (src) { const match = src.match(/\/(\d+)\./); if (match) return match[1]; } } const name = avatar.querySelector('.avatar-name'); if (name) { return name.textContent.trim(); } return avatar.outerHTML; }, findAvatarById: function(charId) { const allAvatars = document.querySelectorAll('.avatar-frame'); for (let avatar of allAvatars) { if (this.getCharacterId(avatar) === charId) { return avatar; } } return null; }, saveTierlist: function() { const table = document.getElementById('tierlist-table'); if (!table) { alert('未找到 Tierlist 表格!'); return; } if (typeof html2canvas === 'undefined') { alert('正在加载图片生成库,请稍后再试...'); return; } const controls = document.querySelector('.tierlist-controls'); const poolContainer = document.querySelector('.character-pool-container'); const originalControlsDisplay = controls ? controls.style.display : ''; const originalPoolDisplay = poolContainer ? poolContainer.style.display : ''; const deleteButtons = document.querySelectorAll('.delete-row-btn'); deleteButtons.forEach(btn => btn.style.display = 'none'); if (controls) controls.style.display = 'none'; if (poolContainer) poolContainer.style.display = 'none'; html2canvas(table, { scale: 2, backgroundColor: '#ffffff', logging: false, useCORS: true, allowTaint: true }).then(canvas => { if (controls) controls.style.display = originalControlsDisplay; if (poolContainer) poolContainer.style.display = originalPoolDisplay; deleteButtons.forEach(btn => btn.style.display = ''); const link = document.createElement('a'); const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5); link.download = 'tierlist_' + timestamp + '.png'; link.href = canvas.toDataURL('image/png'); link.click(); }).catch(err => { console.error('生成图片失败:', err); if (controls) controls.style.display = originalControlsDisplay; if (poolContainer) poolContainer.style.display = originalPoolDisplay; deleteButtons.forEach(btn => btn.style.display = ''); alert('生成图片失败,请查看控制台了解详情'); }); }, resetTierlist: function() { if (!confirm('确定要重置所有排列吗?此操作不可撤销。')) { return; } const pool = document.getElementById('character-pool'); if (!pool) { alert('未找到角色池!'); return; } const allAvatars = Array.from(document.querySelectorAll('.avatar-frame')); document.querySelectorAll('.tier-row').forEach(row => { row.innerHTML = ''; }); pool.innerHTML = ''; allAvatars.forEach(avatar => { pool.appendChild(avatar); const img = avatar.querySelector('img'); if (img) { img.style.opacity = '1'; } }); this.cleanupContainers(); try { localStorage.removeItem('tierlist-state'); console.log('状态已清除'); } catch (e) { console.warn('无法清除状态:', e); } alert('重置完成!'); } }; window.TierlistMakerInitialized = true; window.TierlistMaker = TierlistMaker; TierlistMaker.init(); // 添加手动加载状态的按钮功能 window.loadTierlistState = function() { if (window.TierlistMaker) { window.TierlistMaker.loadState(); } }; })(); </script> </includeonly>
返回
微件:TierListMaker
。