// 全局变量 let customCards = []; let currentSortType = 'newest'; let currentFilterType = 'all'; let currentUserId = null; let currentCardId = null; let userVotes = {}; // DOM元素 const cardsContainer = document.getElementById('cards-container'); const sortBySelect = document.getElementById('sort-by'); const filterBySelect = document.getElementById('filter-by'); const cardModal = document.getElementById('card-modal'); const closeModal = document.querySelector('.close-modal'); const upvoteBtn = document.getElementById('upvote-btn'); const downvoteBtn = document.getElementById('downvote-btn'); // 页面加载完成后初始化 document.addEventListener('DOMContentLoaded', () => { // 获取当前用户ID getCurrentUser() .then(userId => { currentUserId = userId; // 获取用户投票历史 return getUserVotes(userId); }) .then(votes => { userVotes = votes; // 加载自定义卡牌 loadCustomCards(); }) .catch(error => { console.error('初始化失败:', error); showErrorMessage('加载数据失败,请刷新页面重试'); }); // 添加事件监听器 sortBySelect.addEventListener('change', () => { currentSortType = sortBySelect.value; renderCards(); }); filterBySelect.addEventListener('change', () => { currentFilterType = filterBySelect.value; renderCards(); }); // 关闭模态框 closeModal.addEventListener('click', () => { cardModal.style.display = 'none'; }); // 点击模态框外部关闭 window.addEventListener('click', (event) => { if (event.target === cardModal) { cardModal.style.display = 'none'; } }); // 投票按钮点击事件 upvoteBtn.addEventListener('click', () => { if (currentCardId) { voteCard(currentCardId, 'upvote'); } }); downvoteBtn.addEventListener('click', () => { if (currentCardId) { voteCard(currentCardId, 'downvote'); } }); }); // 获取当前用户ID async function getCurrentUser() { try { const response = await fetch('/api/current_user'); if (!response.ok) { throw new Error('获取用户信息失败'); } const data = await response.json(); return data.user_id; } catch (error) { console.error('获取用户ID失败:', error); return null; } } // 获取用户投票历史 async function getUserVotes(userId) { if (!userId) return {}; try { const response = await fetch(`/api/user_votes`); if (!response.ok) { throw new Error('获取投票历史失败'); } const data = await response.json(); return data.votes || {}; } catch (error) { console.error('获取投票历史失败:', error); return {}; } } // 加载自定义卡牌 async function loadCustomCards() { cardsContainer.innerHTML = '
加载中...
'; try { const response = await fetch('/api/custom_cards'); if (!response.ok) { throw new Error('加载卡牌失败'); } const data = await response.json(); customCards = data.cards || []; // 渲染卡牌 renderCards(); } catch (error) { console.error('加载卡牌失败:', error); cardsContainer.innerHTML = `
加载卡牌失败: ${error.message}
`; } } // 渲染卡牌列表 function renderCards() { if (!customCards || customCards.length === 0) { cardsContainer.innerHTML = `

暂无卡牌

成为第一个创建自制卡牌的人吧!

创建卡牌
`; return; } // 过滤卡牌 let filteredCards = [...customCards]; if (currentFilterType === 'my' && currentUserId) { filteredCards = filteredCards.filter(card => card.creator_id === currentUserId); // 如果过滤后没有卡牌 if (filteredCards.length === 0) { cardsContainer.innerHTML = `

您还没有创建卡牌

点击下方按钮开始创建您的第一张自制卡牌!

创建卡牌
`; return; } } // 排序卡牌 sortCards(filteredCards); // 渲染卡牌 cardsContainer.innerHTML = filteredCards.map(card => { // 计算净投票数 const voteScore = (card.upvotes || 0) - (card.downvotes || 0); const voteClass = voteScore > 0 ? 'vote-positive' : (voteScore < 0 ? 'vote-negative' : 'vote-neutral'); // 格式化创建时间 const createdDate = new Date(card.created_at); const formattedDate = `${createdDate.getFullYear()}-${(createdDate.getMonth() + 1).toString().padStart(2, '0')}-${createdDate.getDate().toString().padStart(2, '0')}`; return `
${card.character.avatar || '👤'}

${card.character.name}

${card.character.title}

${card.title}

${card.description}

