From 31a0b5f7d635e7f95e042ec02a63276aab3c0c25 Mon Sep 17 00:00:00 2001
From: Tiaotiao <65841827@qq.com>
Date: Sun, 3 May 2026 11:47:34 +0800
Subject: [PATCH 1/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20med.php?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
med.php | 869 +++++++++++++++++++++++++-------------------------------
1 file changed, 383 insertions(+), 486 deletions(-)
diff --git a/med.php b/med.php
index cf38c52..4a21b15 100644
--- a/med.php
+++ b/med.php
@@ -1,195 +1,123 @@
'));
+define('DEFAULT_COVER', 'data:image/svg+xml;base64,' . base64_encode(''));
+
+// ---------- API 请求函数 ----------
function getContentSummary($contentId, $category, $token, $authCode) {
- $baseUrl = 'http://nlm-api-cn.turtlesim.com/';
- $url = $baseUrl . 'Contents/GetSummary';
-
- $requestData = [
- 'ContentID' => $contentId,
- 'Category' => $category,
- ];
-
+ $url = 'http://nlm-api-cn.turtlesim.com/Contents/GetSummary';
+ $body = json_encode(['ContentID' => $contentId, 'Category' => $category]);
$headers = [
- "Content-Type: application/json",
- "Accept: application/json",
- "Accept-Language: zh-CN",
- "x-API-Token: " . $token,
- "x-API-AuthCode: " . $authCode,
+ 'Content-Type: application/json', 'Accept: application/json', 'Accept-Language: zh-CN',
+ 'x-API-Token: ' . $token, 'x-API-AuthCode: ' . $authCode,
];
-
$ch = curl_init($url);
curl_setopt_array($ch, [
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_HEADER => true,
- CURLOPT_POST => true,
- CURLOPT_HTTPHEADER => $headers,
- CURLOPT_POSTFIELDS => json_encode($requestData),
- CURLOPT_FOLLOWLOCATION => true,
- CURLOPT_TIMEOUT => 15,
- CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
- CURLOPT_SSL_VERIFYPEER => true,
+ CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true, CURLOPT_POST => true,
+ CURLOPT_HTTPHEADER => $headers, CURLOPT_POSTFIELDS => $body,
+ CURLOPT_TIMEOUT => 15, CURLOPT_USERAGENT => 'Mozilla/5.0', CURLOPT_SSL_VERIFYPEER => true,
]);
-
$response = curl_exec($ch);
- if ($response === false) {
- curl_close($ch);
- return null;
- }
-
- $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
- $body = substr($response, $headerSize);
+ $bodyResp = substr($response, $headerSize);
curl_close($ch);
-
- $responseData = json_decode($body, true);
- return json_last_error() === JSON_ERROR_NONE ? $responseData : null;
+ $data = json_decode($bodyResp, true);
+ return (json_last_error() === JSON_ERROR_NONE) ? $data : null;
}
-// 获取改编列表
-function getDerivatives($contentId, $category, $token, $authCode) {
- $baseUrl = 'http://nlm-api-cn.turtlesim.com/';
- $url = $baseUrl . 'Contents/GetDerivatives';
-
- $requestData = [
- 'ContentID' => $contentId,
- 'Category' => $category,
- 'Language' => 'Chinese',
- 'WithSummary' => true
- ];
-
+function getDerivativesAndSupporters($contentId, $category, $token, $authCode) {
+ $url = 'http://nlm-api-cn.turtlesim.com/Contents/GetDerivatives';
+ $body = json_encode(['ContentID' => $contentId, 'Category' => $category]);
$headers = [
- "Content-Type: application/json",
- "Accept: application/json",
- "Accept-Language: zh-CN",
- "x-API-Token: " . $token,
- "x-API-AuthCode: " . $authCode,
+ 'Content-Type: application/json', 'Accept: application/json', 'Accept-Language: zh-CN',
+ 'x-API-Token: ' . $token, 'x-API-AuthCode: ' . $authCode,
];
-
$ch = curl_init($url);
curl_setopt_array($ch, [
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_HEADER => true,
- CURLOPT_POST => true,
- CURLOPT_HTTPHEADER => $headers,
- CURLOPT_POSTFIELDS => json_encode($requestData),
- CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
+ CURLOPT_HTTPHEADER => $headers, CURLOPT_POSTFIELDS => $body,
CURLOPT_TIMEOUT => 15,
]);
-
$response = curl_exec($ch);
- $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
- $body = substr($response, $headerSize);
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ $curlError = curl_error($ch);
curl_close($ch);
-
- $data = json_decode($body, true);
- return json_last_error() === JSON_ERROR_NONE ? $data : null;
+
+ // 调试日志(上线后可注释)
+ // error_log("GetDerivatives HTTP Code: $httpCode, Error: $curlError, Response: $response");
+
+ if ($response === false || $httpCode !== 200) return null;
+ $data = json_decode($response, true);
+ if (json_last_error() !== JSON_ERROR_NONE) return null;
+ return $data['Data'] ?? null;
}
-// 检查是否已收藏(Star)
function isContentStarred($contentId, $category, $token, $authCode) {
- $baseUrl = 'http://nlm-api-cn.turtlesim.com/';
- $url = $baseUrl . 'Contents/IsStarred';
-
- $requestData = [
- 'ContentID' => $contentId,
- 'Category' => $category,
- ];
-
+ $url = 'http://nlm-api-cn.turtlesim.com/Contents/IsStarred';
+ $body = json_encode(['ContentID' => $contentId, 'Category' => $category]);
$headers = [
- "Content-Type: application/json",
- "x-API-Token: " . $token,
- "x-API-AuthCode: " . $authCode,
+ 'Content-Type: application/json',
+ 'x-API-Token: ' . $token, 'x-API-AuthCode: ' . $authCode,
];
-
$ch = curl_init($url);
curl_setopt_array($ch, [
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_HEADER => true,
- CURLOPT_POST => true,
- CURLOPT_HTTPHEADER => $headers,
- CURLOPT_POSTFIELDS => json_encode($requestData),
- CURLOPT_TIMEOUT => 10,
+ CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true, CURLOPT_POST => true,
+ CURLOPT_HTTPHEADER => $headers, CURLOPT_POSTFIELDS => $body, CURLOPT_TIMEOUT => 10,
]);
-
$response = curl_exec($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
- $body = substr($response, $headerSize);
+ $bodyResp = substr($response, $headerSize);
curl_close($ch);
-
- $data = json_decode($body, true);
- if ($data && isset($data['Data']) && is_bool($data['Data'])) {
- return $data['Data'];
- }
- return false;
-}
-
-// 获取作品详情
-$contentData = null;
-if (!empty($contentId) && !empty($category)) {
- $token = $_SESSION['token'] ?? '';
- $authCode = $_SESSION['authCode'] ?? '';
-
- if (isset($token) && isset($authCode)) {
- $contentData = getContentSummary($contentId, $category, $token, $authCode);
- }
+ $data = json_decode($bodyResp, true);
+ return ($data && isset($data['Data']) && $data['Data'] === true);
}
+// ---------- 获取数据 ----------
+$contentData = getContentSummary($contentId, $category, $token, $authCode);
$content = $contentData['Data'] ?? null;
-// 获取改编列表
-$remixes = [];
-$isStarred = false;
-if ($content && $contentId && $category) {
- $derivativesData = getDerivatives($contentId, $category, $token, $authCode);
- if ($derivativesData && isset($derivativesData['Data']['Experiments']['Children-Models'])) {
- $remixes = $derivativesData['Data']['Experiments']['Children-Models'];
- }
- // 获取初始收藏状态
- $isStarred = isContentStarred($contentId, $category, $token, $authCode);
-}
+// 改编 + 支持者
+$derivativesData = getDerivativesAndSupporters($contentId, $category, $token, $authCode);
+$remixes = $derivativesData['Experiments']['Children-Models'] ?? [];
+$supporters = $derivativesData['Supporters'] ?? [];
+$parentModel = $derivativesData['Model'] ?? null;
-// 处理日期格式
-function formatDate($timestamp) {
- return date('Y年m月d日', $timestamp / 1000);
+$isStarred = isContentStarred($contentId, $category, $token, $authCode);
+
+// ---------- 辅助函数 ----------
+function buildAvatarUrl($userId, $avatarId) {
+ if (!$avatarId || !$userId) return DEFAULT_AVATAR;
+ $base = 'http://netlogo-cn.oss-cn-hongkong.aliyuncs.com/users/avatars/';
+ return $base . substr($userId,0,4) . '/' . substr($userId,4,2) . '/' . substr($userId,6,2) . '/' . substr($userId,8,16) . '/' . $avatarId . '.jpg!full';
}
-// 页面标题映射
-$pageTitles = [
- 'explore' => '探索指南',
- 'featured' => '精选实验',
- 'daily' => '每日模型',
- 'hot' => '热门实验',
- 'new' => '最新实验',
- 'visual' => '可视化编程',
- 'knowledge' => '实验知识库'
-];
-$pageTitle = $pageTitles[$type] ?? '作品详情';
+function buildThumbUrl($exp) {
+ if (($exp['Image'] ?? 0) < 0) return DEFAULT_COVER;
+ $base = 'http://netlogo-cn.oss-cn-hongkong.aliyuncs.com/experiments/images/';
+ $id = $exp['ID'];
+ return $base . substr($id,0,4) . '/' . substr($id,4,2) . '/' . substr($id,6,2) . '/' . substr($id,8,16) . '/' . $exp['Image'] . '.jpg!full';
+}
-// 自定义标签解析器类
class CustomTagParser {
public static function parse(string $text): string {
if (empty($text)) return '';
$text = htmlspecialchars($text);
- $text = self::parseMarkdownHeadings($text);
$text = nl2br($text);
-
$patterns = [
'/<user=([a-f0-9]+)>(.*?)<\/user>/i',
'/<experiment=([a-f0-9]+)>(.*?)<\/experiment>/i',
@@ -202,7 +130,6 @@ public static function parse(string $text): string {
'/<i>(.*?)<\/i>/i',
'/<a>(.*?)<\/a>/i'
];
-
$replacements = [
'$2',
'$2',
@@ -215,21 +142,7 @@ public static function parse(string $text): string {
'$1',
'$1'
];
-
$text = preg_replace($patterns, $replacements, $text);
- $text = self::parseSimpleMarkdown($text);
- return $text;
- }
-
- private static function parseMarkdownHeadings(string $text): string {
- $text = preg_replace('/^# (.+)$/m', '$1', $text);
- $text = preg_replace('/^## (.+)$/m', '$1', $text);
- $text = preg_replace('/^### (.+)$/m', '$1', $text);
- $text = preg_replace('/^#### (.+)$/m', '$1', $text);
- return $text;
- }
-
- private static function parseSimpleMarkdown(string $text): string {
$text = preg_replace('/\*\*(.*?)\*\*/', '$1', $text);
$text = preg_replace('/\*(.*?)\*/', '$1', $text);
$text = preg_replace('/~~(.*?)~~/', '$1', $text);
@@ -244,204 +157,176 @@ private static function parseSimpleMarkdown(string $text): string {
-
-
= htmlspecialchars($content['LocalizedSubject']['Chinese'] ?? $pageTitle) ?> - Turtle Universe Web
+ = htmlspecialchars($content['LocalizedSubject']['Chinese'] ?? $content['Subject'] ?? '作品详情') ?> - Turtle Universe Web
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ = htmlspecialchars($content['Category']) ?>
+ = $content['Visits'] ?? 0 ?>
+
+
+ = htmlspecialchars($tag) ?>
+
+
-
-
-
-
-
= htmlspecialchars($content['LocalizedSubject']['Chinese'] ?? $content['Subject']) ?>
-
- = htmlspecialchars($content['Category']) ?>
- = $content['Visits'] ?? 0 ?>
-
-
- = htmlspecialchars($tag) ?>
-
-
-
+
+
+
赞 = $content['Supports'] ?? 0 ?>
+
收藏
+
= $content['Comments'] ?? 0 ?>
+
分享
-
-
-
-
-
- 赞 = $content['Supports'] ?? 0 ?>
-
-
- 收藏
-
-
- = $content['Comments'] ?? 0 ?>
-
-
- 分享
-
-
-
-
-
-
-
-
+
+
+
+
-
-