408 lines
14 KiB
JavaScript
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);
|
|
} |