diff --git a/Plugin.php b/Plugin.php new file mode 100644 index 0000000..9b285b8 --- /dev/null +++ b/Plugin.php @@ -0,0 +1,2527 @@ +contentEx = array('MovieInfo_Plugin', 'parse'); + Typecho_Plugin::factory('Widget_Abstract_Contents')->excerptEx = array('MovieInfo_Plugin', 'parse'); + Typecho_Plugin::factory('admin/write-post.php')->bottom = array('MovieInfo_Plugin', 'renderButton'); + Typecho_Plugin::factory('admin/write-page.php')->bottom = array('MovieInfo_Plugin', 'renderButton'); + + $cacheDir = dirname(__FILE__) . '/cache/'; + if (!file_exists($cacheDir)) mkdir($cacheDir, 0755, true); + + return 'TMDB电影插件激活成功!'; + } + + /** + * 禁用插件 + */ + public static function deactivate() + { + return '插件已禁用'; + } + + /** + * 配置面板 + */ + public static function config(Typecho_Widget_Helper_Form $form) + { + // TMDB API 配置 + $tmdbApiKey = new Typecho_Widget_Helper_Form_Element_Text('tmdbApiKey', NULL, '', + 'TMDB API Key', '在TMDB网站申请的API密钥'); + $form->addInput($tmdbApiKey); + + $language = new Typecho_Widget_Helper_Form_Element_Select('language', + array( + 'zh-CN' => '中文', + 'en-US' => '英文', + 'ja-JP' => '日文', + 'ko-KR' => '韩文', + 'fr-FR' => '法文' + ), 'zh-CN', '显示语言', '电影信息的显示语言'); + $form->addInput($language); + + $cacheEnable = new Typecho_Widget_Helper_Form_Element_Radio('cacheEnable', + array('1' => '启用', '0' => '禁用'), + '1', '启用缓存', '缓存电影信息,提升访问速度'); + $form->addInput($cacheEnable); + + $cacheTime = new Typecho_Widget_Helper_Form_Element_Text('cacheTime', NULL, '30', + '缓存时间(天)', '电影信息缓存保留天数'); + $cacheTime->addRule('isInteger', '请输入整数'); + $form->addInput($cacheTime); + + $imageProxy = new Typecho_Widget_Helper_Form_Element_Text('imageProxy', NULL, + 'https://images.weserv.nl/?url=', '图片代理', '用于加载TMDB图片'); + $form->addInput($imageProxy); + + $defaultPoster = new Typecho_Widget_Helper_Form_Element_Text('defaultPoster', NULL, + 'https://via.placeholder.com/300x450/CCCCCC/666666?text=No+Poster', + '默认海报', '当无法获取海报时显示的图片'); + $form->addInput($defaultPoster); + + $summaryLength = new Typecho_Widget_Helper_Form_Element_Text('summaryLength', NULL, '200', + '简介显示长度', '简介默认显示的最大字符数,超出部分可展开查看'); + $summaryLength->addRule('isInteger', '请输入整数'); + $form->addInput($summaryLength); + + $expandText = new Typecho_Widget_Helper_Form_Element_Text('expandText', NULL, '展开', + '"展开"文字', '点击展开完整简介的文字'); + $form->addInput($expandText); + + $collapseText = new Typecho_Widget_Helper_Form_Element_Text('collapseText', NULL, '收起', + '"收起"文字', '点击收起简介的文字'); + $form->addInput($collapseText); + + $expandColor = new Typecho_Widget_Helper_Form_Element_Text('expandColor', NULL, '#0073aa', + '展开按钮颜色', '展开/收起按钮的文字颜色'); + $form->addInput($expandColor); + + // 独立页面每页显示条数设置 + $pageSize = new Typecho_Widget_Helper_Form_Element_Text('pageSize', NULL, '10', + '独立页面每页显示条数', '在独立页面中每页显示的电影数量(1-50)'); + $pageSize->addRule('isInteger', '请输入整数'); + $pageSize->addRule(array(new MovieInfo_Plugin, 'validatePageSize'), '请输入1-50之间的整数'); + $form->addInput($pageSize); + } + + /** + * 验证页面显示条数 + */ + public static function validatePageSize($value) + { + $value = intval($value); + if ($value < 1 || $value > 50) { + throw new Typecho_Widget_Exception('请输入1-50之间的整数'); + } + return true; + } + + /** + * 个人配置面板 + */ + public static function personalConfig(Typecho_Widget_Helper_Form $form) + { + } + + /** + * 解析短代码 + */ + public static function parse($content, $widget, $lastResult) + { + $content = empty($lastResult) ? $content : $lastResult; + + // 如果是独立页面,且内容中包含[all_movies]标记,则显示所有电影 + if ($widget instanceof Widget_Archive && $widget->is('page')) { + $pattern = '/\[all_movies(?::page=(\d+))?\]/i'; + if (preg_match_all($pattern, $content, $matches)) { + foreach ($matches[0] as $key => $match) { + $page = isset($matches[1][$key]) ? intval($matches[1][$key]) : 1; + $allMoviesHtml = self::renderAllMovies($page); + $content = str_replace($match, $allMoviesHtml, $content); + } + } + } + + // 如果是单篇文章,解析电影短代码 + if ($widget instanceof Widget_Archive && $widget->is('single')) { + // 匹配 [movie:数字] 或 [movie:数字:短评] 格式 + $pattern = '/\[movie:(\d+)(?::([^\]]+))?\]/i'; + if (preg_match_all($pattern, $content, $matches)) { + foreach ($matches[0] as $key => $match) { + $movieId = $matches[1][$key]; + $reviewWithCustom = isset($matches[2][$key]) ? trim($matches[2][$key]) : ''; + + $review = ''; + $customData = array(); + + // 解码短评和自定义数据 + if (!empty($reviewWithCustom)) { + // 分离短评和自定义数据 + if (strpos($reviewWithCustom, '|CUSTOM:') !== false) { + list($review, $customJson) = explode('|CUSTOM:', $reviewWithCustom, 2); + + // 解码自定义数据 + if (!empty($customJson)) { + $decodedJson = urldecode($customJson); + $customData = json_decode($decodedJson, true); + if (!is_array($customData)) { + $customData = array(); + } + } + } else { + // 检查旧格式的自定义数据 + if (preg_match('/^(自定义:(.*))$/u', $reviewWithCustom, $customMatch)) { + $review = ''; + $customData = self::parseLegacyCustomData($customMatch[1]); + } else { + // 检查中文括号格式 + if (preg_match('/^(.*?)(自定义:(.*))$/u', $reviewWithCustom, $customMatch)) { + $review = trim($customMatch[1]); + $customData = self::parseLegacyCustomData($customMatch[2]); + } else { + $review = $reviewWithCustom; + } + } + } + + // 解码短评 + if (!empty($review)) { + $review = str_replace(array('[', ']'), array('[', ']'), $review); + } + } + + // 获取电影数据 + $movieHtml = self::renderMovie($movieId, $review, $customData); + $content = str_replace($match, $movieHtml, $content); + } + } + } + + return $content; + } + + /** + * 解析旧格式的自定义数据 + */ + private static function parseLegacyCustomData($customText) + { + $customData = array(); + + $pairs = explode(',', $customText); + foreach ($pairs as $pair) { + if (strpos($pair, ':') !== false) { + list($key, $value) = explode(':', $pair, 2); + switch (trim($key)) { + case '开始观看': + $customData['startDate'] = trim($value); + break; + case '结束观看': + $customData['watchDate'] = trim($value); + break; + case '观看方式': + $customData['watchMethod'] = trim($value); + break; + case '电影分类': + $customData['movieCategory'] = trim($value); + break; + case '推荐指数': + $starCount = substr_count($value, '★'); + $customData['recommendation'] = $starCount; + break; + case '我的评分': + $customData['myRating'] = trim($value); + break; + } + } + } + + return $customData; + } + + /** + * 渲染单部电影信息 + */ + private static function renderMovie($movieId, $review = '', $customData = array()) + { + // 获取电影数据 + $movieData = self::getMovieData($movieId, $review, $customData); + + if (!$movieData || empty($movieData['title'])) { + return '
+ 获取电影信息失败,ID:' . htmlspecialchars($movieId) . ' +
'; + } + + $options = Typecho_Widget::widget('Widget_Options')->plugin('MovieInfo'); + $imageProxy = isset($options->imageProxy) ? $options->imageProxy : 'https://images.weserv.nl/?url='; + $defaultPoster = isset($options->defaultPoster) ? $options->defaultPoster : + 'https://via.placeholder.com/300x450/CCCCCC/666666?text=No+Poster'; + $summaryLength = isset($options->summaryLength) ? intval($options->summaryLength) : 200; + $expandText = isset($options->expandText) ? $options->expandText : '展开'; + $collapseText = isset($options->collapseText) ? $options->collapseText : '收起'; + $expandColor = isset($options->expandColor) ? $options->expandColor : '#0073aa'; + + $title = htmlspecialchars($movieData['title']); + $originalTitle = isset($movieData['original_title']) ? htmlspecialchars($movieData['original_title']) : ''; + $releaseYear = isset($movieData['release_year']) ? htmlspecialchars($movieData['release_year']) : '未知'; + $director = isset($movieData['director']) ? htmlspecialchars($movieData['director']) : '未知'; + $genres = isset($movieData['genres']) ? $movieData['genres'] : array('未知'); + $runtime = isset($movieData['runtime']) ? htmlspecialchars($movieData['runtime']) . '分钟' : '未知'; + $summary = isset($movieData['overview']) ? $movieData['overview'] : ''; + $rating = isset($movieData['vote_average']) ? floatval($movieData['vote_average']) : 0; + $ratingCount = isset($movieData['vote_count']) ? intval($movieData['vote_count']) : 0; + $productionCountries = isset($movieData['production_countries']) ? $movieData['production_countries'] : array('未知'); + + $review = htmlspecialchars($review); + + // 自定义字段 + $startDate = isset($customData['startDate']) ? htmlspecialchars($customData['startDate']) : ''; + $watchDate = isset($customData['watchDate']) ? htmlspecialchars($customData['watchDate']) : ''; + $watchMethod = isset($customData['watchMethod']) ? htmlspecialchars($customData['watchMethod']) : ''; + $movieCategory = isset($customData['movieCategory']) ? htmlspecialchars($customData['movieCategory']) : ''; + $recommendation = isset($customData['recommendation']) ? intval($customData['recommendation']) : 0; + $myRating = isset($customData['myRating']) ? htmlspecialchars($customData['myRating']) : ''; + + // 如果customData中没有,尝试从movieData中获取 + if (empty($startDate) && isset($movieData['custom_start_date']) && !empty($movieData['custom_start_date'])) { + $startDate = htmlspecialchars($movieData['custom_start_date']); + } + if (empty($watchDate) && isset($movieData['custom_watch_date']) && !empty($movieData['custom_watch_date'])) { + $watchDate = htmlspecialchars($movieData['custom_watch_date']); + } + if (empty($watchMethod) && isset($movieData['custom_watch_method']) && !empty($movieData['custom_watch_method'])) { + $watchMethod = htmlspecialchars($movieData['custom_watch_method']); + } + if (empty($movieCategory) && isset($movieData['custom_movie_category']) && !empty($movieData['custom_movie_category'])) { + $movieCategory = htmlspecialchars($movieData['custom_movie_category']); + } + if ($recommendation == 0 && isset($movieData['custom_recommendation'])) { + $recommendation = intval($movieData['custom_recommendation']); + } + if (empty($myRating) && isset($movieData['custom_my_rating'])) { + $myRating = htmlspecialchars($movieData['custom_my_rating']); + } + + // 检查简介长度 + $isSummaryLong = false; + $summaryShort = $summary; + + $plainSummary = strip_tags($summary); + if (mb_strlen($plainSummary, 'UTF-8') > $summaryLength) { + $isSummaryLong = true; + $plainShort = mb_substr($plainSummary, 0, $summaryLength, 'UTF-8'); + $summaryShort = $plainShort . '...'; + } + + // 海报URL + $posterPath = isset($movieData['poster_path']) ? $movieData['poster_path'] : ''; + if ($posterPath) { + $posterUrl = 'https://image.tmdb.org/t/p/w300' . $posterPath; + $posterSrc = $imageProxy . urlencode($posterUrl); + } else { + $posterSrc = $defaultPoster; + } + + // 类型显示 - 确保不换行 + $genresHtml = ''; + if (is_array($genres)) { + $genresHtml = implode(' / ', $genres); + } + + // 地区显示 + $countriesHtml = ''; + if (is_array($productionCountries)) { + $countriesHtml = implode(' / ', $productionCountries); + } + + // TMDB评分显示 - 移除括号和评价人数 + $ratingHtml = ''; + if ($rating > 0) { + $ratingHtml = '
+ 评分: + ' . number_format($rating, 1) . ' +
'; + } + + // 我的评分显示 + $myRatingHtml = ''; + if (!empty($myRating)) { + $myRatingHtml = '
+ 我的评分: + ' . $myRating . ' +
'; + } + + // 推荐指数星星 + $recommendationHtml = ''; + if ($recommendation > 0) { + $recommendationHtml = '
+ 推荐指数:'; + + for ($i = 1; $i <= 5; $i++) { + if ($i <= $recommendation) { + $recommendationHtml .= ''; + } else { + $recommendationHtml .= ''; + } + } + $recommendationHtml .= '
'; + } + + // 自定义信息 - 按图书插件逻辑处理开始和结束观看 + $customInfoHtml = ''; + $hasCustomInfo = false; + + // 判断开始和结束观看日期是否相同 + $hasStartDate = !empty($startDate); + $hasWatchDate = !empty($watchDate); + $datesEqual = $hasStartDate && $hasWatchDate && $startDate === $watchDate; + + if ($hasStartDate || $hasWatchDate || $watchMethod || $movieCategory) { + $hasCustomInfo = true; + + if ($datesEqual) { + // 开始和结束观看日期相同,显示"观看日期" + $customInfoHtml .= '
+ 观看日期: + ' . $startDate . ' +
'; + } else { + // 日期不同或只有一个日期,分开显示 + if ($startDate) { + $customInfoHtml .= '
+ 开始观看: + ' . $startDate . ' +
'; + } + + if ($watchDate) { + $customInfoHtml .= '
+ 结束观看: + ' . $watchDate . ' +
'; + } + } + + if ($watchMethod) { + $customInfoHtml .= '
+ 观看方式: + ' . $watchMethod . ' +
'; + } + + if ($movieCategory) { + $customInfoHtml .= '
+ 电影分类: + ' . $movieCategory . ' +
'; + } + } + + // 右侧栏完整HTML + $rightColumnHtml = ''; + + if ($myRatingHtml) { + $rightColumnHtml .= $myRatingHtml; + } + + if ($recommendationHtml) { + $rightColumnHtml .= $recommendationHtml; + } + + if ($customInfoHtml) { + $rightColumnHtml .= $customInfoHtml; + } else { + $rightColumnHtml .= '
+ 观看记录: + 暂无记录 +
'; + } + + // 简介部分HTML + $summaryHtml = '
'; + + if ($isSummaryLong) { + $summaryHtml .= ' +
+
+ ' . nl2br($summaryShort) . ' + ' + . htmlspecialchars($expandText) . ' ↓ + +
+
+ '; + } else { + $summaryHtml .= ' +
+ ' . $summary . ' +
'; + } + + $summaryHtml .= '
'; + + // 短评HTML + $reviewHtml = ''; + if (!empty($review)) { + $reviewHtml = '
+
💭 我的影评
+
+ ' . nl2br($review) . ' +
+
'; + } + + // 原始标题显示 - 仅作为鼠标悬停提示 + $titleTooltip = ''; + if ($originalTitle && $originalTitle != $title) { + $titleTooltip = ' title="原名:' . $originalTitle . '"'; + } + + $html = << +:root { + --movie-bg-primary: #ffffff; + --movie-bg-secondary: #f9fafb; + --movie-bg-tertiary: #fafafa; + --movie-bg-card: #ffffff; + --movie-text-primary: #1a1a1a; + --movie-text-secondary: #666666; + --movie-text-tertiary: #999999; + --movie-primary-color: #0073aa; + --movie-primary-hover: #0056b3; + --movie-accent-color: #01d277; + --movie-accent-hover: #01b36b; + --movie-border-color: #e8e8e8; + --movie-border-light: #f0f0f0; + --movie-shadow-color: rgba(0,0,0,0.08); + --movie-rating-color: #ffac2d; + --movie-my-rating-color: #ff6b35; + --movie-star-color: #ff6b35; + --movie-star-empty-color: #dddddd; + --movie-button-bg: #f8f9fa; + --movie-button-hover-bg: #e9ecef; + --movie-review-bg: #f9f9f9; +} + +@media (prefers-color-scheme: dark) { + :root { + --movie-bg-primary: #1a1a1a; + --movie-bg-secondary: #2d2d2d; + --movie-bg-tertiary: #2a2a2a; + --movie-bg-card: #2d2d2d; + --movie-text-primary: #e0e0e0; + --movie-text-secondary: #aaaaaa; + --movie-text-tertiary: #888888; + --movie-primary-color: #4dabf7; + --movie-primary-hover: #74c0fc; + --movie-accent-color: #20c997; + --movie-accent-hover: #12b886; + --movie-border-color: #404040; + --movie-border-light: #333333; + --movie-shadow-color: rgba(0,0,0,0.2); + --movie-rating-color: #ffc107; + --movie-my-rating-color: #ff922b; + --movie-star-color: #ff922b; + --movie-star-empty-color: #555555; + --movie-button-bg: #3a3a3a; + --movie-button-hover-bg: #4a4a4a; + --movie-review-bg: #3a3a3a; + } +} +.dark .markdown-body h2{border-bottom:0px!important;margin-top:0px!important;padding-bottom:0px!important;margin-bottom:0px!important;} +.movie-card-content { + background: var(--movie-bg-card); + border-radius: 12px; + box-shadow: 0 4px 12px var(--movie-shadow-color); + overflow: hidden; + border: 1px solid var(--movie-border-color); + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.movie-card-content:hover { + transform: translateY(-2px); + box-shadow: 0 6px 16px var(--movie-shadow-color); +} + +.movie-header { + padding: 20px 25px; + background: linear-gradient(135deg, var(--movie-bg-secondary) 0%, var(--movie-bg-tertiary) 100%); + border-bottom: 1px solid var(--movie-border-light); + text-align: center; +} + +.movie-title { + margin: 0; + font-size: 22px; + line-height: 1.3; + color: var(--movie-text-primary); + font-weight: 700; +} + +.movie-title-link { + color: var(--movie-primary-color); + text-decoration: none; + transition: color 0.2s ease; +} + +.movie-title-link:hover { + color: var(--movie-primary-hover); + text-decoration: underline; +} + +.movie-content { + padding: 25px; + border-bottom: 1px solid var(--movie-border-light); + background: var(--movie-bg-card); +} + +.movie-grid { + display: grid; + grid-template-columns: 120px 1fr 1fr; + gap: 25px; + align-items: stretch; +} + +@media (max-width: 768px) { + .movie-grid { + grid-template-columns: 1fr; + gap: 20px; + } + + .movie-grid > div:nth-child(2) { + border-right: none; + padding-right: 0; + } + + .movie-grid > div:nth-child(3) { + padding-left: 0; + } +} + +.movie-poster-container { + display: flex; + align-items: center; + justify-content: center; +} + +.movie-poster-link { + display: block; + text-decoration: none; + width: 100%; +} + +.movie-poster-wrapper { + position: relative; + width: 100%; +} + +.movie-poster-frame { + width: 100%; + height: 0; + padding-bottom: 150%; + position: relative; + overflow: hidden; + border-radius: 8px; + border: 3px solid var(--movie-bg-card); + box-shadow: 0 4px 12px rgba(0,0,0,0.12); + background: var(--movie-bg-tertiary); +} + +.movie-poster { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.movie-poster:hover { + transform: scale(1.05); +} + +.movie-poster-badge { + position: absolute; + top: -5px; + right: -5px; + background: var(--movie-accent-color); + color: white; + width: 24px; + height: 24px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + font-weight: bold; + box-shadow: 0 2px 4px rgba(1,210,119,0.3); +} + +.movie-info-left { + padding-right: 15px; + border-right: 1px solid var(--movie-border-color); +} + +.movie-info-item { + margin: 0 0 10px 0; + font-size: 14px; + color: var(--movie-text-secondary); + line-height: 1.5; +} + +.movie-info-label { + font-weight: 600; + color: var(--movie-text-primary); + display: inline-block; + width: 70px; + flex-shrink: 0; +} + +.movie-info-value { + color: var(--movie-text-primary); +} + +.movie-genres { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: inline; +} + +.movie-info-right { + padding-left: 15px; +} + +.movie-footer { + padding: 20px 25px 25px 25px; +} + +.movie-summary-section { + margin-bottom: 20px; +} + +.movie-summary-header { + margin: 0 0 12px 0; + font-size: 16px; + color: var(--movie-text-primary); + font-weight: 600; + display: flex; + align-items: center; + gap: 8px; + padding-bottom: 8px; + border-bottom: 1px solid var(--movie-border-color); +} + +.movie-summary-icon { + background: var(--movie-accent-color); + color: white; + width: 28px; + height: 28px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; +} + +.movie-summary-content { + background: var(--movie-bg-tertiary); + padding: 20px; + border-radius: 8px; + border: 1px solid var(--movie-border-color); + box-shadow: 0 1px 3px rgba(0,0,0,0.05); +} + + +
+
+ + + + +
+
+ + + + +
+ +
+ 导演: + {$director} +
+ + +
+ 类型: + {$genresHtml} +
+ + +
+ 年份: + {$releaseYear} +
+ + +
+ 时长: + {$runtime} +
+ + +
+ 地区: + {$countriesHtml} +
+ + + {$ratingHtml} +
+ + +
+ {$rightColumnHtml} +
+
+
+ + + +
+
+HTML; + + // 添加JavaScript切换函数 + $html .= ' + '; + + return $html; + } + + /** + * 获取所有电影数据(支持分页) + */ + private static function getAllMoviesData($page = 1, $pageSize = 10) + { + $cacheDir = dirname(__FILE__) . '/cache/'; + $allMovies = array(); + + // 扫描缓存目录 + if (file_exists($cacheDir)) { + $files = scandir($cacheDir); + foreach ($files as $file) { + if (pathinfo($file, PATHINFO_EXTENSION) === 'json') { + $filePath = $cacheDir . $file; + $content = file_get_contents($filePath); + if ($content) { + $data = json_decode($content, true); + if ($data && isset($data['fetched_at'])) { + $movieId = pathinfo($file, PATHINFO_FILENAME); + $data['movieId'] = $movieId; + + if (file_exists($filePath)) { + $data['added_time'] = filemtime($filePath); + } else { + $data['added_time'] = isset($data['fetched_at']) ? $data['fetched_at'] : time(); + } + + $allMovies[] = $data; + } + } + } + } + } + + // 按added_time倒序排序 + usort($allMovies, function($a, $b) { + return $b['added_time'] - $a['added_time']; + }); + + $total = count($allMovies); + $totalPages = ceil($total / $pageSize); + + // 限制页码范围 + $page = max(1, min($page, $totalPages)); + + // 分页处理 + $startIndex = ($page - 1) * $pageSize; + $paginatedMovies = array_slice($allMovies, $startIndex, $pageSize); + + return array( + 'movies' => $paginatedMovies, + 'total' => $total, + 'page' => $page, + 'pageSize' => $pageSize, + 'totalPages' => $totalPages, + 'startIndex' => $startIndex + 1, + 'endIndex' => min($startIndex + $pageSize, $total) + ); + } + + /** + * 渲染所有电影列表(简单文本格式)- 支持分页 + */ + public static function renderAllMovies($page = 1) + { + // 从GET参数获取页码 + if (isset($_GET['page']) && is_numeric($_GET['page'])) { + $page = intval($_GET['page']); + } + + $options = Typecho_Widget::widget('Widget_Options')->plugin('MovieInfo'); + $pageSize = isset($options->pageSize) ? intval($options->pageSize) : 10; + $imageProxy = isset($options->imageProxy) ? $options->imageProxy : 'https://images.weserv.nl/?url='; + $defaultPoster = isset($options->defaultPoster) ? $options->defaultPoster : + 'https://via.placeholder.com/300x450/CCCCCC/666666?text=No+Poster'; + + // 获取分页数据 + $paginationData = self::getAllMoviesData($page, $pageSize); + $allMovies = $paginationData['movies']; + $total = $paginationData['total']; + $currentPage = $paginationData['page']; + $totalPages = $paginationData['totalPages']; + $startIndex = $paginationData['startIndex']; + $endIndex = $paginationData['endIndex']; + + if (empty($allMovies)) { + return '
+

暂无电影数据

+

请先在文章中使用[movie:ID]短代码添加电影

+
'; + } + + $html = ''; + + $html .= '
'; + + // 标题模块 - 调整深色模式 + $html .= '
+

🎬 我的全部已看电影

+

已记录 ' . $total . ' 部电影,继续探索更多精彩影片

+
'; + + // 页码信息 - 调整深色模式 + $html .= '
+
+
+ 显示范围: + ' . $startIndex . '-' . $endIndex . ' + / 总计: + ' . $total . ' +
+
+ 当前页码: + 第 ' . $currentPage . ' 页 + / 总页数: + ' . $totalPages . ' 页 +
+
+
'; + + // 计算倒序序号 + $totalCount = $total; + $currentIndex = $totalCount - (($currentPage - 1) * $pageSize); + + foreach ($allMovies as $movie) { + $movieId = $movie['movieId']; + $title = isset($movie['title']) ? htmlspecialchars($movie['title']) : '未知电影'; + $originalTitle = isset($movie['original_title']) ? htmlspecialchars($movie['original_title']) : ''; + + // 海报URL + $posterPath = isset($movie['poster_path']) ? $movie['poster_path'] : ''; + if ($posterPath) { + $posterUrl = 'https://image.tmdb.org/t/p/w200' . $posterPath; + $posterSrc = $imageProxy . urlencode($posterUrl); + } else { + $posterSrc = $defaultPoster; + } + + // 自定义字段 + $startDate = isset($movie['custom_start_date']) ? htmlspecialchars($movie['custom_start_date']) : ''; + $watchDate = isset($movie['custom_watch_date']) ? htmlspecialchars($movie['custom_watch_date']) : ''; + $watchMethod = isset($movie['custom_watch_method']) ? htmlspecialchars($movie['custom_watch_method']) : ''; + $movieCategory = isset($movie['custom_movie_category']) ? htmlspecialchars($movie['custom_movie_category']) : ''; + $myRating = isset($movie['custom_my_rating']) ? htmlspecialchars($movie['custom_my_rating']) : ''; + + // 电影信息 + $releaseYear = isset($movie['release_year']) ? htmlspecialchars($movie['release_year']) : '未知'; + $director = isset($movie['director']) ? htmlspecialchars($movie['director']) : '未知'; + + // 类型 - 使用·分隔符 + $genres = '未知'; + if (isset($movie['genres']) && is_array($movie['genres'])) { + $genres = implode('·', $movie['genres']); + } + + // 时长 + $runtime = isset($movie['runtime']) ? htmlspecialchars($movie['runtime']) . '分钟' : '未知'; + + // 评分 + $rating = isset($movie['vote_average']) ? floatval($movie['vote_average']) : 0; + $ratingDisplay = $rating > 0 ? number_format($rating, 1) . '分' : '暂无评分'; + + // 短评 + $review = isset($movie['review']) ? htmlspecialchars($movie['review']) : ''; + + // 原始标题作为工具提示 + $titleTooltip = ''; + if ($originalTitle && $originalTitle != $title) { + $titleTooltip = ' title="原名:' . $originalTitle . '"'; + } + + // 获取序号颜色 + $indexColors = [ + '#01d277, #01b36b', // TMDB绿色 + '#0073aa, #0056b3', // 蓝色 + '#e67e22, #d35400', // 橙色 + '#9b59b6, #8e44ad', // 紫色 + '#e74c3c, #c0392b', // 红色 + ]; + $indexColor = $indexColors[($currentIndex - 1) % count($indexColors)]; + + $html .= '
+
+ + + + +
+ +
+ 《' . $title . '》'; + + if ($movieCategory) { + $html .= '/' . $movieCategory . ''; + } + + // 处理观看日期显示 + if ($startDate && $watchDate) { + if ($startDate === $watchDate) { + $html .= '/' . $startDate . ''; + } else { + $html .= '/' . $startDate . '-' . $watchDate . ''; + } + } elseif ($startDate) { + $html .= '/' . $startDate . '-至今'; + } elseif ($watchDate) { + $html .= '/未知-' . $watchDate . ''; + } + + if ($watchMethod) { + $html .= '/' . $watchMethod . ''; + } + + $html .= '
'; + + // 第二行:导演/类型/年份/时长/评分 - 修改:导演前面加"导演:" + $html .= '
'; + + $html .= '导演:' . $director . ''; + $html .= '/'; + + // 类型显示 - 使用·分隔符 + $html .= '' . $genres . ''; + $html .= '/'; + + $html .= '' . $releaseYear . '年'; + $html .= '/'; + $html .= '' . $runtime . ''; + $html .= '/'; + + if ($rating > 0) { + $html .= '评分:' . $ratingDisplay . ''; + } else { + $html .= '' . $ratingDisplay . ''; + } + + if ($myRating) { + $html .= '/我的评分:' . $myRating . ''; + } + + $html .= '
'; + + // 第三行:短评 + if ($review) { + $html .= '
+
📝 影评
+
' . nl2br($review) . '
+
'; + } + + $html .= '
+
+
'; + + $currentIndex--; + } + + // 分页导航 + if ($totalPages > 1) { + $html .= self::generatePagination($currentPage, $totalPages); + } + + $html .= '
'; + + return $html; + } + + /** + * 生成分页HTML + */ + private static function generatePagination($currentPage, $totalPages, $baseUrl = '') + { + if ($totalPages <= 1) { + return ''; + } + + $html = '
+
'; + + // 首页 + if ($currentPage > 1) { + $html .= '«'; + } else { + $html .= '«'; + } + + // 上一页 + if ($currentPage > 1) { + $html .= ''; + } else { + $html .= ''; + } + + // 页码显示 + $startPage = max(1, $currentPage - 2); + $endPage = min($totalPages, $currentPage + 2); + + for ($i = $startPage; $i <= $endPage; $i++) { + if ($i == $currentPage) { + $html .= '' . $i . ''; + } else { + $html .= '' . $i . ''; + } + } + + // 下一页 + if ($currentPage < $totalPages) { + $html .= ''; + } else { + $html .= ''; + } + + // 末页 + if ($currentPage < $totalPages) { + $html .= '»'; + } else { + $html .= '»'; + } + + $html .= '
'; + + return $html; + } + + /** + * 获取页面URL + */ + private static function getPageUrl($page, $baseUrl = '') + { + if (empty($baseUrl)) { + $currentUrl = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; + $currentUrl = preg_replace('/[&?]page=\d+/', '', $currentUrl); + $currentUrl = rtrim($currentUrl, '?&'); + + $separator = strpos($currentUrl, '?') === false ? '?' : '&'; + return $currentUrl . $separator . 'page=' . $page; + } + + return $baseUrl . (strpos($baseUrl, '?') === false ? '?' : '&') . 'page=' . $page; + } + + /** + * 获取序号颜色 + */ + private static function getIndexColor($index) + { + $colors = [ + '#01d277, #01b36b', // TMDB绿色 + '#0073aa, #0056b3', // 蓝色 + '#e67e22, #d35400', // 橙色 + '#9b59b6, #8e44ad', // 紫色 + '#e74c3c, #c0392b', // 红色 + ]; + + return $colors[($index - 1) % count($colors)]; + } + + /** + * 获取电影数据(包含影评和自定义信息) + */ + private static function getMovieData($movieId, $review = '', $customData = array()) + { + if (!is_numeric($movieId)) return null; + + $cacheFile = dirname(__FILE__) . '/cache/' . $movieId . '.json'; + $options = Typecho_Widget::widget('Widget_Options')->plugin('MovieInfo'); + $cacheEnable = isset($options->cacheEnable) ? $options->cacheEnable : '1'; + $cacheTime = isset($options->cacheTime) ? intval($options->cacheTime) : 7; + $apiKey = isset($options->tmdbApiKey) ? $options->tmdbApiKey : ''; + $language = isset($options->language) ? $options->language : 'zh-CN'; + + if (empty($apiKey)) { + return array( + 'title' => '请配置TMDB API Key', + 'original_title' => 'Please configure TMDB API Key', + 'error' => 'API_KEY_MISSING' + ); + } + + $data = null; + $needUpdate = false; + + // 检查缓存 + if ($cacheEnable == '1' && file_exists($cacheFile)) { + $fileTime = filemtime($cacheFile); + $expireTime = $cacheTime * 24 * 3600; + if (time() - $fileTime < $expireTime) { + $cacheContent = file_get_contents($cacheFile); + if ($cacheContent) { + $data = json_decode($cacheContent, true); + } + } + } + + // 如果缓存不存在或已过期,从TMDB API获取 + if (!$data || empty($data['title'])) { + $data = self::fetchFromTMDB($movieId, $apiKey, $language); + $needUpdate = true; + } + + // 更新影评 + if (!empty($review) && (!isset($data['review']) || $data['review'] !== $review)) { + $data['review'] = $review; + $data['review_updated'] = time(); + $needUpdate = true; + } + + // 更新自定义数据 + if (!empty($customData)) { + if (isset($customData['startDate']) && (!isset($data['custom_start_date']) || $data['custom_start_date'] !== $customData['startDate'])) { + $data['custom_start_date'] = $customData['startDate']; + $needUpdate = true; + } + if (isset($customData['watchDate']) && (!isset($data['custom_watch_date']) || $data['custom_watch_date'] !== $customData['watchDate'])) { + $data['custom_watch_date'] = $customData['watchDate']; + $needUpdate = true; + } + if (isset($customData['watchMethod']) && (!isset($data['custom_watch_method']) || $data['custom_watch_method'] !== $customData['watchMethod'])) { + $data['custom_watch_method'] = $customData['watchMethod']; + $needUpdate = true; + } + if (isset($customData['movieCategory']) && (!isset($data['custom_movie_category']) || $data['custom_movie_category'] !== $customData['movieCategory'])) { + $data['custom_movie_category'] = $customData['movieCategory']; + $needUpdate = true; + } + if (isset($customData['recommendation']) && (!isset($data['custom_recommendation']) || $data['custom_recommendation'] != $customData['recommendation'])) { + $data['custom_recommendation'] = intval($customData['recommendation']); + $needUpdate = true; + } + if (isset($customData['myRating']) && (!isset($data['custom_my_rating']) || $data['custom_my_rating'] !== $customData['myRating'])) { + $data['custom_my_rating'] = $customData['myRating']; + $needUpdate = true; + } + } + + // 确保自定义字段存在 + $customFields = array( + 'custom_start_date' => '', + 'custom_watch_date' => '', + 'custom_watch_method' => '', + 'custom_movie_category' => '', + 'custom_recommendation' => 0, + 'custom_my_rating' => '' + ); + + foreach ($customFields as $field => $default) { + if (!isset($data[$field])) { + $data[$field] = $default; + } + } + + // 如果需要更新缓存,保存到文件 + if ($needUpdate && $data && !empty($data['title'])) { + file_put_contents($cacheFile, json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); + } + + return $data; + } + + /** + * 从TMDB API获取数据 + */ + private static function fetchFromTMDB($movieId, $apiKey, $language) + { + // TMDB API URL + $url = "https://api.themoviedb.org/3/movie/{$movieId}?api_key={$apiKey}&language={$language}&append_to_response=credits"; + + $ch = curl_init(); + curl_setopt_array($ch, array( + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_TIMEOUT => 20, + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + CURLOPT_ENCODING => 'gzip, deflate', + CURLOPT_HTTPHEADER => array( + 'Accept: application/json', + 'Cache-Control: no-cache' + ) + )); + + $response = curl_exec($ch); + if (curl_errno($ch)) { + curl_close($ch); + return null; + } + + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($httpCode != 200 || empty($response)) { + return null; + } + + $movieData = json_decode($response, true); + if (!$movieData) { + return null; + } + + $data = array(); + + // 1. 基本信息 + $data['title'] = isset($movieData['title']) ? trim($movieData['title']) : '未知电影'; + $data['original_title'] = isset($movieData['original_title']) ? trim($movieData['original_title']) : ''; + + // 2. 海报 + $data['poster_path'] = isset($movieData['poster_path']) ? $movieData['poster_path'] : ''; + + // 3. 简介 + $data['overview'] = isset($movieData['overview']) ? trim($movieData['overview']) : '暂无简介'; + + // 4. 上映年份 + if (isset($movieData['release_date']) && !empty($movieData['release_date'])) { + $releaseDate = $movieData['release_date']; + $data['release_year'] = substr($releaseDate, 0, 4); + } else { + $data['release_year'] = '未知'; + } + + // 5. 导演 + $director = '未知'; + if (isset($movieData['credits']['crew'])) { + foreach ($movieData['credits']['crew'] as $crew) { + if (isset($crew['job']) && $crew['job'] === 'Director') { + $director = $crew['name']; + break; + } + } + } + $data['director'] = $director; + + // 6. 类型 + $genres = array(); + if (isset($movieData['genres'])) { + foreach ($movieData['genres'] as $genre) { + if (isset($genre['name'])) { + $genres[] = $genre['name']; + } + } + } + $data['genres'] = !empty($genres) ? $genres : array('未知'); + + // 7. 时长 + $data['runtime'] = isset($movieData['runtime']) ? $movieData['runtime'] : 0; + + // 8. 评分 + $data['vote_average'] = isset($movieData['vote_average']) ? floatval($movieData['vote_average']) : 0; + $data['vote_count'] = isset($movieData['vote_count']) ? intval($movieData['vote_count']) : 0; + + // 9. 生产国家 + $countries = array(); + if (isset($movieData['production_countries'])) { + foreach ($movieData['production_countries'] as $country) { + if (isset($country['name'])) { + $countries[] = $country['name']; + } + } + } + $data['production_countries'] = !empty($countries) ? $countries : array('未知'); + + // 10. 初始化影评和自定义字段 + $data['review'] = ''; + $data['review_updated'] = 0; + + // 初始化自定义字段 + $data['custom_start_date'] = ''; + $data['custom_watch_date'] = ''; + $data['custom_watch_method'] = ''; + $data['custom_movie_category'] = ''; + $data['custom_recommendation'] = 0; + $data['custom_my_rating'] = ''; + + // 11. 添加抓取时间 + $data['fetched_at'] = time(); + + return $data; + } + + /** + * 渲染编辑器按钮 - 增加关键词联想搜索 + */ +public static function renderButton() +{ + // 获取插件配置 + $options = Typecho_Widget::widget('Widget_Options')->plugin('MovieInfo'); + $apiKey = isset($options->tmdbApiKey) ? $options->tmdbApiKey : ''; + $language = isset($options->language) ? $options->language : 'zh-CN'; + + // 生成nonce或token用于验证请求 + $nonce = md5(uniqid()); + + echo << + #movieinfo-button { + padding: 5px!important; + background: #fff; + cursor: pointer; + color: white; + border: none; + border-radius: 4px; + font-size: 16px; + line-height: 1; + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 26px; + min-height: 26px; + } + #movieinfo-button:hover { background: #E9E9E6 } + .dark #movieinfo-button { background: rgb(16, 25, 40); } + .dark #movieinfo-button:hover { background: #375d85; } + + /* 搜索建议下拉框样式 */ + .movie-search-suggestions { + position: absolute; + background: white; + border: 1px solid #ddd; + border-radius: 4px; + box-shadow: 0 2px 10px rgba(0,0,0,0.1); + max-height: 300px; + overflow-y: auto; + z-index: 10001; + width: 300px; + margin-top: 2px; + } + + .movie-search-suggestion-item { + padding: 8px 12px; + cursor: pointer; + border-bottom: 1px solid #f0f0f0; + font-size: 14px; + color: #333; + display: flex; + align-items: center; + gap: 10px; + } + + .movie-search-suggestion-item:hover { + background: #f5f5f5; + } + + .movie-search-suggestion-item.selected { + background: #0073aa; + color: white; + } + + .movie-search-suggestion-poster { + width: 30px; + height: 45px; + object-fit: cover; + border-radius: 3px; + flex-shrink: 0; + } + + .movie-search-suggestion-info { + flex-grow: 1; + overflow: hidden; + } + + .movie-search-suggestion-title { + font-weight: 600; + margin-bottom: 2px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .movie-search-suggestion-year { + font-size: 12px; + color: #666; + } + + .movie-search-suggestion-item:hover .movie-search-suggestion-year { + color: #ccc; + } + + .movie-search-suggestion-item.selected .movie-search-suggestion-year { + color: #ccc; + } + + .movie-search-loading { + padding: 10px; + text-align: center; + color: #666; + font-size: 14px; + } + + .movie-search-no-results { + padding: 10px; + text-align: center; + color: #999; + font-size: 14px; + } + + .movie-search-input-container { + position: relative; + margin-bottom: 10px; + } + + .movie-search-results { + position: relative; + } + + .movie-id-section { + margin-top: 15px; + margin-bottom: 10px; + padding-top: 15px; + border-top: 1px solid #eee; + } + + .dark .movie-search-suggestions { + background: #2d2d2d; + border-color: #404040; + color: #e0e0e0; + } + + .dark .movie-search-suggestion-item { + color: #e0e0e0; + border-bottom-color: #404040; + } + + .dark .movie-search-suggestion-item:hover { + background: #3a3a3a; + } + + .dark .movie-search-suggestion-item.selected { + background: #0073aa; + } + + .dark .movie-search-suggestion-year { + color: #aaa; + } + + .dark .movie-search-loading, + .dark .movie-search-no-results { + color: #aaa; + } + + + +HTML; +} +} \ No newline at end of file diff --git a/cache/1084242.json b/cache/1084242.json new file mode 100644 index 0000000..d9eb4e1 --- /dev/null +++ b/cache/1084242.json @@ -0,0 +1,30 @@ +{ + "title": "疯狂动物城2", + "original_title": "Zootopia 2", + "poster_path": "\/YQildBNfvOR8IQiwFY66IzrT9z.jpg", + "overview": "在《疯狂动物城2》中,警官兔朱迪(金妮弗·古德温 配音)与狐尼克(杰森·贝特曼 配音)这对备受全球观众喜爱的搭档将再度携手,带领观众重返充满活力的动物城,开启全新冒险。故事紧接前作,这对默契十足的搭档将直面职业与关系上的新挑战,揭开动物城深藏的秘密。", + "release_year": "2025", + "director": "贾里德·布什", + "genres": [ + "动画", + "喜剧", + "冒险", + "家庭", + "悬疑" + ], + "runtime": 108, + "vote_average": 7.6, + "vote_count": 1178, + "production_countries": [ + "United States of America" + ], + "review": "不错,值得多刷几次", + "review_updated": 1769400052, + "custom_start_date": "2025.12.18", + "custom_watch_date": "2025.12.18", + "custom_watch_method": "电影院", + "custom_movie_category": "动画", + "custom_recommendation": 5, + "custom_my_rating": "9.5", + "fetched_at": 1769400052 +} \ No newline at end of file diff --git a/cache/1622.json b/cache/1622.json new file mode 100644 index 0000000..9eb758e --- /dev/null +++ b/cache/1622.json @@ -0,0 +1,28 @@ +{ + "title": "旅鼠", + "original_title": "Lemming", + "poster_path": "\/oeNPyQRhpnaa4dMyt2lNMQNPv75.jpg", + "overview": "年轻的电脑工程师艾林•盖提(Laurent Lucas 饰)因工作原因和妻子本妮蒂特(Charlotte Gainsbourg 夏洛特•甘斯布 饰)搬到了法国图卢兹的郊区。定居不久,艾林的设计取得成功,并正式投产。为庆祝这一时刻,他邀请公司老板理查德(André Dussollier 饰)及其夫人爱丽丝(Charlotte Rampling 夏洛特•莱普宁 饰)来家中共进晚餐。   但是爱丽丝粗鲁乖张的举动破坏了当天的晚宴,次日她又以探望丈夫的名义来到艾林的实验室。在这里,她向艾林讲述了与里查德之间危险的夫妻关系,继而引诱眼前这名年轻的工程师。两对夫妻由此开始了他们噩梦一般的经历……", + "release_year": "2005", + "director": "Dominik Moll", + "genres": [ + "剧情", + "惊悚", + "悬疑" + ], + "runtime": 124, + "vote_average": 6.5, + "vote_count": 132, + "production_countries": [ + "France" + ], + "review": "不错", + "review_updated": 1765891146, + "custom_start_date": "", + "custom_watch_date": "", + "custom_watch_method": "", + "custom_movie_category": "", + "custom_recommendation": 0, + "custom_my_rating": "", + "fetched_at": 1765891146 +} \ No newline at end of file diff --git a/cache/23527.json b/cache/23527.json new file mode 100644 index 0000000..1b9deed --- /dev/null +++ b/cache/23527.json @@ -0,0 +1,33 @@ +{ + "title": "第一小队", + "original_title": "Первый отряд", + "poster_path": "\/mh2DUD5iHNs9VR8kxxJ8yVgZD0N.jpg", + "overview": "由日本、加拿大、俄罗斯三国携手合作。故事发生在第二次世界大战爆发几天后的东部战线,纳粹德军的党卫队司令官Martin Linz意图唤醒出十二世纪东征十字军的超能力部队,并组成幽灵军团来攻占苏联。片中的五位年轻主角Nadya、Leo、Zena、Marat、Valya是在苏联军队中接受了手术改造的异能士兵,而他们的任务即是尽全力消灭这批幽灵兵团,以击败纳粹司令官的野心。", + "release_year": "2009", + "director": "Alexey Klimov", + "genres": [ + "奇幻", + "动画", + "动作", + "科幻" + ], + "runtime": 73, + "vote_average": 6.233, + "vote_count": 135, + "production_countries": [ + "Canada", + "Hong Kong", + "Japan", + "Russia", + "Germany" + ], + "review": "不错", + "review_updated": 1765891210, + "custom_start_date": "", + "custom_watch_date": "", + "custom_watch_method": "", + "custom_movie_category": "", + "custom_recommendation": 0, + "custom_my_rating": "", + "fetched_at": 1765891210 +} \ No newline at end of file diff --git a/cache/83533.json b/cache/83533.json new file mode 100644 index 0000000..6f36749 --- /dev/null +++ b/cache/83533.json @@ -0,0 +1,28 @@ +{ + "title": "阿凡达3", + "original_title": "Avatar: Fire and Ash", + "poster_path": "\/hYGXf2kkykFhBny0vHHmbx5G27o.jpg", + "overview": "故事发生在2154年,故事从地球开始,杰克·萨利是一个双腿瘫痪的前海军陆战队员,他觉得没有任何东西值得他去战斗,因此他对被派遣去潘多拉星球的采矿公司工作欣然接受。这个星球上有一种别的地方都没有的矿物元素“Unobtanium”,能够吸引人类不远万里来到这里拓荒的原因就是“Unobtanium”将彻底改变人类的能源产业。但是问题是,资源丰富的潘多拉星球并不适合人类生活,这里的空气对人类致命,本土的动植物都是凶猛的掠食者,极度危险。这里的环境也造就了与人类不同的种族:10英尺高(约3米)的蓝色类人生物“Na'vi族”。Na'vi族不满人类拓荒者的到来,也不喜欢人类的机器在这个星球的土地上因为到处挖矿而留下的斑斑伤痕。", + "release_year": "2025", + "director": "詹姆斯·卡梅隆", + "genres": [ + "科幻", + "冒险", + "奇幻" + ], + "runtime": 197, + "vote_average": 7, + "vote_count": 21, + "production_countries": [ + "United States of America" + ], + "review": "哈哈", + "review_updated": 1765970513, + "custom_start_date": "233213", + "custom_watch_date": "321321", + "custom_watch_method": "13213", + "custom_movie_category": "31321", + "custom_recommendation": 3, + "custom_my_rating": "8", + "fetched_at": 1765970513 +} \ No newline at end of file diff --git a/cache/8393.json b/cache/8393.json new file mode 100644 index 0000000..2d784ae --- /dev/null +++ b/cache/8393.json @@ -0,0 +1,28 @@ +{ + "title": "上帝也疯狂", + "original_title": "The Gods Must Be Crazy", + "poster_path": "\/mEECufjJu7pr6xh4oJuA7pM0b1v.jpg", + "overview": "  广袤无垠的非洲大陆,现代文明与原始社会和谐共存。在离现代大都市六千公里的卡拉哈里沙漠腹地,生活着仍未受到外来文明影响的布须曼人。他们刀耕火种,狩猎农作,过着与世无争、敬畏自然的平静生活。某天,一支来自现代文明的可乐瓶打乱了他们一成不变的日子。最先发现瓶子的基(N!xau 饰)将其带回部落,族人惊叹可乐瓶子的完美构造和繁多的用途,认为这是上帝赐予他们的礼物。可是兴奋的心情很快为别样的情绪所取代,习惯了平等共有的族人开始想要将瓶子据为己有,矛盾悄然而生。基不愿看到族人发生争吵与殴斗,于是决定将可乐瓶还给上帝,只为恢复曾经平静快乐的生活……", + "release_year": "1980", + "director": "加美·尤伊斯", + "genres": [ + "动作", + "喜剧" + ], + "runtime": 109, + "vote_average": 7.3, + "vote_count": 1250, + "production_countries": [ + "South Africa", + "Botswana" + ], + "review": "测试影评", + "review_updated": 1765711721, + "custom_watch_date": "2025.12.26", + "custom_watch_method": "手机", + "custom_movie_category": "科幻", + "custom_recommendation": 3, + "custom_my_rating": "8.7", + "fetched_at": 1765711721, + "custom_start_date": "2025.12.26" +} \ No newline at end of file