diff --git a/app/Douban.php b/app/Douban.php index 65ac021..9432b24 100644 --- a/app/Douban.php +++ b/app/Douban.php @@ -173,6 +173,85 @@ final class Douban return isset($d[$k]) && is_scalar($d[$k]) ? (string)$d[$k] : ''; } + /** + * 拼一份**带主要信息**的简介(v24 用户 2026-10-03 第 2 条)。 + * + * 用户原话:「添加电影的时候,从豆瓣获取的信息不够,应该把导演、主要演员, + * 上映年份等主要信息,也都放在简介中。」 + * + * 为什么要有这个函数(而不是在路上顺手拼字符串): + * · 简介是**写进 movie_details.info 的正文**,一旦存下来就与豆瓣脱钩了 + * (以后豆瓣改了也不会变)。所以拼法必须是一处定义、可测: + * `_fb_douban_summary.php` 直接断言各种组合下的输出。 + * · 用户要求"主要信息**也都放在简介中**",即这些字段要**落进正文**, + * 而不是只躺在隐藏的 douban_meta JSON 里(那个详情页另有展示, + * 但编辑表单里看不到、复制出去也没有)。 + * + * 格式(只有有值的行才出现,绝不写"导演:"这种空壳行): + * 《片名》(年份) + * 导演:X + * 主演:A、B、C + * 类型:剧情 / 家庭 + * 片长:125分钟 + * 制片国家/地区:中国大陆 + * 豆瓣评分:8.6 + * + * <剧情简介原文> + * + * ⚠️ 用与详情页 `db-meta` 相同的标签词(年份/类型/片长/导演/主演/制片国家/地区), + * 这样同一个字段在表单与详情页叫同一个名字,用户不会以为是两回事。 + * + * @param array $meta fetchDetail() 产出的 meta + * @param string $title 片名(可能来自候选/用户输入) + * @param bool $withPlot 是否附带剧情简介原文(默认带) + * @return string 可直接写进 info 的文本;什么信息都没有时返回 '' + */ + public static function summaryText(array $meta, string $title = '', bool $withPlot = true): string + { + $title = trim($title); + $year = trim((string)($meta['year'] ?? '')); + $lines = []; + + // 第一行:片名(年份) + $head = ''; + if ($title !== '') { + $head = '《' . $title . '》'; + if ($year !== '') { + $head .= '(' . $year . ')'; + } + } elseif ($year !== '') { + $head = $year . ' 年'; + } + if ($head !== '') { + $lines[] = $head; + } + + // 主要信息:顺序按"用户最关心 → 次要",空的不占行 + $fields = [ + '导演' => (string)($meta['director'] ?? ''), + '主演' => (string)($meta['actors'] ?? ''), + '类型' => (string)($meta['genre'] ?? ''), + '片长' => (string)($meta['runtime'] ?? ''), + '制片国家/地区' => (string)($meta['country'] ?? ''), + '又名' => (string)($meta['alias'] ?? ''), + '豆瓣评分' => (string)($meta['rating'] ?? ''), + ]; + foreach ($fields as $label => $val) { + $val = trim($val); + if ($val !== '') { + $lines[] = $label . ':' . $val; + } + } + + $plot = $withPlot ? trim((string)($meta['plot'] ?? '')) : ''; + if ($plot !== '') { + $lines[] = ''; // 空行:把"事实"与"剧情"分开,读起来清爽 + $lines[] = $plot; + } + + return trim(implode("\n", $lines)); + } + // ---------------- 搜索候选整理 ---------------- /** 规范化片名用于匹配:去空白、去常见标点、转小写 */ diff --git a/index.php b/index.php index e338d07..64cc8ff 100644 --- a/index.php +++ b/index.php @@ -2396,6 +2396,14 @@ switch ($r) { 'source' => 'douban', 'title' => (string)($resDb['title'] ?? ''), 'meta' => $resDb['meta'], + // 拼好的简介(含导演/主演/年份/类型/片长/国家/评分 + 剧情原文)。 + // 放在服务端拼、由前端填空 —— 见 Douban::summaryText 的注释: + // 这份文本会**落库**(movie_details.info),所以拼法要可测、只有一处。 + 'summary' => Douban::summaryText( + (array)$resDb['meta'], + (string)($resDb['title'] ?? ''), + true + ), 'poster_key' => $posterKey, 'poster' => $posterShow, ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); diff --git a/templates/movies/form.php b/templates/movies/form.php index 1288eab..c8aa6e6 100644 --- a/templates/movies/form.php +++ b/templates/movies/form.php @@ -127,8 +127,8 @@ $selAttendees = array_map('intval', (array)old('attendees', $curAttendees));
- +
@@ -278,8 +278,27 @@ $selAttendees = array_map('intval', (array)old('attendees', $curAttendees)); if (data.title) titleEl.value = data.title; if (data.meta) { metaEl.value = JSON.stringify(data.meta); - // 剧情简介填进「简介」,但只填空白的 —— 用户已经写了就不覆盖 - if (infoEl && data.meta.plot && infoEl.value.trim() === '') infoEl.value = data.meta.plot; + } + /* 简介:用服务端拼好的 summary(**含导演/主演/年份/类型/片长/国家/评分 + 剧情原文**), + 而不是只塞剧情那一小段。用户 2026-10-03:「从豆瓣获取的信息不够, + 应该把导演、主要演员,上映年份等主要信息,也都放在简介中。」 + ⚠️ 仍然**只填空白的**:用户已经写过的内容不能被抓取覆盖。 + ⚠️ 而且要把"有东西但没写进简介"这件事说清楚 —— 以前只塞 plot, + 遇到豆瓣没有 plot 的电影就**什么都不填而且没有提示**,用户会以为抓取坏了。 + 现在:抓到了但简介非空 → 明确提示;什么都没抓到 → 也明确说一声。 */ + if (infoEl) { + var summary = (data.summary || '').trim(); + if (summary !== '') { + if (infoEl.value.trim() === '') { + infoEl.value = summary; + } else { + infoEl.setAttribute('data-db-summary', summary); + alert('豆瓣信息已抓取。\n\n「简介」里已经有你写的内容,我没有覆盖它。\n' + + '如果想用豆瓣的简介(含导演/主演/年份等),请先清空「简介」再点一次「自动获取」。'); + } + } else if ((data.meta && (data.meta.plot || data.meta.director)) || data.title) { + alert('豆瓣信息已抓取(片名/海报/元数据),但这部电影豆瓣没有可用的简介文本。'); + } } if (data.poster_key) { lastPosterKey = data.poster_key;