true, 'num1' => $num1, 'num2' => $num2 ], JSON_UNESCAPED_UNICODE); exit; } if ($api === 'categories') { try { $categories = []; $debug_info['DB_findAll_exists'] = method_exists($DB, 'findAll') ? 'yes' : 'no'; if ($DB && method_exists($DB, 'findAll')) { $categories = $DB->findAll('category', '*', null, 'sid asc'); $debug_info['categories_count'] = count($categories); } if (empty($categories)) { $categories = [ ['catename' => '唐诗'], ['catename' => '宋词'], ['catename' => '元曲'], ['catename' => '诗词句'], ['catename' => '现代诗'] ]; $debug_info['used_fallback'] = 'yes'; } echo json_encode([ 'ok' => true, 'categories' => $categories, 'debug' => $debug_info ], JSON_UNESCAPED_UNICODE); } catch (Exception $e) { $debug_info['exception'] = $e->getMessage(); echo json_encode([ 'ok' => true, 'categories' => [ ['catename' => '唐诗'], ['catename' => '宋词'], ['catename' => '元曲'], ['catename' => '诗词句'], ['catename' => '现代诗'] ], 'debug' => $debug_info ], JSON_UNESCAPED_UNICODE); } exit; } if ($api === 'check-name') { if (!isset($_POST['name'])) { echo json_encode(['ok' => false, 'error' => '缺少name参数']); exit; } try { $name = trim($_POST['name']); $exists = false; $similar_count = 0; $max_similarity = 0; $threshold = isset($_POST['threshold']) ? intval($_POST['threshold']) : 80; $threshold = max(0, min(100, $threshold)); if ($DB && method_exists($DB, 'findAll')) { $tables_to_check = ['site', 'apply']; foreach ($tables_to_check as $table) { $all_records = $DB->findAll($table, 'name'); if ($all_records) { foreach ($all_records as $record) { $db_name = trim($record['name']); if ($db_name === $name) { $exists = true; $max_similarity = 100; $similar_count = 1; break 2; } $similarity = calculateSimilarity($name, $db_name); if ($similarity >= $threshold) { $similar_count++; if ($similarity > $max_similarity) { $max_similarity = $similarity; } } } } } } if ($max_similarity >= $threshold) { $exists = true; } echo json_encode([ 'ok' => true, 'exists' => $exists, 'similar_count' => $similar_count, 'max_similarity' => $max_similarity, 'threshold' => $threshold ], JSON_UNESCAPED_UNICODE); } catch (Exception $e) { echo json_encode([ 'ok' => true, 'exists' => false, 'similar_count' => 0, 'max_similarity' => 0, 'threshold' => 80 ], JSON_UNESCAPED_UNICODE); } exit; } if ($api === 'submit') { $submit_debug = []; session_start(); $client_ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $rate_limit_key = 'submit_rate_' . $client_ip; if (!isset($_SESSION[$rate_limit_key])) { $_SESSION[$rate_limit_key] = []; } $current_time = time(); $_SESSION[$rate_limit_key] = array_filter($_SESSION[$rate_limit_key], function($time) use ($current_time) { return ($current_time - $time) < 60; }); if (count($_SESSION[$rate_limit_key]) >= 3) { echo json_encode(['ok' => false, 'error' => '提交过于频繁,请稍后再试']); exit; } $img = isset($_POST['img']) ? trim($_POST['img']) : ''; $isFlutter = strpos($img, 'Flutter') !== false; $required = ['name', 'catename', 'url', 'keywords', 'introduce']; if (!$isFlutter) { $required[] = 'captcha'; } foreach ($required as $field) { if (!isset($_POST[$field]) || empty(trim($_POST[$field]))) { echo json_encode(['ok' => false, 'error' => "缺少必填字段:{$field}"]); exit; } } if (!$isFlutter) { $captcha = trim($_POST['captcha']); $captcha_key = 'captcha_' . session_id(); if (!isset($_SESSION[$captcha_key]) || $_SESSION[$captcha_key] != $captcha) { echo json_encode(['ok' => false, 'error' => '验证码错误,请重新输入']); exit; } unset($_SESSION[$captcha_key]); } try { $name = trim($_POST['name']); $threshold = isset($_POST['threshold']) ? intval($_POST['threshold']) : 80; $threshold = max(0, min(100, $threshold)); $similar_exists = false; if ($DB && method_exists($DB, 'findAll')) { $tables_to_check = ['site', 'apply']; foreach ($tables_to_check as $table) { $all_records = $DB->findAll($table, 'name'); if ($all_records) { foreach ($all_records as $record) { $db_name = trim($record['name']); if ($db_name === $name) { $similar_exists = true; break 2; } $similarity = calculateSimilarity($name, $db_name); if ($similarity >= $threshold) { $similar_exists = true; break 2; } } } } } if ($similar_exists) { echo json_encode(['ok' => false, 'error' => '该诗词已存在!']); exit; } $catename = trim($_POST['catename']); $url = trim($_POST['url']); $keywords = trim($_POST['keywords']); $introduce = trim($_POST['introduce']); $img = isset($_POST['img']) ? trim($_POST['img']) : 'default'; $submit_debug['input_data'] = [ 'name' => $name, 'catename' => $catename, 'url' => $url, 'keywords' => $keywords, 'introduce' => $introduce, 'img' => $img ]; $data = [ 'name' => $name, 'img' => $img, 'catename' => $catename, 'url' => $url, 'keywords' => $keywords, 'introduce' => $introduce, 'reject' => 0, 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s') ]; $submit_debug['insert_data'] = $data; $submit_debug['DB_insert_exists'] = method_exists($DB, 'insert') ? 'yes' : 'no'; $result = false; $db_error = ''; if ($DB && method_exists($DB, 'insert')) { $result = $DB->insert('apply', $data); $submit_debug['insert_result'] = $result; if (method_exists($DB, 'error')) { $db_error = $DB->error(); $submit_debug['db_error'] = $db_error; } if (method_exists($DB, 'lastInsertId')) { $submit_debug['last_insert_id'] = $DB->lastInsertId(); } } if ($result) { $_SESSION[$rate_limit_key][] = $current_time; echo json_encode([ 'ok' => true, 'message' => '✅ 提交成功!等待审核', 'debug' => $submit_debug ], JSON_UNESCAPED_UNICODE); } else { echo json_encode([ 'ok' => false, 'error' => '❌ 数据库写入失败:无法插入数据', 'debug' => $submit_debug ], JSON_UNESCAPED_UNICODE); } } catch (Exception $e) { $submit_debug['exception'] = $e->getMessage(); $submit_debug['trace'] = $e->getTraceAsString(); echo json_encode([ 'ok' => false, 'error' => $e->getMessage(), 'debug' => $submit_debug ], JSON_UNESCAPED_UNICODE); } exit; } } function calculateSimilarity($str1, $str2) { $str1 = preg_replace('/[^\p{L}\p{N}\s]/u', '', $str1); $str2 = preg_replace('/[^\p{L}\p{N}\s]/u', '', $str2); $str1 = preg_replace('/\s+/', '', $str1); $str2 = preg_replace('/\s+/', '', $str2); $len1 = mb_strlen($str1, 'UTF-8'); $len2 = mb_strlen($str2, 'UTF-8'); if ($len1 === 0 || $len2 === 0) { return 0; } $maxLen = max($len1, $len2); $distance = levenshtein($str1, $str2); if ($distance === 0) { return 100; } $similarity = round((1 - $distance / $maxLen) * 100, 2); return max(0, min(100, $similarity)); } echo json_encode(['ok' => false, 'error' => '无效的API请求']);