卡厄思
梦
境
菜单
首页
回到首页
WIKI工具
全站样式
全站JS
修改导航栏
测试
沙盒
可视化管理器
战斗员管理器
卡牌管理器
伙伴管理器
装备管理器
词典管理器
图鉴
战斗员
伙伴
装备
怪物卡牌
中立卡牌
词典
小工具
配队模拟器
节奏榜生成器
搜索
链入页面
相关更改
特殊页面
页面信息
最近更改
登录
微件
查看“︁TierListMaker”︁的源代码
←
微件:TierListMaker
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您没有权限编辑
微件
命名空间内的页面。
您可以查看和复制此页面的源代码。
<includeonly> <style> .tier-row { position: relative; background-color: #fafafa; border: 2px dashed transparent; transition: all 0.2s ease; min-height: 120px; } .tier-row.drag-over { background-color: #e3f2fd; border-color: #2196F3; } #character-pool { position: relative; min-height: 150px; } #character-pool.drag-over { background-color: #fff3e0; } .tierlist-table { width: 100%; table-layout: fixed; } .tierlist-table th { width: 100px; position: relative; } .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; } </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, init: function() { // 等待DOM完全加载 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this.setup()); } else { setTimeout(() => this.setup(), 100); } }, setup: function() { this.initDragAndDrop(); this.initButtons(); this.loadState(); }, initDragAndDrop: function() { const avatars = document.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)); } }); // 为tier行添加拖放事件 const tierRows = document.querySelectorAll('.tier-row'); 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)); } }); // 为角色池添加拖放事件 const characterPool = document.getElementById('character-pool'); 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)); } }, handleDragStart: function(e, element) { this.draggedElement = element; this.sourceContainer = element.parentElement; element.classList.add('dragging'); e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/plain', element.getAttribute('data-character-id') || 'drag'); }, handleDragEnd: function(e, element) { element.classList.remove('dragging'); // 移除所有drag-over类 document.querySelectorAll('.drag-over').forEach(el => { el.classList.remove('drag-over'); }); // 保存状态 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) { if (e.target === element) { element.classList.remove('drag-over'); } }, handleDrop: function(e, element) { e.preventDefault(); e.stopPropagation(); 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'; } } 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'); // 为所有tier header添加编辑功能 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); header.querySelector('.delete-row-btn').remove(); header.textContent = newName; header.style.backgroundColor = newColor; // 重新添加删除按钮 const deleteBtn = document.createElement('button'); deleteBtn.className = 'delete-row-btn'; deleteBtn.textContent = '删除'; deleteBtn.onclick = (e) => { e.stopPropagation(); this.deleteRow(header.parentElement); }; header.appendChild(deleteBtn); // 更新对应的tier-row 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 style="padding: 10px; min-height: 120px;" 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 = tierRow.querySelectorAll('.avatar-frame'); const pool = document.getElementById('character-pool'); // 将角色移回角色池 avatars.forEach(avatar => { pool.appendChild(avatar); }); // 删除行 row.remove(); 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)); } catch (e) { console.warn('无法保存状态:', e); } }, loadState: function() { try { const stateJson = localStorage.getItem('tierlist-state'); if (!stateJson) return; const state = JSON.parse(stateJson); // 先清空所有行(保留第一行作为模板) 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); } } } }); // 如果保存的行数多于当前行数,添加新行 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 style="padding: 10px; min-height: 120px;" 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) { tierRow.appendChild(avatar); } }); }); }, 100); } catch (e) { console.warn('无法加载状态:', e); } }, getCharacterId: function(avatar) { // 尝试多种方式获取角色ID 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 = document.querySelectorAll('.avatar-frame'); document.querySelectorAll('.tier-row').forEach(row => { row.innerHTML = ''; }); allAvatars.forEach(avatar => { pool.appendChild(avatar); const img = avatar.querySelector('img'); if (img) { img.style.opacity = '1'; } }); // 清除保存的状态 try { localStorage.removeItem('tierlist-state'); } catch (e) { console.warn('无法清除状态:', e); } } }; // 标记已初始化 window.TierlistMakerInitialized = true; window.TierlistMaker = TierlistMaker; // 自动初始化 TierlistMaker.init(); })(); </script> </includeonly>
返回
微件:TierListMaker
。