0, 'msg' => '', 'data' => null]; $action = $_REQUEST['action'] ?? 'question'; $id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : null; switch($action){ case 'question': $result['data'] = getQuestion($id ?? getCurrentId()); break; case 'next': $result['data'] = getNextQuestionAuto(); break; case 'fetch': $result['data'] = fetchNewQuestion(); break; case 'answer': $result['data'] = checkAnswer($id, $_REQUEST['answer'] ?? ''); break; case 'hint': $result['data'] = getHint($id); break; case 'list': $result['data'] = getQuestionList(); break; case 'refresh': $result['data'] = refreshCache(); break; case 'stats': $result['data'] = getStats(); break; default: $result['code'] = 400; $result['msg'] = '未知操作'; } echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); function getStats(){ global $cacheData; $cache = loadCache(); return [ 'total_questions' => count($cache), 'cache_file_size' => file_exists(CACHE_FILE) ? round(filesize(CACHE_FILE) / 1024, 2) . ' KB' : 0, 'last_updated' => file_exists(CACHE_FILE) ? date('Y-m-d H:i:s', filemtime(CACHE_FILE)) : 'N/A', 'memory_usage' => round(memory_get_peak_usage(true) / 1024, 2) . ' KB' ]; } function getQuestion($id){ $cache = loadCache(); if(empty($cache)){ return ['error' => '没有题目数据']; } if($id < 0 || $id >= count($cache)){ return ['error' => '题目不存在', 'total' => count($cache)]; } $item = $cache[$id]; return [ 'id' => $id, 'total' => count($cache), 'question' => $item['question_content'], 'author' => $item['type']['person'] ?? '', 'type' => $item['type']['type'] ?? '', 'grade' => $item['type']['grade'] ?? '', 'dynasty' => $item['type']['dynasty'] ?? '', 'options' => formatOptions($item['option_answers'] ?? []) ]; } function getNextQuestionAuto(){ $cache = loadCache(); if(empty($cache)){ return ['error' => '没有题目数据']; } $total = count($cache); $currentId = getCurrentId(); $nextId = $currentId + 1; if($nextId >= $total){ $nextId = 0; } setCurrentId($nextId); $result = getQuestion($nextId); $result['prev_id'] = $currentId; return $result; } function getCurrentId(){ return isset($_SESSION['current_question_id']) ? intval($_SESSION['current_question_id']) : 0; } function setCurrentId($id){ $_SESSION['current_question_id'] = $id; } function fetchNewQuestion(){ $apiData = fetchFromBaiduApi(); if($apiData === null){ $cache = loadCache(); if(!empty($cache)){ $randomId = array_rand($cache); $result = formatQuestionItem($randomId, $cache[$randomId], count($cache)); $result['from_cache'] = true; $result['api_status'] = 'failed'; return $result; } return ['error' => 'API请求失败且无本地缓存']; } $cache = loadCache(); $newCount = mergeToCache($apiData, $cache); $randomItem = $apiData[array_rand($apiData)]; $result = formatQuestionItem(null, $randomItem, count($cache)); $result['from_cache'] = false; $result['new_questions'] = $newCount; $result['api_status'] = 'success'; return $result; } function formatQuestionItem($id, $item, $total, $fromCache = false, $newCount = 0){ return [ 'id' => $id, 'total' => $total, 'question' => $item['question_content'], 'author' => $item['type']['person'] ?? '', 'type' => $item['type']['type'] ?? '', 'grade' => $item['type']['grade'] ?? '', 'dynasty' => $item['type']['dynasty'] ?? '', 'options' => formatOptions($item['option_answers'] ?? []), 'from_cache' => $fromCache, 'new_questions' => $newCount ]; } function checkAnswer($id, $answer){ $cache = loadCache(); if(empty($cache)){ return ['error' => '没有题目数据']; } if($id < 0 || $id >= count($cache)){ return ['error' => '题目不存在']; } $item = $cache[$id]; $correctAnswer = findAnswer($item['option_answers'] ?? []); $isCorrect = ($answer === $correctAnswer); return [ 'id' => $id, 'correct' => $isCorrect, 'your_answer' => $answer, 'correct_answer' => $correctAnswer, 'next_id' => $id + 1, 'has_next' => $id + 1 < count($cache) ]; } function getHint($id){ $cache = loadCache(); if(empty($cache)){ return ['error' => '没有题目数据']; } if($id < 0 || $id >= count($cache)){ return ['error' => '题目不存在']; } $item = $cache[$id]; return [ 'id' => $id, 'hint' => '这是首描写' . ($item['type']['type'] ?? '') . '的诗,你在' . ($item['type']['grade'] ?? '') . '学过它。', 'author' => $item['type']['person'] ?? '', 'dynasty' => $item['type']['dynasty'] ?? '' ]; } function getQuestionList(){ $cache = loadCache(); if(empty($cache)){ return ['total' => 0, 'list' => []]; } $list = []; foreach($cache as $i => $item){ $list[] = [ 'id' => $i, 'question' => mb_substr($item['question_content'], 0, 30, 'UTF-8') . '...', 'author' => $item['type']['person'] ?? '', 'dynasty' => $item['type']['dynasty'] ?? '' ]; } return ['total' => count($list), 'list' => $list]; } function refreshCache(){ $apiData = fetchFromBaiduApi(); if($apiData === null){ return ['refreshed' => false, 'error' => 'API请求失败']; } $cache = loadCache(); $newCount = mergeToCache($apiData, $cache); return ['refreshed' => true, 'total' => count($cache), 'new_questions' => $newCount]; } function loadCache(){ global $cacheData; if($cacheData !== null){ return $cacheData; } if(!file_exists(CACHE_FILE)){ $cacheData = []; return []; } $content = file_get_contents(CACHE_FILE); if($content === false){ $cacheData = []; return []; } $data = json_decode($content, true); if(!is_array($data) || !isset($data['questions'])){ $cacheData = []; return []; } $cacheData = $data['questions']; return $cacheData; } function saveCache($questions){ global $cacheData; if(!is_dir(CACHE_DIR)){ mkdir(CACHE_DIR, 0755, true); } $data = [ 'updated' => date('Y-m-d H:i:s'), 'count' => count($questions), 'questions' => $questions ]; $tempFile = CACHE_FILE . '.tmp'; $result = file_put_contents($tempFile, json_encode($data, JSON_UNESCAPED_UNICODE), LOCK_EX); if($result !== false){ rename($tempFile, CACHE_FILE); } $cacheData = $questions; } function fetchFromBaiduApi(){ if(file_exists(API_LOCK_FILE)){ $lockTime = intval(file_get_contents(API_LOCK_FILE)); if(time() - $lockTime < API_INTERVAL){ return null; } } file_put_contents(API_LOCK_FILE, time()); $url = 'https://hanyu.baidu.com/hanyu/ajax/pingce_data'; $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_TIMEOUT => 5, CURLOPT_CONNECTTIMEOUT => 3, CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', CURLOPT_HTTPHEADER => [ 'Accept: application/json', 'Accept-Language: zh-CN,zh;q=0.9' ] ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if($httpCode !== 200 || empty($response)){ return null; } $json = json_decode($response, true); if(!isset($json['data']) || !is_array($json['data'])){ return null; } return $json['data']; } function mergeToCache($newData, &$existingCache){ if(empty($newData)){ return 0; } $existingKeys = []; foreach($existingCache as $item){ $key = $item['question_content'] ?? ''; $existingKeys[$key] = true; } $newCount = 0; foreach($newData as $item){ $key = $item['question_content'] ?? ''; if(!isset($existingKeys[$key])){ $existingCache[] = $item; $existingKeys[$key] = true; $newCount++; } } if($newCount > 0){ saveCache($existingCache); } return $newCount; } function formatOptions($options){ $result = []; foreach($options as $i => $opt){ $result[] = [ 'index' => $i + 1, 'content' => $opt['answer_content'] ?? '' ]; } return $result; } function findAnswer($options){ foreach($options as $i => $opt){ if(($opt['is_standard_answer'] ?? 0) === 1){ return (string)($i + 1); } } return ''; } ?>