// 全局变量
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.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);
}