import React, { useState, useEffect } from 'react';
import Head from 'next/head';
import { useRouter } from 'next/router';
import MagicalGirlCardACG from '../components/MagicalGirlCardACG';
import { useCooldown } from '../lib/cooldown';
import { quickCheck } from '@/lib/sensitive-word-filter';
interface Questionnaire {
questions: string[];
}
interface MagicalGirlACG {
codename: string;
appearance: {
outfit: string;
accessories: string;
colorScheme: string;
overallLook: string;
};
magicWeapon: {
name: string;
form: string;
basicAbilities: string[];
description: string;
};
specialMove: {
name: string;
chant: string;
description: string;
};
awakening: {
name: string;
evolvedAbilities: string[];
evolvedForm: string;
evolvedOutfit: string;
};
analysis: {
personalityAnalysis: string;
abilityReasoning: string;
coreTraits: string[];
predictionBasis: string;
};
}
const SaveJsonButton: React.FC<{ magicalGirlDetails: MagicalGirlACG; answers: string[] }> = ({ magicalGirlDetails, answers }) => {
const [isMobile, setIsMobile] = useState(false);
const [showJsonText, setShowJsonText] = useState(false);
useEffect(() => {
const userAgent = navigator.userAgent.toLowerCase();
const isMobileDevice = /mobile|android|iphone|ipad|ipod|blackberry|iemobile|opera mini/.test(userAgent);
setIsMobile(isMobileDevice);
}, []);
const downloadJson = () => {
const dataToSave = {
...magicalGirlDetails,
userAnswers: answers
};
const jsonData = JSON.stringify(dataToSave, null, 2);
const blob = new Blob([jsonData], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = `魔法少女_${magicalGirlDetails.codename || 'data'}.json`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
};
const handleSave = () => {
if (isMobile) {
setShowJsonText(true);
} else {
downloadJson();
}
};
if (showJsonText) {
return (
请复制以下数据并保存
);
}
return (
);
};
const ACGPage: React.FC = () => {
const router = useRouter();
const [questions, setQuestions] = useState([]);
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
const [answers, setAnswers] = useState([]);
const [currentAnswer, setCurrentAnswer] = useState('');
const [loading, setLoading] = useState(true);
const [submitting, setSubmitting] = useState(false);
const [isTransitioning, setIsTransitioning] = useState(false);
const [magicalGirlDetails, setMagicalGirlDetails] = useState(null);
const [showImageModal, setShowImageModal] = useState(false);
const [savedImageUrl, setSavedImageUrl] = useState(null);
const [showIntroduction, setShowIntroduction] = useState(true);
const [error, setError] = useState(null);
const [showDetails, setShowDetails] = useState(false);
const { isCooldown, startCooldown, remainingTime } = useCooldown('generateDetailsCooldown', 60000);
useEffect(() => {
fetch('/acg_questionnaire.json')
.then(response => {
if (!response.ok) {
throw new Error('加载问卷文件失败');
}
return response.json();
})
.then((data: Questionnaire) => {
setQuestions(data.questions);
setAnswers(new Array(data.questions.length).fill(''));
setLoading(false);
})
.catch(error => {
console.error('加载问卷失败:', error);
setError('📋 加载问卷失败,请刷新页面重试');
setLoading(false);
});
}, []);
const handleNext = () => {
if (currentAnswer.trim().length === 0) {
setError('⚠️ 请输入答案后再继续');
return;
}
if (currentAnswer.length > 30) {
setError('⚠️ 答案不能超过30字');
return;
}
setError(null);
proceedToNextQuestion(currentAnswer.trim());
};
const handleQuickOption = (option: string) => {
proceedToNextQuestion(option);
};
const proceedToNextQuestion = (answer: string) => {
const newAnswers = [...answers];
newAnswers[currentQuestionIndex] = answer;
setAnswers(newAnswers);
if (currentQuestionIndex < questions.length - 1) {
setIsTransitioning(true);
setTimeout(() => {
setCurrentQuestionIndex(currentQuestionIndex + 1);
setCurrentAnswer(newAnswers[currentQuestionIndex + 1] || '');
setTimeout(() => {
setIsTransitioning(false);
}, 50);
}, 250);
} else {
handleSubmit(newAnswers);
}
};
const handleSubmit = async (finalAnswers: string[]) => {
if (isCooldown) {
setError(`请等待 ${remainingTime} 秒后再生成`);
return;
}
setSubmitting(true);
setError(null);
const result = await quickCheck(finalAnswers.join(''));
if (result.hasSensitiveWords) {
router.push('/arrested');
return;
}
try {
const response = await fetch('/api/generate-magical-girl-acg', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ answers: finalAnswers })
});
if (!response.ok) {
const errorData = await response.json();
if (response.status === 429) {
const retryAfter = errorData.retryAfter || 60;
throw new Error(`请求过于频繁!请等待 ${retryAfter} 秒后再试。`);
} else if (response.status >= 500) {
throw new Error('服务器内部错误,请稍后重试');
} else {
throw new Error(errorData.message || errorData.error || '生成失败');
}
}
const result: MagicalGirlACG = await response.json();
setMagicalGirlDetails(result);
setError(null);
} catch (error) {
if (error instanceof Error) {
const errorMessage = error.message;
if (errorMessage.includes('请求过于频繁')) {
setError('🚫 请求太频繁了!每2分钟只能生成一次哦~请稍后再试吧!');
} else if (errorMessage.includes('网络') || error instanceof TypeError) {
setError('🌐 网络连接有问题!请检查网络后重试~');
} else {
setError(`✨ 魔法失效了!${errorMessage}`);
}
} else {
setError('✨ 魔法失效了!生成详情时发生未知错误,请重试');
}
} finally {
setSubmitting(false);
startCooldown();
}
};
const handleSaveImage = (imageUrl: string) => {
setSavedImageUrl(imageUrl);
setShowImageModal(true);
};
const handleStartQuestionnaire = () => {
setShowIntroduction(false);
};
if (loading) {
return (
);
}
if (questions.length === 0) {
return (
);
}
const isLastQuestion = currentQuestionIndex === questions.length - 1;
return (
<>
魔法少女调查问卷 ~ 二次元篇
{showIntroduction ? (
回答这些问题,唤醒你心中沉睡的魔法少女之魂!
本测试将为你量身打造专属的二次元魔法少女设定
) : (
<>
问题 {currentQuestionIndex + 1} / {questions.length}
{Math.round(((currentQuestionIndex + 1) / questions.length) * 100)}%
0 ? 'slideInFromRight 0.3s ease-out' : 'none'
}}
>
{questions[currentQuestionIndex]}
{error && (
{error}
)}
>
)}
{magicalGirlDetails && (
<>
{showDetails && (
1. 魔法武器
每个魔法少女都拥有独特的魔法武器,这是她们力量的源泉和象征。武器的形态和能力多种多样,完全反映了持有者的内心和特质。
2. 必杀技
必杀技是魔法少女最强大的招式,通常需要咏唱咒语并伴随着华丽的动画演出。这是她们在关键时刻扭转战局、守护重要之物的最终王牌。
3. 觉醒/超进化
当魔法少女的意志和情感达到顶峰时,她们可能会迎来力量的觉醒或超进化。这不仅会带来更华丽的服装和更强大的武器,更象征着角色的成长和蜕变。
)}
>
)}
{showImageModal && savedImageUrl && (
💫 长按图片保存到相册
)}
>
);
};
export default ACGPage;