TierListMaker.js:修订间差异
来自卡厄思梦境WIKI
无编辑摘要 标签:已被回退 |
无编辑摘要 标签:已被回退 |
||
| 第1行: | 第1行: | ||
(function() { | (function() { | ||
'use strict'; | 'use strict'; | ||
// | // 等待页面完全加载 | ||
if ( | $(document).ready(function() { | ||
// 延迟执行,确保 SMW 查询结果已渲染 | |||
setTimeout(function() { | |||
if ($('.wikitable').length) { | |||
loadDragula(function() { | |||
initTierList(); | |||
}); | |||
} | |||
}, 1000); | |||
}); | }); | ||
| 第42行: | 第39行: | ||
function initTierList() { | function initTierList() { | ||
console.log('=== 初始化 Tier List ==='); | |||
addStyles(); | addStyles(); | ||
createAvatarPool(); | createAvatarPool(); | ||
| 第101行: | 第99行: | ||
border-radius: 4px; | border-radius: 4px; | ||
margin-bottom: 5px; | margin-bottom: 5px; | ||
object-fit: cover; | |||
} | } | ||
| 第109行: | 第108行: | ||
word-break: break-word; | word-break: break-word; | ||
max-width: 80px; | max-width: 80px; | ||
line-height: 1.2; | |||
} | } | ||
| 第116行: | 第116行: | ||
} | } | ||
.wikitable td: | .wikitable td:not(:first-child) { | ||
background: #fafafa; | background: #fafafa !important; | ||
padding: 10px; | padding: 10px !important; | ||
display: flex; | display: flex; | ||
flex-wrap: wrap; | flex-wrap: wrap; | ||
| 第125行: | 第125行: | ||
} | } | ||
.wikitable td: | .wikitable td:not(:first-child).gu-over { | ||
background: #e8f4f8; | background: #e8f4f8 !important; | ||
} | } | ||
| 第211行: | 第211行: | ||
max-width: 500px; | max-width: 500px; | ||
width: 90%; | width: 90%; | ||
max-height: 80vh; | |||
overflow-y: auto; | |||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3); | box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3); | ||
animation: slideUp 0.3s; | animation: slideUp 0.3s; | ||
| 第297行: | 第299行: | ||
} | } | ||
. | .saved-list-item { | ||
border: 1px solid #ddd; | |||
border-radius: 6px; | |||
border: | padding: 10px; | ||
padding: | margin-bottom: 10px; | ||
cursor: pointer; | cursor: pointer; | ||
transition: all 0.2s; | |||
} | } | ||
. | .saved-list-item:hover { | ||
background: # | background: #f0f8ff; | ||
border-color: #4a9eff; | |||
} | } | ||
| 第355行: | 第356行: | ||
var $pool = $('<div>') | var $pool = $('<div>') | ||
.attr('id', 'avatar-pool') | .attr('id', 'avatar-pool') | ||
.html('<h3 style="width: 100%; margin: 0 0 10px 0; color: #666;">角色池 - 拖拽角色到对应层级</h3>'); | .html('<h3 style="width: 100%; margin: 0 0 10px 0; color: #666;">📦 角色池 - 拖拽角色到对应层级</h3>'); | ||
$('.wikitable').before($pool); | // 在表格前插入角色池 | ||
var $table = $('.wikitable').first(); | |||
if ($table.length) { | |||
$table.before($pool); | |||
console.log('角色池已创建'); | |||
} | |||
} | } | ||
function processAvatars() { | function processAvatars() { | ||
console.log('开始处理角色...'); | |||
$( | // 查找所有符合条件的图片 | ||
// 适配多种可能的图片结构 | |||
var $images = $('img').filter(function() { | |||
var src = $(this).attr('src') || ''; | |||
var alt = $(this).attr('alt') || ''; | |||
// 匹配角色头像图片 | |||
return src.includes('Face_character') || | |||
src.includes('Character_') || | |||
alt.includes('character') || | |||
$(this).closest('.character-icon').length > 0; | |||
}); | |||
console.log('找到', $images.length, '个角色图片'); | |||
if ($images.length === 0) { | |||
// 如果没找到,尝试其他选择器 | |||
$images = $('.wikitable').nextAll('img, a img, div img').filter(function() { | |||
return $(this).attr('src') && !$(this).closest('#avatar-pool').length; | |||
}); | |||
console.log('备用查找到', $images.length, '个图片'); | |||
} | |||
var processedCount = 0; | |||
$images.each(function() { | |||
var $img = $(this); | var $img = $(this); | ||
var $ | |||
var | // 跳过已经在角色池中的 | ||
if ($img.closest('#avatar-pool').length > 0) { | |||
return; | |||
} | |||
// 跳过已经在表格中的 | |||
if ($img.closest('.wikitable').length > 0) { | |||
return; | |||
} | |||
var imgSrc = $img.attr('src'); | |||
var imgAlt = $img.attr('alt') || ''; | |||
var imgTitle = $img.attr('title') || ''; | |||
// 获取角色名称 | // 获取角色名称 | ||
var name = $img. | var name = imgTitle || imgAlt || ''; | ||
// 尝试从父元素获取名称 | |||
if (!name) { | |||
var $parent = $img.parent(); | |||
name = $parent.attr('title') || $parent.text().trim() || ''; | |||
} | |||
// 如果还是没有名称,从图片路径提取 | |||
if (!name && imgSrc) { | |||
var match = imgSrc.match(/Face_character_(.+?)\.png/); | |||
if (match) { | |||
name = match[1]; | |||
} | |||
} | |||
console.log('处理角色:', name, '图片:', imgSrc); | |||
// 创建头像框架 | // 创建头像框架 | ||
var $frame = $('<div>') | var $frame = $('<div>') | ||
.addClass('avatar-frame') | .addClass('avatar-frame') | ||
.append($img.clone()) | .append($img.clone().css({ | ||
'width': '64px', | |||
'height': '64px' | |||
})) | |||
.append($('<div>').addClass('avatar-name').text(name)); | .append($('<div>').addClass('avatar-name').text(name)); | ||
| 第380行: | 第441行: | ||
var uniqueId = 'avatar_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); | var uniqueId = 'avatar_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); | ||
$frame.attr('data-tier-id', uniqueId); | $frame.attr('data-tier-id', uniqueId); | ||
$frame.attr('data-avatar-src', imgSrc); | |||
$frame.attr('data-avatar-name', name); | |||
// 添加到头像池 | // 添加到头像池 | ||
$('#avatar-pool').append($frame); | $('#avatar-pool').append($frame); | ||
processedCount++; | |||
}); | }); | ||
console.log('成功处理', processedCount, '个角色'); | |||
if (processedCount === 0) { | |||
showNotification('⚠️ 未找到角色图片,请确认页面已完全加载', 'error'); | |||
} else { | |||
showNotification('✅ 已加载 ' + processedCount + ' 个角色', 'success'); | |||
} | } | ||
} | } | ||
function setupDragAndDrop() { | function setupDragAndDrop() { | ||
var containers = [ | console.log('设置拖拽功能...'); | ||
var containers = []; | |||
// 添加头像池 | |||
containers.push(document.getElementById('avatar-pool')); | |||
// 添加所有tier单元格 | |||
$('.wikitable td:nth-child(2)').each(function() { | |||
containers.push(this); | |||
}); | |||
console.log('容器数量:', containers.length); | |||
var drake = dragula(containers, { | var drake = dragula(containers, { | ||
moves: function(el, source, handle, sibling) { | |||
return $(el). | return $(el).hasClass('avatar-frame'); | ||
}, | }, | ||
accepts: function(el, target, source, sibling) { | |||
return | return true; | ||
}, | }, | ||
invalid: function(el, handle) { | |||
return | return false; | ||
}, | }, | ||
direction: 'horizontal', | |||
copy: false, | copy: false, | ||
revertOnSpill: true | copySortSource: false, | ||
revertOnSpill: true, | |||
removeOnSpill: false, | |||
mirrorContainer: document.body | |||
}); | }); | ||
drake.on('drop', function(el, target, source, sibling) { | drake.on('drop', function(el, target, source, sibling) { | ||
console.log('拖拽完成:', el, '从', source, '到', target); | |||
var $el = $(el); | var $el = $(el); | ||
var $target = $(target); | var $target = $(target); | ||
// 如果拖到tier单元格中,添加标记 | |||
if ($target.is('td')) { | |||
// | |||
if ($target.is(' | |||
$el.addClass('in-tier'); | $el.addClass('in-tier'); | ||
} else if ($target.is('#avatar-pool')) { | } else if ($target.is('#avatar-pool')) { | ||
$el.removeClass('in-tier'); | $el.removeClass('in-tier'); | ||
} | } | ||
showNotification('已移动角色', 'info'); | |||
}); | |||
drake.on('over', function(el, container, source) { | |||
$(container).addClass('gu-over'); | |||
}); | |||
drake.on('out', function(el, container, source) { | |||
$(container).removeClass('gu-over'); | |||
}); | }); | ||
console.log('拖拽功能设置完成'); | |||
} | } | ||
| 第439行: | 第522行: | ||
var $button = $('<button>') | var $button = $('<button>') | ||
.attr('id', 'export-tierlist-btn') | .attr('id', 'export-tierlist-btn') | ||
. | .html('📸 导出为图片') | ||
.click(function() { | .click(function() { | ||
loadHtml2Canvas(function() { | loadHtml2Canvas(function() { | ||
| 第446行: | 第529行: | ||
}); | }); | ||
$(' | $('#avatar-pool').after($button); | ||
} | } | ||
| 第452行: | 第535行: | ||
var $saveBtn = $('<button>') | var $saveBtn = $('<button>') | ||
.attr('id', 'save-tierlist-btn') | .attr('id', 'save-tierlist-btn') | ||
. | .html('💾 保存榜单') | ||
.click(function() { | .click(function() { | ||
saveTierListData(); | |||
}); | }); | ||
var $loadBtn = $('<button>') | var $loadBtn = $('<button>') | ||
.attr('id', 'load-tierlist-btn') | .attr('id', 'load-tierlist-btn') | ||
. | .html('📂 加载榜单') | ||
.click(function() { | .click(function() { | ||
showLoadDialog(); | showLoadDialog(); | ||
| 第466行: | 第549行: | ||
var $shareBtn = $('<button>') | var $shareBtn = $('<button>') | ||
.attr('id', 'share-tierlist-btn') | .attr('id', 'share-tierlist-btn') | ||
. | .html('🔗 分享榜单') | ||
.click(function() { | .click(function() { | ||
showShareDialog(); | showShareDialog(); | ||
| 第474行: | 第557行: | ||
} | } | ||
function | function saveTierListData() { | ||
console.log('开始保存榜单...'); | |||
var tierData = collectTierData(); | var tierData = collectTierData(); | ||
console.log(' | console.log('收集到的数据:', tierData); | ||
console.log(' | console.log('层级数:', tierData.tiers.length); | ||
console.log('池中角色数:', tierData.pool.length); | console.log('池中角色数:', tierData.pool.length); | ||
var totalAvatars = tierData.pool.length; | var totalAvatars = tierData.pool.length; | ||
tierData.tiers.forEach(function(tier) { | tierData.tiers.forEach(function(tier) { | ||
| 第494行: | 第578行: | ||
} | } | ||
if (tierData.tiers.length === 0) { | if (tierData.tiers.length === 0 || tierData.tiers.every(t => t.avatars.length === 0)) { | ||
var confirm = window.confirm('您还没有将任何角色放入层级中,确定要保存空榜单吗?'); | var confirm = window.confirm('您还没有将任何角色放入层级中,确定要保存空榜单吗?'); | ||
if (!confirm) { | if (!confirm) { | ||
| 第510行: | 第594行: | ||
}; | }; | ||
try { | |||
localStorage.setItem('tierlist_' + listId, JSON.stringify(saveData)); | |||
console.log('保存成功,ID:', listId); | |||
showSaveSuccessDialog(listId); | |||
} catch (e) { | |||
console.error('保存失败:', e); | |||
alert('保存失败:' + e.message); | |||
} | |||
console. | |||
} | } | ||
| 第531行: | 第612行: | ||
// 收集各个tier中的数据 | // 收集各个tier中的数据 | ||
$('.wikitable tr').each(function() { | $('.wikitable tr').each(function() { | ||
var $ | var $row = $(this); | ||
var $cells = $row.find('td, th'); | |||
if ($cells.length >= 2) { | if ($cells.length >= 2) { | ||
var | // 第一个单元格是层级名称 | ||
var $tierNameCell = $cells.eq(0); | |||
var tierName = $tierNameCell.text().trim(); | |||
// 第二个单元格包含角色 | |||
var $tierCell = $cells.eq(1); | var $tierCell = $cells.eq(1); | ||
var $avatarsInTier = $tierCell.find('.avatar-frame'); | var $avatarsInTier = $tierCell.find('.avatar-frame'); | ||
| 第545行: | 第630行: | ||
$avatarsInTier.each(function() { | $avatarsInTier.each(function() { | ||
var | var avatarData = getAvatarData($(this)); | ||
if ( | if (avatarData) { | ||
avatars.push( | avatars.push(avatarData); | ||
console.log('收集角色:', | console.log('收集角色:', avatarData.name); | ||
} | } | ||
}); | }); | ||
| 第565行: | 第650行: | ||
// 收集头像池中的数据 | // 收集头像池中的数据 | ||
$('#avatar-pool .avatar-frame').each(function() { | $('#avatar-pool .avatar-frame').each(function() { | ||
var | var avatarData = getAvatarData($(this)); | ||
if ( | if (avatarData) { | ||
data.pool.push( | data.pool.push(avatarData); | ||
} | } | ||
}); | }); | ||
console.log(' | console.log('最终数据:', data); | ||
return data; | return data; | ||
} | } | ||
function | function getAvatarData($avatar) { | ||
return { | |||
tierId: $avatar.attr('data-tier-id'), | |||
src: $avatar.attr('data-avatar-src') || $avatar.find('img').attr('src'), | |||
name: $avatar.attr('data-avatar-name') || $avatar.find('.avatar-name').text().trim(), | |||
html: $avatar.prop('outerHTML') | |||
}; | |||
} | |||
} | } | ||
| 第653行: | 第704行: | ||
$('body').append($overlay); | $('body').append($overlay); | ||
$('#copy-url-btn').click(function() { | $('#copy-url-btn').click(function() { | ||
var $input = $dialog.find('input'); | var $input = $dialog.find('input'); | ||
| 第661行: | 第711行: | ||
}); | }); | ||
setTimeout(function() { | setTimeout(function() { | ||
$dialog.find('input').select(); | $dialog.find('input').select(); | ||
| 第771行: | 第820行: | ||
console.log('尝试加载榜单 ID:', listId); | console.log('尝试加载榜单 ID:', listId); | ||
if (!savedData) { | if (!savedData) { | ||
| 第795行: | 第843行: | ||
console.log('应用榜单数据:', tierData); | console.log('应用榜单数据:', tierData); | ||
// | // 首先将所有角色移回池中 | ||
$('.wikitable td | $('.wikitable td .avatar-frame').each(function() { | ||
$(this).removeClass('in-tier'); | $(this).removeClass('in-tier'); | ||
$('#avatar-pool').append($(this)); | $('#avatar-pool').append($(this)); | ||
}); | }); | ||
// 应用tier数据 | // 应用tier数据 | ||
| 第807行: | 第853行: | ||
console.log('处理层级', index, ':', tier.name, '包含', tier.avatars.length, '个角色'); | console.log('处理层级', index, ':', tier.name, '包含', tier.avatars.length, '个角色'); | ||
var $ | // 找到对应的tier单元格 | ||
var $tierRow = $('.wikitable tr').eq(index); | |||
var $tierCell = $tierRow.find('td:nth-child(2)'); | |||
if ($tierCell.length === 0) { | |||
console.warn('未找到层级单元格,跳过'); | |||
return; | |||
} | |||
// 清空该单元格 | |||
$tierCell.empty(); | |||
// | // 将角色移动到该层级 | ||
tier.avatars.forEach(function(avatarData) { | |||
var $ | var $avatar = findAvatarByIdentifier(avatarData); | ||
if ($ | |||
if ($avatar && $avatar.length > 0) { | |||
if ( | console.log('找到角色:', avatarData.name, '移动到', tier.name); | ||
$ | $avatar.addClass('in-tier'); | ||
$tierCell.append($avatar); | |||
} else { | |||
console.warn('未找到角色:', avatarData.name); | |||
// 如果找不到,尝试从保存的HTML重建 | |||
if (avatarData.html) { | |||
try { | |||
var $newAvatar = $(avatarData.html); | |||
$newAvatar.addClass('in-tier'); | |||
$tierCell.append($newAvatar); | |||
console.log('从HTML重建角色:', avatarData.name); | |||
} catch (e) { | |||
console.error('重建角色失败:', e); | |||
} | |||
} | } | ||
} | } | ||
}); | }); | ||
}); | |||
// 处理池中的角色 | |||
if (tierData.pool && tierData.pool.length > 0) { | |||
console.log('处理角色池,包含', tierData.pool.length, '个角色'); | |||
tierData.pool.forEach(function(avatarData) { | |||
var $avatar = findAvatarByIdentifier(avatarData); | |||
if ($avatar && $avatar.length > 0) { | |||
$avatar.removeClass('in-tier'); | |||
if ($avatar.closest('#avatar-pool').length === 0) { | |||
$('#avatar-pool').append($avatar); | |||
$ | |||
} | } | ||
} | } | ||
} | }); | ||
} | |||
} | |||
console.log(' | console.log('榜单数据应用完成'); | ||
} | } | ||
function findAvatarByIdentifier( | function findAvatarByIdentifier(identifier) { | ||
console.log('查找角色:', identifier); | |||
if (!identifier) { | |||
return null; | |||
} | |||
try { | try { | ||
var $found = null; | var $found = null; | ||
// 优先通过tierId查找 | |||
if (identifier.tierId) { | |||
$found = $('[data-tier-id="' + identifier.tierId + '"]'); | |||
if ($found.length > 0) { | |||
console.log('通过tierId找到角色'); | |||
return $found; | |||
} | |||
} | |||
// 通过图片src和名称查找 | |||
$('.avatar-frame').each(function() { | $('.avatar-frame').each(function() { | ||
if ($found) return false; | |||
var $avatar = $(this); | var $avatar = $(this); | ||
var src = $avatar.attr('data-avatar-src') || $avatar.find('img').attr('src'); | |||
var name = $avatar.attr('data-avatar-name') || $avatar.find('.avatar-name').text().trim(); | |||
if (identifier.src && src === identifier.src) { | |||
if (!identifier.name || name === identifier.name) { | |||
if (identifier.src && | |||
if (identifier.name | |||
$found = $avatar; | $found = $avatar; | ||
console.log('通过src找到角色:', name); | |||
return false; | return false; | ||
} | } | ||
} | } | ||
if (identifier.name && name === identifier.name) { | |||
if (identifier.name | if (!identifier.src || src === identifier.src) { | ||
if ( | |||
$found = $avatar; | $found = $avatar; | ||
console.log('通过name找到角色:', name); | |||
return false; | return false; | ||
} | } | ||
| 第883行: | 第956行: | ||
return $found; | return $found; | ||
} catch (e) { | } catch (e) { | ||
console.error(' | console.error('查找角色失败:', e); | ||
return null; | return null; | ||
} | } | ||
| 第889行: | 第962行: | ||
function showShareDialog() { | function showShareDialog() { | ||
var tierData = collectTierData(); | var tierData = collectTierData(); | ||
var listId = generateUniqueId(); | var listId = generateUniqueId(); | ||
| 第902行: | 第974行: | ||
localStorage.setItem('tierlist_' + listId, JSON.stringify(saveData)); | localStorage.setItem('tierlist_' + listId, JSON.stringify(saveData)); | ||
var pageUrl = window.location.origin + window.location.pathname; | var pageUrl = window.location.origin + window.location.pathname; | ||
var fullUrl = pageUrl + '?tierlist=' + listId; | var fullUrl = pageUrl + '?tierlist=' + listId; | ||
| 第934行: | 第1,005行: | ||
$('body').append($overlay); | $('body').append($overlay); | ||
$('#share-copy-btn').click(function() { | $('#share-copy-btn').click(function() { | ||
var $input = $('#share-url-input'); | var $input = $('#share-url-input'); | ||
| 第942行: | 第1,012行: | ||
}); | }); | ||
setTimeout(function() { | setTimeout(function() { | ||
$('#share-url-input').select(); | $('#share-url-input').select(); | ||
| 第956行: | 第1,025行: | ||
setTimeout(function() { | setTimeout(function() { | ||
if (loadTierListData(tierlistId)) { | if (loadTierListData(tierlistId)) { | ||
showNotification('已自动加载分享的榜单', ' | showNotification('✅ 已自动加载分享的榜单', 'success'); | ||
} else { | } else { | ||
showNotification('无法加载分享的榜单', 'error'); | showNotification('❌ 无法加载分享的榜单', 'error'); | ||
} | } | ||
}, | }, 1500); | ||
} | } | ||
} | } | ||
| 第999行: | 第1,068行: | ||
function captureTierList() { | function captureTierList() { | ||
var $table = $('.wikitable').first().clone(); | var $table = $('.wikitable').first().clone(); | ||
// 确保表格中的图片样式正确 | |||
$table.find('.avatar-frame img').css({ | |||
'width': '64px', | |||
'height': '64px', | |||
'display': 'block' | |||
}); | |||
// 移除空的tier单元格中的占位内容 | // 移除空的tier单元格中的占位内容 | ||
$table.find('td:nth-child(2)').each(function() { | $table.find('td:nth-child(2)').each(function() { | ||
if ($(this).find('.avatar-frame').length === 0) { | if ($(this).find('.avatar-frame').length === 0) { | ||
$(this).empty(); | $(this).empty().css({ | ||
'min-height': '80px', | |||
'background': '#fafafa' | |||
}); | |||
} | } | ||
}); | |||
// 优化表格样式 | |||
$table.css({ | |||
'border-collapse': 'collapse', | |||
'width': '100%' | |||
}); | |||
$table.find('th, td').css({ | |||
'border': '2px solid #333', | |||
'padding': '10px' | |||
}); | }); | ||
| 第1,014行: | 第1,104行: | ||
top: '0', | top: '0', | ||
background: 'white', | background: 'white', | ||
padding: ' | padding: '30px', | ||
minWidth: ' | minWidth: '900px', | ||
fontFamily: 'Arial, sans-serif' | |||
}) | }) | ||
.append($table); | .append($table); | ||
| 第1,023行: | 第1,114行: | ||
// 添加标题 | // 添加标题 | ||
var $title = $('<h2>') | var $title = $('<h2>') | ||
.text(' | .text('我的角色Tier榜单') | ||
.css({ | .css({ | ||
textAlign: 'center', | textAlign: 'center', | ||
marginBottom: '20px', | marginBottom: '20px', | ||
color: '#333' | color: '#333', | ||
fontSize: '28px', | |||
fontWeight: 'bold' | |||
}); | |||
// 添加时间戳 | |||
var $timestamp = $('<div>') | |||
.text('生成时间: ' + new Date().toLocaleString('zh-CN')) | |||
.css({ | |||
textAlign: 'center', | |||
marginBottom: '15px', | |||
color: '#666', | |||
fontSize: '14px' | |||
}); | }); | ||
$container.prepend($title); | $container.prepend($timestamp).prepend($title); | ||
html2canvas($container[0], { | html2canvas($container[0], { | ||
| 第1,037行: | 第1,140行: | ||
logging: false, | logging: false, | ||
useCORS: true, | useCORS: true, | ||
allowTaint: true | allowTaint: true, | ||
imageTimeout: 0 | |||
}).then(function(canvas) { | }).then(function(canvas) { | ||
$container.remove(); | $container.remove(); | ||
canvas.toBlob(function(blob) { | canvas.toBlob(function(blob) { | ||
var url = URL.createObjectURL(blob); | var url = URL.createObjectURL(blob); | ||
| 第1,052行: | 第1,155行: | ||
URL.revokeObjectURL(url); | URL.revokeObjectURL(url); | ||
showNotification('榜单图片已导出!', 'success'); | showNotification('📸 榜单图片已导出!', 'success'); | ||
}); | }); | ||
}).catch(function(error) { | }).catch(function(error) { | ||
| 第1,062行: | 第1,165行: | ||
})(); | })(); | ||
2025年10月8日 (三) 13:02的版本
(function() {
'use strict';
// 等待页面完全加载
$(document).ready(function() {
// 延迟执行,确保 SMW 查询结果已渲染
setTimeout(function() {
if ($('.wikitable').length) {
loadDragula(function() {
initTierList();
});
}
}, 1000);
});
function loadDragula(callback) {
// 加载CSS
if (!$('#dragula-css').length) {
$('<link>')
.attr('id', 'dragula-css')
.attr('rel', 'stylesheet')
.attr('href', 'https://cdn.jsdelivr.net/npm/dragula@3.7.3/dist/dragula.min.css')
.appendTo('head');
}
// 加载JS
if (typeof dragula === 'undefined') {
$.getScript('https://cdn.jsdelivr.net/npm/dragula@3.7.3/dist/dragula.min.js')
.done(function() {
callback();
})
.fail(function() {
console.error('加载Dragula失败');
});
} else {
callback();
}
}
function initTierList() {
console.log('=== 初始化 Tier List ===');
addStyles();
createAvatarPool();
processAvatars();
setupDragAndDrop();
addExportButton();
addSaveLoadButtons();
checkUrlForTierList();
}
function addStyles() {
var css = `
#avatar-pool {
background: #f5f5f5;
border: 2px dashed #ccc;
border-radius: 8px;
padding: 15px;
margin: 20px 0;
min-height: 120px;
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: flex-start;
}
#avatar-pool.gu-over {
background: #e8f4f8;
border-color: #4a9eff;
}
.avatar-frame {
display: inline-flex;
flex-direction: column;
align-items: center;
padding: 8px;
background: white;
border: 2px solid #ddd;
border-radius: 8px;
cursor: move;
transition: all 0.2s;
margin: 4px;
min-width: 80px;
}
.avatar-frame:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
border-color: #4a9eff;
}
.avatar-frame.gu-transit {
opacity: 0.8;
transform: scale(1.05);
}
.avatar-frame img {
width: 64px;
height: 64px;
border-radius: 4px;
margin-bottom: 5px;
object-fit: cover;
}
.avatar-name {
font-size: 12px;
text-align: center;
color: #333;
word-break: break-word;
max-width: 80px;
line-height: 1.2;
}
.wikitable td {
vertical-align: top;
min-height: 100px;
}
.wikitable td:not(:first-child) {
background: #fafafa !important;
padding: 10px !important;
display: flex;
flex-wrap: wrap;
gap: 8px;
align-content: flex-start;
}
.wikitable td:not(:first-child).gu-over {
background: #e8f4f8 !important;
}
.gu-mirror {
cursor: grabbing !important;
opacity: 0.9;
z-index: 9999 !important;
}
#export-tierlist-btn,
#save-tierlist-btn,
#load-tierlist-btn,
#share-tierlist-btn {
margin: 10px 5px;
padding: 12px 24px;
font-size: 16px;
font-weight: bold;
border: none;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
color: white;
}
#export-tierlist-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
#export-tierlist-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}
#save-tierlist-btn {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
#save-tierlist-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(245, 87, 108, 0.4);
}
#load-tierlist-btn {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
#load-tierlist-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(79, 172, 254, 0.4);
}
#share-tierlist-btn {
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
}
#share-tierlist-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(67, 233, 123, 0.4);
}
.tier-dialog-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
animation: fadeIn 0.3s;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.tier-dialog {
background: white;
border-radius: 12px;
padding: 30px;
max-width: 500px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
animation: slideUp 0.3s;
}
@keyframes slideUp {
from {
transform: translateY(50px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.tier-dialog h3 {
margin: 0 0 20px 0;
color: #333;
font-size: 24px;
}
.tier-dialog input {
width: 100%;
padding: 12px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 16px;
margin-bottom: 20px;
box-sizing: border-box;
}
.tier-dialog input:focus {
outline: none;
border-color: #4a9eff;
}
.tier-dialog-buttons {
display: flex;
gap: 10px;
justify-content: flex-end;
}
.tier-dialog-btn {
padding: 10px 20px;
border: none;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
transition: all 0.3s;
}
.tier-dialog-btn-primary {
background: #4a9eff;
color: white;
}
.tier-dialog-btn-primary:hover {
background: #3a8eef;
}
.tier-dialog-btn-secondary {
background: #e0e0e0;
color: #333;
}
.tier-dialog-btn-secondary:hover {
background: #d0d0d0;
}
.tier-info-box {
background: #f0f8ff;
border: 2px solid #4a9eff;
border-radius: 8px;
padding: 15px;
margin: 15px 0;
}
.tier-info-box p {
margin: 8px 0;
color: #333;
}
.tier-info-box strong {
color: #4a9eff;
}
.saved-list-item {
border: 1px solid #ddd;
border-radius: 6px;
padding: 10px;
margin-bottom: 10px;
cursor: pointer;
transition: all 0.2s;
}
.saved-list-item:hover {
background: #f0f8ff;
border-color: #4a9eff;
}
.tier-notification {
position: fixed;
top: 20px;
right: 20px;
padding: 15px 25px;
border-radius: 8px;
color: white;
font-size: 16px;
z-index: 10001;
animation: slideInRight 0.3s;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.tier-notification.success {
background: #4caf50;
}
.tier-notification.error {
background: #f44336;
}
.tier-notification.info {
background: #2196f3;
}
`;
$('<style>').text(css).appendTo('head');
}
function createAvatarPool() {
var $pool = $('<div>')
.attr('id', 'avatar-pool')
.html('<h3 style="width: 100%; margin: 0 0 10px 0; color: #666;">📦 角色池 - 拖拽角色到对应层级</h3>');
// 在表格前插入角色池
var $table = $('.wikitable').first();
if ($table.length) {
$table.before($pool);
console.log('角色池已创建');
}
}
function processAvatars() {
console.log('开始处理角色...');
// 查找所有符合条件的图片
// 适配多种可能的图片结构
var $images = $('img').filter(function() {
var src = $(this).attr('src') || '';
var alt = $(this).attr('alt') || '';
// 匹配角色头像图片
return src.includes('Face_character') ||
src.includes('Character_') ||
alt.includes('character') ||
$(this).closest('.character-icon').length > 0;
});
console.log('找到', $images.length, '个角色图片');
if ($images.length === 0) {
// 如果没找到,尝试其他选择器
$images = $('.wikitable').nextAll('img, a img, div img').filter(function() {
return $(this).attr('src') && !$(this).closest('#avatar-pool').length;
});
console.log('备用查找到', $images.length, '个图片');
}
var processedCount = 0;
$images.each(function() {
var $img = $(this);
// 跳过已经在角色池中的
if ($img.closest('#avatar-pool').length > 0) {
return;
}
// 跳过已经在表格中的
if ($img.closest('.wikitable').length > 0) {
return;
}
var imgSrc = $img.attr('src');
var imgAlt = $img.attr('alt') || '';
var imgTitle = $img.attr('title') || '';
// 获取角色名称
var name = imgTitle || imgAlt || '';
// 尝试从父元素获取名称
if (!name) {
var $parent = $img.parent();
name = $parent.attr('title') || $parent.text().trim() || '';
}
// 如果还是没有名称,从图片路径提取
if (!name && imgSrc) {
var match = imgSrc.match(/Face_character_(.+?)\.png/);
if (match) {
name = match[1];
}
}
console.log('处理角色:', name, '图片:', imgSrc);
// 创建头像框架
var $frame = $('<div>')
.addClass('avatar-frame')
.append($img.clone().css({
'width': '64px',
'height': '64px'
}))
.append($('<div>').addClass('avatar-name').text(name));
// 添加唯一标识
var uniqueId = 'avatar_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
$frame.attr('data-tier-id', uniqueId);
$frame.attr('data-avatar-src', imgSrc);
$frame.attr('data-avatar-name', name);
// 添加到头像池
$('#avatar-pool').append($frame);
processedCount++;
});
console.log('成功处理', processedCount, '个角色');
if (processedCount === 0) {
showNotification('⚠️ 未找到角色图片,请确认页面已完全加载', 'error');
} else {
showNotification('✅ 已加载 ' + processedCount + ' 个角色', 'success');
}
}
function setupDragAndDrop() {
console.log('设置拖拽功能...');
var containers = [];
// 添加头像池
containers.push(document.getElementById('avatar-pool'));
// 添加所有tier单元格
$('.wikitable td:nth-child(2)').each(function() {
containers.push(this);
});
console.log('容器数量:', containers.length);
var drake = dragula(containers, {
moves: function(el, source, handle, sibling) {
return $(el).hasClass('avatar-frame');
},
accepts: function(el, target, source, sibling) {
return true;
},
invalid: function(el, handle) {
return false;
},
direction: 'horizontal',
copy: false,
copySortSource: false,
revertOnSpill: true,
removeOnSpill: false,
mirrorContainer: document.body
});
drake.on('drop', function(el, target, source, sibling) {
console.log('拖拽完成:', el, '从', source, '到', target);
var $el = $(el);
var $target = $(target);
// 如果拖到tier单元格中,添加标记
if ($target.is('td')) {
$el.addClass('in-tier');
} else if ($target.is('#avatar-pool')) {
$el.removeClass('in-tier');
}
showNotification('已移动角色', 'info');
});
drake.on('over', function(el, container, source) {
$(container).addClass('gu-over');
});
drake.on('out', function(el, container, source) {
$(container).removeClass('gu-over');
});
console.log('拖拽功能设置完成');
}
function addExportButton() {
var $button = $('<button>')
.attr('id', 'export-tierlist-btn')
.html('📸 导出为图片')
.click(function() {
loadHtml2Canvas(function() {
captureTierList();
});
});
$('#avatar-pool').after($button);
}
function addSaveLoadButtons() {
var $saveBtn = $('<button>')
.attr('id', 'save-tierlist-btn')
.html('💾 保存榜单')
.click(function() {
saveTierListData();
});
var $loadBtn = $('<button>')
.attr('id', 'load-tierlist-btn')
.html('📂 加载榜单')
.click(function() {
showLoadDialog();
});
var $shareBtn = $('<button>')
.attr('id', 'share-tierlist-btn')
.html('🔗 分享榜单')
.click(function() {
showShareDialog();
});
$('#export-tierlist-btn').after($saveBtn).after($loadBtn).after($shareBtn);
}
function saveTierListData() {
console.log('开始保存榜单...');
var tierData = collectTierData();
console.log('收集到的数据:', tierData);
console.log('层级数:', tierData.tiers.length);
console.log('池中角色数:', tierData.pool.length);
var totalAvatars = tierData.pool.length;
tierData.tiers.forEach(function(tier) {
totalAvatars += tier.avatars.length;
});
console.log('总角色数:', totalAvatars);
if (totalAvatars === 0) {
alert('没有检测到任何角色数据!');
return;
}
if (tierData.tiers.length === 0 || tierData.tiers.every(t => t.avatars.length === 0)) {
var confirm = window.confirm('您还没有将任何角色放入层级中,确定要保存空榜单吗?');
if (!confirm) {
return;
}
}
var listId = generateUniqueId();
var timestamp = new Date().toISOString();
var saveData = {
id: listId,
timestamp: timestamp,
data: tierData
};
try {
localStorage.setItem('tierlist_' + listId, JSON.stringify(saveData));
console.log('保存成功,ID:', listId);
showSaveSuccessDialog(listId);
} catch (e) {
console.error('保存失败:', e);
alert('保存失败:' + e.message);
}
}
function collectTierData() {
var data = {
tiers: [],
pool: []
};
// 收集各个tier中的数据
$('.wikitable tr').each(function() {
var $row = $(this);
var $cells = $row.find('td, th');
if ($cells.length >= 2) {
// 第一个单元格是层级名称
var $tierNameCell = $cells.eq(0);
var tierName = $tierNameCell.text().trim();
// 第二个单元格包含角色
var $tierCell = $cells.eq(1);
var $avatarsInTier = $tierCell.find('.avatar-frame');
console.log('检查层级:', tierName, '包含', $avatarsInTier.length, '个角色');
if ($avatarsInTier.length > 0) {
var avatars = [];
$avatarsInTier.each(function() {
var avatarData = getAvatarData($(this));
if (avatarData) {
avatars.push(avatarData);
console.log('收集角色:', avatarData.name);
}
});
if (avatars.length > 0) {
data.tiers.push({
name: tierName,
avatars: avatars
});
console.log('保存层级:', tierName, '共', avatars.length, '个角色');
}
}
}
});
// 收集头像池中的数据
$('#avatar-pool .avatar-frame').each(function() {
var avatarData = getAvatarData($(this));
if (avatarData) {
data.pool.push(avatarData);
}
});
console.log('最终数据:', data);
return data;
}
function getAvatarData($avatar) {
return {
tierId: $avatar.attr('data-tier-id'),
src: $avatar.attr('data-avatar-src') || $avatar.find('img').attr('src'),
name: $avatar.attr('data-avatar-name') || $avatar.find('.avatar-name').text().trim(),
html: $avatar.prop('outerHTML')
};
}
function showSaveSuccessDialog(listId) {
var pageUrl = window.location.origin + window.location.pathname;
var fullUrl = pageUrl + '?tierlist=' + listId;
var $overlay = $('<div>')
.addClass('tier-dialog-overlay')
.click(function(e) {
if (e.target === this) {
$(this).remove();
}
});
var $dialog = $('<div>').addClass('tier-dialog');
$dialog.html(`
<h3>✅ 榜单保存成功!</h3>
<div class="tier-info-box">
<p><strong>榜单ID:</strong> ${listId}</p>
<p><strong>分享链接:</strong></p>
<input type="text" value="${fullUrl}" readonly style="margin-bottom: 10px;">
</div>
<p style="color: #666; font-size: 14px;">您可以通过以下方式访问这个榜单:</p>
<ul style="color: #666; font-size: 14px; margin: 10px 0;">
<li>点击"加载榜单"按钮,输入ID:<code style="background: #f0f0f0; padding: 2px 6px; border-radius: 3px;">${listId}</code></li>
<li>复制分享链接发送给其他人</li>
</ul>
<div class="tier-dialog-buttons">
<button class="tier-dialog-btn tier-dialog-btn-secondary" onclick="this.closest('.tier-dialog-overlay').remove()">关闭</button>
<button class="tier-dialog-btn tier-dialog-btn-primary" id="copy-url-btn">复制链接</button>
</div>
`);
$overlay.append($dialog);
$('body').append($overlay);
$('#copy-url-btn').click(function() {
var $input = $dialog.find('input');
$input.select();
document.execCommand('copy');
showNotification('链接已复制到剪贴板!', 'success');
});
setTimeout(function() {
$dialog.find('input').select();
}, 100);
}
function showLoadDialog() {
var $overlay = $('<div>')
.addClass('tier-dialog-overlay')
.click(function(e) {
if (e.target === this) {
$(this).remove();
}
});
var $dialog = $('<div>').addClass('tier-dialog');
// 获取所有保存的榜单
var savedLists = [];
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
if (key.startsWith('tierlist_')) {
try {
var data = JSON.parse(localStorage.getItem(key));
savedLists.push(data);
} catch (e) {
console.error('解析榜单失败:', key, e);
}
}
}
// 按时间排序
savedLists.sort(function(a, b) {
return new Date(b.timestamp) - new Date(a.timestamp);
});
var listHtml = '';
if (savedLists.length > 0) {
listHtml = '<div style="max-height: 300px; overflow-y: auto; margin: 15px 0;">';
savedLists.forEach(function(list) {
var date = new Date(list.timestamp).toLocaleString('zh-CN');
var tierCount = list.data.tiers.length;
var avatarCount = list.data.pool.length;
list.data.tiers.forEach(function(tier) {
avatarCount += tier.avatars.length;
});
listHtml += `
<div style="border: 1px solid #ddd; border-radius: 6px; padding: 10px; margin-bottom: 10px; cursor: pointer; transition: all 0.2s;"
class="saved-list-item"
data-list-id="${list.id}"
onmouseover="this.style.background='#f0f8ff'; this.style.borderColor='#4a9eff';"
onmouseout="this.style.background='white'; this.style.borderColor='#ddd';">
<div style="font-weight: bold; margin-bottom: 5px;">ID: ${list.id}</div>
<div style="font-size: 12px; color: #666;">保存时间: ${date}</div>
<div style="font-size: 12px; color: #666;">包含 ${tierCount} 个层级,${avatarCount} 个角色</div>
</div>
`;
});
listHtml += '</div>';
}
$dialog.html(`
<h3>📂 加载榜单</h3>
<p style="color: #666; margin-bottom: 15px;">输入榜单ID或从下方选择:</p>
<input type="text" id="tierlist-id-input" placeholder="输入榜单ID" style="margin-bottom: 15px;">
${listHtml || '<p style="color: #999; text-align: center; padding: 20px;">暂无保存的榜单</p>'}
<div class="tier-dialog-buttons">
<button class="tier-dialog-btn tier-dialog-btn-secondary" onclick="this.closest('.tier-dialog-overlay').remove()">取消</button>
<button class="tier-dialog-btn tier-dialog-btn-primary" id="load-btn">加载</button>
</div>
`);
$overlay.append($dialog);
$('body').append($overlay);
// 点击列表项选择
$('.saved-list-item').click(function() {
$('.saved-list-item').css('background', 'white').css('border-color', '#ddd');
$(this).css('background', '#e8f4f8').css('border-color', '#4a9eff');
$('#tierlist-id-input').val($(this).data('list-id'));
});
// 加载按钮
$('#load-btn').click(function() {
var listId = $('#tierlist-id-input').val().trim();
if (!listId) {
alert('请输入或选择榜单ID');
return;
}
if (loadTierListData(listId)) {
$overlay.remove();
} else {
alert('加载失败:未找到该榜单');
}
});
// 回车加载
$('#tierlist-id-input').keypress(function(e) {
if (e.which === 13) {
$('#load-btn').click();
}
});
}
function loadTierListData(listId) {
var savedData = localStorage.getItem('tierlist_' + listId);
console.log('尝试加载榜单 ID:', listId);
if (!savedData) {
console.error('未找到榜单数据');
return false;
}
try {
var saveData = JSON.parse(savedData);
console.log('解析后的数据:', saveData);
applyTierData(saveData.data);
showNotification('榜单加载成功!', 'success');
return true;
} catch (e) {
console.error('加载榜单失败:', e);
return false;
}
}
function applyTierData(tierData) {
console.log('应用榜单数据:', tierData);
// 首先将所有角色移回池中
$('.wikitable td .avatar-frame').each(function() {
$(this).removeClass('in-tier');
$('#avatar-pool').append($(this));
});
// 应用tier数据
tierData.tiers.forEach(function(tier, index) {
console.log('处理层级', index, ':', tier.name, '包含', tier.avatars.length, '个角色');
// 找到对应的tier单元格
var $tierRow = $('.wikitable tr').eq(index);
var $tierCell = $tierRow.find('td:nth-child(2)');
if ($tierCell.length === 0) {
console.warn('未找到层级单元格,跳过');
return;
}
// 清空该单元格
$tierCell.empty();
// 将角色移动到该层级
tier.avatars.forEach(function(avatarData) {
var $avatar = findAvatarByIdentifier(avatarData);
if ($avatar && $avatar.length > 0) {
console.log('找到角色:', avatarData.name, '移动到', tier.name);
$avatar.addClass('in-tier');
$tierCell.append($avatar);
} else {
console.warn('未找到角色:', avatarData.name);
// 如果找不到,尝试从保存的HTML重建
if (avatarData.html) {
try {
var $newAvatar = $(avatarData.html);
$newAvatar.addClass('in-tier');
$tierCell.append($newAvatar);
console.log('从HTML重建角色:', avatarData.name);
} catch (e) {
console.error('重建角色失败:', e);
}
}
}
});
});
// 处理池中的角色
if (tierData.pool && tierData.pool.length > 0) {
console.log('处理角色池,包含', tierData.pool.length, '个角色');
tierData.pool.forEach(function(avatarData) {
var $avatar = findAvatarByIdentifier(avatarData);
if ($avatar && $avatar.length > 0) {
$avatar.removeClass('in-tier');
if ($avatar.closest('#avatar-pool').length === 0) {
$('#avatar-pool').append($avatar);
}
}
});
}
console.log('榜单数据应用完成');
}
function findAvatarByIdentifier(identifier) {
console.log('查找角色:', identifier);
if (!identifier) {
return null;
}
try {
var $found = null;
// 优先通过tierId查找
if (identifier.tierId) {
$found = $('[data-tier-id="' + identifier.tierId + '"]');
if ($found.length > 0) {
console.log('通过tierId找到角色');
return $found;
}
}
// 通过图片src和名称查找
$('.avatar-frame').each(function() {
if ($found) return false;
var $avatar = $(this);
var src = $avatar.attr('data-avatar-src') || $avatar.find('img').attr('src');
var name = $avatar.attr('data-avatar-name') || $avatar.find('.avatar-name').text().trim();
if (identifier.src && src === identifier.src) {
if (!identifier.name || name === identifier.name) {
$found = $avatar;
console.log('通过src找到角色:', name);
return false;
}
}
if (identifier.name && name === identifier.name) {
if (!identifier.src || src === identifier.src) {
$found = $avatar;
console.log('通过name找到角色:', name);
return false;
}
}
});
return $found;
} catch (e) {
console.error('查找角色失败:', e);
return null;
}
}
function showShareDialog() {
var tierData = collectTierData();
var listId = generateUniqueId();
var timestamp = new Date().toISOString();
var saveData = {
id: listId,
timestamp: timestamp,
data: tierData
};
localStorage.setItem('tierlist_' + listId, JSON.stringify(saveData));
var pageUrl = window.location.origin + window.location.pathname;
var fullUrl = pageUrl + '?tierlist=' + listId;
var $overlay = $('<div>')
.addClass('tier-dialog-overlay')
.click(function(e) {
if (e.target === this) {
$(this).remove();
}
});
var $dialog = $('<div>').addClass('tier-dialog');
$dialog.html(`
<h3>🔗 分享榜单</h3>
<div class="tier-info-box">
<p><strong>分享链接:</strong></p>
<input type="text" value="${fullUrl}" readonly id="share-url-input">
<p style="margin-top: 10px; font-size: 14px; color: #666;">
将此链接发送给好友,他们打开后可以看到您的榜单排序。
</p>
</div>
<div class="tier-dialog-buttons">
<button class="tier-dialog-btn tier-dialog-btn-secondary" onclick="this.closest('.tier-dialog-overlay').remove()">关闭</button>
<button class="tier-dialog-btn tier-dialog-btn-primary" id="share-copy-btn">复制链接</button>
</div>
`);
$overlay.append($dialog);
$('body').append($overlay);
$('#share-copy-btn').click(function() {
var $input = $('#share-url-input');
$input.select();
document.execCommand('copy');
showNotification('分享链接已复制!', 'success');
});
setTimeout(function() {
$('#share-url-input').select();
}, 100);
}
function checkUrlForTierList() {
var urlParams = new URLSearchParams(window.location.search);
var tierlistId = urlParams.get('tierlist');
if (tierlistId) {
console.log('检测到URL中的榜单ID:', tierlistId);
setTimeout(function() {
if (loadTierListData(tierlistId)) {
showNotification('✅ 已自动加载分享的榜单', 'success');
} else {
showNotification('❌ 无法加载分享的榜单', 'error');
}
}, 1500);
}
}
function generateUniqueId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2, 9);
}
function showNotification(message, type) {
var $notification = $('<div>')
.addClass('tier-notification')
.addClass(type || 'info')
.text(message);
$('body').append($notification);
setTimeout(function() {
$notification.fadeOut(300, function() {
$(this).remove();
});
}, 3000);
}
function loadHtml2Canvas(callback) {
if (typeof html2canvas === 'undefined') {
$.getScript('https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js')
.done(function() {
callback();
})
.fail(function() {
alert('加载html2canvas失败,请检查网络连接');
});
} else {
callback();
}
}
function captureTierList() {
var $table = $('.wikitable').first().clone();
// 确保表格中的图片样式正确
$table.find('.avatar-frame img').css({
'width': '64px',
'height': '64px',
'display': 'block'
});
// 移除空的tier单元格中的占位内容
$table.find('td:nth-child(2)').each(function() {
if ($(this).find('.avatar-frame').length === 0) {
$(this).empty().css({
'min-height': '80px',
'background': '#fafafa'
});
}
});
// 优化表格样式
$table.css({
'border-collapse': 'collapse',
'width': '100%'
});
$table.find('th, td').css({
'border': '2px solid #333',
'padding': '10px'
});
// 创建临时容器
var $container = $('<div>')
.css({
position: 'fixed',
left: '-9999px',
top: '0',
background: 'white',
padding: '30px',
minWidth: '900px',
fontFamily: 'Arial, sans-serif'
})
.append($table);
$('body').append($container);
// 添加标题
var $title = $('<h2>')
.text('我的角色Tier榜单')
.css({
textAlign: 'center',
marginBottom: '20px',
color: '#333',
fontSize: '28px',
fontWeight: 'bold'
});
// 添加时间戳
var $timestamp = $('<div>')
.text('生成时间: ' + new Date().toLocaleString('zh-CN'))
.css({
textAlign: 'center',
marginBottom: '15px',
color: '#666',
fontSize: '14px'
});
$container.prepend($timestamp).prepend($title);
html2canvas($container[0], {
backgroundColor: '#ffffff',
scale: 2,
logging: false,
useCORS: true,
allowTaint: true,
imageTimeout: 0
}).then(function(canvas) {
$container.remove();
canvas.toBlob(function(blob) {
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = 'tierlist_' + Date.now() + '.png';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
showNotification('📸 榜单图片已导出!', 'success');
});
}).catch(function(error) {
$container.remove();
console.error('导出失败:', error);
alert('导出图片失败:' + error.message);
});
}
})();