Warhummer/static/js/create_card.js
2025-06-25 09:35:26 +08:00

408 lines
14 KiB
JavaScript

// DOM元素
const cardTitleInput = document.getElementById('card-title');
const characterNameInput = document.getElementById('character-name');
const characterTitleInput = document.getElementById('character-title');
const characterAvatarInput = document.getElementById('character-avatar');
const cardDescriptionInput = document.getElementById('card-description');
const optionATextInput = document.getElementById('option-a-text');
const optionBTextInput = document.getElementById('option-b-text');
// 选项A的效果输入
const optionALoyalty = document.getElementById('option-a-loyalty');
const optionAChaos = document.getElementById('option-a-chaos');
const optionAPopulation = document.getElementById('option-a-population');
const optionAMilitary = document.getElementById('option-a-military');
const optionAResources = document.getElementById('option-a-resources');
// 选项B的效果输入
const optionBLoyalty = document.getElementById('option-b-loyalty');
const optionBChaos = document.getElementById('option-b-chaos');
const optionBPopulation = document.getElementById('option-b-population');
const optionBMilitary = document.getElementById('option-b-military');
const optionBResources = document.getElementById('option-b-resources');
// 表单和按钮
const createCardForm = document.getElementById('create-card-form');
const previewButton = document.getElementById('preview-button');
// 计数器元素
const titleCount = document.getElementById('title-count');
const nameCount = document.getElementById('name-count');
const titleCount2 = document.getElementById('title-count-2');
const descCount = document.getElementById('desc-count');
const optionACount = document.getElementById('option-a-count');
const optionBCount = document.getElementById('option-b-count');
// 效果总计
const optionATotal = document.getElementById('option-a-total');
const optionBTotal = document.getElementById('option-b-total');
const optionAWarning = document.getElementById('option-a-warning');
const optionBWarning = document.getElementById('option-b-warning');
// 预览模态框元素
const previewModal = document.getElementById('preview-modal');
const closePreview = document.getElementById('close-preview');
const previewCardTitle = document.getElementById('preview-card-title');
const previewCharacterName = document.getElementById('preview-character-name');
const previewCharacterTitle = document.getElementById('preview-character-title');
const previewCharacterAvatar = document.getElementById('preview-character-avatar');
const previewCardDescription = document.getElementById('preview-card-description');
const previewOptionAText = document.getElementById('preview-option-a-text');
const previewOptionBText = document.getElementById('preview-option-b-text');
const previewOptionAEffects = document.getElementById('preview-option-a-effects');
const previewOptionBEffects = document.getElementById('preview-option-b-effects');
// 表情符号选择器
const emojiItems = document.querySelectorAll('.emoji-item');
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {
// 添加字符计数事件监听器
setupCharacterCounter(cardTitleInput, titleCount, 50);
setupCharacterCounter(characterNameInput, nameCount, 30);
setupCharacterCounter(characterTitleInput, titleCount2, 30);
setupCharacterCounter(cardDescriptionInput, descCount, 200);
setupCharacterCounter(optionATextInput, optionACount, 50);
setupCharacterCounter(optionBTextInput, optionBCount, 50);
// 添加效果值变化监听器
setupEffectListeners('option-a');
setupEffectListeners('option-b');
// 预览按钮点击事件
previewButton.addEventListener('click', showPreview);
// 关闭预览模态框
closePreview.addEventListener('click', () => {
previewModal.style.display = 'none';
});
// 点击模态框外部关闭
window.addEventListener('click', (event) => {
if (event.target === previewModal) {
previewModal.style.display = 'none';
}
});
// 表单提交事件
createCardForm.addEventListener('submit', submitCard);
// 表情符号选择器
emojiItems.forEach(item => {
item.addEventListener('click', () => {
const emoji = item.getAttribute('data-emoji');
characterAvatarInput.value = emoji;
});
});
});
// 设置字符计数器
function setupCharacterCounter(input, counter, maxLength) {
// 初始更新
updateCharacterCount(input, counter);
// 添加输入事件监听器
input.addEventListener('input', () => {
updateCharacterCount(input, counter);
});
}
// 更新字符计数
function updateCharacterCount(input, counter) {
const length = input.value.length;
counter.textContent = length;
// 如果超过最大长度,添加警告样式
if (length >= parseInt(input.getAttribute('maxlength'))) {
counter.parentElement.classList.add('warning');
} else {
counter.parentElement.classList.remove('warning');
}
}
// 设置效果值监听器
function setupEffectListeners(prefix) {
const effects = [
document.getElementById(`${prefix}-loyalty`),
document.getElementById(`${prefix}-chaos`),
document.getElementById(`${prefix}-population`),
document.getElementById(`${prefix}-military`),
document.getElementById(`${prefix}-resources`)
];
// 为每个效果输入添加监听器
effects.forEach(effect => {
effect.addEventListener('input', () => {
updateEffectsTotal(prefix);
});
});
// 初始计算总和
updateEffectsTotal(prefix);
}
// 更新效果总和
function updateEffectsTotal(prefix) {
const effects = [
parseInt(document.getElementById(`${prefix}-loyalty`).value) || 0,
parseInt(document.getElementById(`${prefix}-chaos`).value) || 0,
parseInt(document.getElementById(`${prefix}-population`).value) || 0,
parseInt(document.getElementById(`${prefix}-military`).value) || 0,
parseInt(document.getElementById(`${prefix}-resources`).value) || 0
];
// 计算绝对值总和
const total = effects.reduce((sum, effect) => sum + Math.abs(effect), 0);
// 更新显示
const totalElement = document.getElementById(`${prefix}-total`);
const warningElement = document.getElementById(`${prefix}-warning`);
// 添加空检查
if (totalElement) {
totalElement.textContent = total;
} else {
console.error(`找不到元素: ${prefix}-total`);
}
// 添加空检查
if (warningElement) {
if (total > 80) {
warningElement.style.display = 'block';
if (totalElement) totalElement.classList.add('warning');
} else {
warningElement.style.display = 'none';
if (totalElement) totalElement.classList.remove('warning');
}
}
}
// 获取选项效果对象
function getOptionEffects(prefix) {
return {
loyalty: parseInt(document.getElementById(`${prefix}-loyalty`).value) || 0,
chaos: parseInt(document.getElementById(`${prefix}-chaos`).value) || 0,
population: parseInt(document.getElementById(`${prefix}-population`).value) || 0,
military: parseInt(document.getElementById(`${prefix}-military`).value) || 0,
resources: parseInt(document.getElementById(`${prefix}-resources`).value) || 0
};
}
// 生成效果标签HTML
function generateEffectTags(effects) {
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(`
<div class="effect-tag ${isPositive ? 'positive' : 'negative'}">
${statIcon} ${statName} ${isPositive ? '+' : ''}${value}
</div>
`);
}
return tags.join('');
}
// 验证表单
function validateForm() {
// 基本字段验证
if (!cardTitleInput.value.trim()) {
showMessage('请输入卡牌标题');
cardTitleInput.focus();
return false;
}
if (!characterNameInput.value.trim()) {
showMessage('请输入角色名称');
characterNameInput.focus();
return false;
}
if (!characterTitleInput.value.trim()) {
showMessage('请输入角色头衔');
characterTitleInput.focus();
return false;
}
if (!characterAvatarInput.value.trim()) {
showMessage('请选择角色图标');
characterAvatarInput.focus();
return false;
}
if (!cardDescriptionInput.value.trim()) {
showMessage('请输入卡牌描述');
cardDescriptionInput.focus();
return false;
}
if (!optionATextInput.value.trim()) {
showMessage('请输入选项A文本');
optionATextInput.focus();
return false;
}
if (!optionBTextInput.value.trim()) {
showMessage('请输入选项B文本');
optionBTextInput.focus();
return false;
}
// 效果值总和验证
const optionAEffectsTotal = Object.values(getOptionEffects('option-a')).reduce((sum, val) => sum + Math.abs(val), 0);
const optionBEffectsTotal = Object.values(getOptionEffects('option-b')).reduce((sum, val) => sum + Math.abs(val), 0);
if (optionAEffectsTotal > 80) {
showMessage('选项A的效果总和不能超过40');
return false;
}
if (optionBEffectsTotal > 80) {
showMessage('选项B的效果总和不能超过40');
return false;
}
return true;
}
// 显示预览
function showPreview() {
if (!validateForm()) return;
// 填充预览内容
previewCardTitle.textContent = cardTitleInput.value;
previewCharacterName.textContent = characterNameInput.value;
previewCharacterTitle.textContent = characterTitleInput.value;
previewCharacterAvatar.textContent = characterAvatarInput.value;
previewCardDescription.textContent = cardDescriptionInput.value;
previewOptionAText.textContent = optionATextInput.value;
previewOptionBText.textContent = optionBTextInput.value;
// 生成效果标签
const optionAEffects = getOptionEffects('option-a');
const optionBEffects = getOptionEffects('option-b');
previewOptionAEffects.innerHTML = generateEffectTags(optionAEffects);
previewOptionBEffects.innerHTML = generateEffectTags(optionBEffects);
// 显示预览模态框
previewModal.style.display = 'block';
}
async function submitCard(event) {
event.preventDefault();
console.log("表单提交触发"); // 添加调试日志
if (!validateForm()) return;
// 构造卡牌数据
const cardData = {
title: cardTitleInput.value.trim(),
character: {
name: characterNameInput.value.trim(),
title: characterTitleInput.value.trim(),
avatar: characterAvatarInput.value.trim()
},
description: cardDescriptionInput.value.trim(),
option_a: {
text: optionATextInput.value.trim(),
effects: getOptionEffects('option-a')
},
option_b: {
text: optionBTextInput.value.trim(),
effects: getOptionEffects('option-b')
}
};
console.log("准备发送的数据:", cardData); // 添加调试日志
try {
// 显示加载状态
const submitButton = createCardForm.querySelector('button[type="submit"]');
const originalText = submitButton.textContent;
submitButton.disabled = true;
submitButton.textContent = '提交中...';
// 发送请求
const response = await fetch('/api/create_custom_card', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(cardData)
});
console.log("服务器响应状态:", response.status); // 添加调试日志
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || '创建卡牌失败');
}
const result = await response.json();
console.log("创建成功, 结果:", result); // 添加调试日志
// 创建成功,跳转到卡牌列表页
window.location.href = '/custom_cards';
} catch (error) {
console.error('创建卡牌失败:', error);
showMessage(error.message || '创建卡牌失败,请稍后再试');
// 恢复按钮状态
const submitButton = createCardForm.querySelector('button[type="submit"]');
submitButton.disabled = false;
submitButton.textContent = '提交卡牌';
}
}
// 显示消息(临时弹出提示)
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);
}