`; }).join(''); // 添加卡牌点击事件 document.querySelectorAll('.card-item').forEach(card => { card.addEventListener('click', () => { const cardId = card.getAttribute('data-id'); openCardDetails(cardId); }); }); } // 排序卡牌 function sortCards(cards) { switch (currentSortType) { case 'newest': // 按创建时间降序排序(最新的在前面) cards.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); break; case 'popular': // 按点赞数降序排序 cards.sort((a, b) => ((b.upvotes || 0) - (b.downvotes || 0)) - ((a.upvotes || 0) - (a.downvotes || 0))); break; case 'controversial': // 按总投票数排序 (争议性) cards.sort((a, b) => ((b.upvotes || 0) + (b.downvotes || 0)) - ((a.upvotes || 0) + (a.downvotes || 0))); break; default: // 默认按最新排序 cards.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); } } // 打开卡牌详情 function openCardDetails(cardId) { const card = customCards.find(c => c.id === cardId); if (!card) return; // 更新当前卡牌ID currentCardId = cardId; // 填充模态框内容 document.getElementById('modal-card-title').textContent = card.title; document.getElementById('modal-card-creator').textContent = card.creator_name; // 格式化创建时间 const createdDate = new Date(card.created_at); const formattedDate = `${createdDate.getFullYear()}-${(createdDate.getMonth() + 1).toString().padStart(2, '0')}-${createdDate.getDate().toString().padStart(2, '0')}`; document.getElementById('modal-card-date').textContent = formattedDate; document.getElementById('modal-card-description').textContent = card.description; document.getElementById('modal-option-a-text').textContent = card.option_a.text; document.getElementById('modal-option-b-text').textContent = card.option_b.text; // 生成效果标签 const optionAEffects = document.getElementById('modal-option-a-effects'); const optionBEffects = document.getElementById('modal-option-b-effects'); optionAEffects.innerHTML = generateEffectTags(card.option_a.effects); optionBEffects.innerHTML = generateEffectTags(card.option_b.effects); // 更新投票状态 const voteScore = (card.upvotes || 0) - (card.downvotes || 0); document.getElementById('modal-card-votes').textContent = voteScore; // 检查用户之前的投票 const userVote = userVotes[cardId]; upvoteBtn.classList.toggle('voted', userVote === 'upvote'); downvoteBtn.classList.toggle('voted', userVote === 'downvote'); // 显示模态框 cardModal.style.display = 'block'; } // 生成效果标签HTML function generateEffectTags(effects) { if (!effects) return ''; const tags = []; for (const [stat, value] of Object.entries(effects)) { if (value === 0) continue; let statName = ''; let statIcon = ''; switch (stat) { case 'loyalty': statName = '帝国忠诚度'; statIcon = '🦅'; break; case 'chaos': statName = '混沌侵染'; statIcon = '🌀'; break; case 'population': statName = '民众控制'; statIcon = '👥'; break; case 'military': statName = '军事力量'; statIcon = '🔫'; break; case 'resources': statName = '资源储备'; statIcon = '⚙️'; break; } const isPositive = value > 0; tags.push(`
${statIcon} ${statName} ${isPositive ? '+' : ''}${value}
`); } return tags.join(''); } // 投票 async function voteCard(cardId, voteType) { if (!currentUserId) { showMessage('请先登录后再投票'); return; } try { const response = await fetch(`/api/vote_card`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ card_id: cardId, vote_type: voteType }) }); if (!response.ok) { throw new Error('投票失败'); } const data = await response.json(); // 更新本地投票记录 userVotes[cardId] = data.newVote || null; // 更新卡牌数据 const cardIndex = customCards.findIndex(c => c.id === cardId); if (cardIndex !== -1) { customCards[cardIndex].upvotes = data.upvotes; customCards[cardIndex].downvotes = data.downvotes; // 更新UI const voteScore = data.upvotes - data.downvotes; document.getElementById('modal-card-votes').textContent = voteScore; // 更新投票按钮状态 upvoteBtn.classList.toggle('voted', data.newVote === 'upvote'); downvoteBtn.classList.toggle('voted', data.newVote === 'downvote'); // 渲染卡牌列表以更新投票数量 renderCards(); } } catch (error) { console.error('投票失败:', error); showMessage('投票失败,请稍后再试'); } } // 显示错误消息 function showErrorMessage(message) { cardsContainer.innerHTML = `
${message}
`; } // 显示消息(临时弹出提示) function showMessage(message) { const messageElement = document.createElement('div'); messageElement.className = 'message-popup'; messageElement.textContent = message; document.body.appendChild(messageElement); // 消息显示动画 setTimeout(() => { messageElement.classList.add('show'); }, 10); // 3秒后移除消息 setTimeout(() => { messageElement.classList.remove('show'); setTimeout(() => { messageElement.remove(); }, 300); }, 3000); }