Files
laoyang 40e1bc5e56 feat: 完善电影记录系统源码与项目文档
功能模块:
- 观影记录:列表(瀑布流)/ 添加 / 编辑 / 详情 / 删除,删除时同步清理图片文件
- 首页快捷搜索 + 高级搜索(片名、影院、观影人、日期区间组合筛选)
- 影院管理:三段式信息 + 50 种预设配色,删除已引用影院时二次确认
- 观影人管理:头像裁剪上传 + 专属配色,已引用者禁止删除
- 图片处理:Cropper.js 裁剪票根/海报/观影照片/头像,多图上传,首字母 SVG 头像兜底
- OMDb 自动获取影片信息(fetch_movie.php 代理,返回 JSON)
- CSV 批量导入:UTF-8/GBK 自动识别,影院去重,事务保护,逐行错误报告
- 统计仪表板:总览 + 按影院/观影人/年份/近 12 个月排行
- 年度报告:按账号关联的观影人视角生成,含 Chart.js 月度与星期分布图
- 多用户:账号增删改、账号与观影人绑定、修改自己的用户名与密码
- 登录鉴权:Session + password_hash,全站页面登录校验

文档:
- 重写 README:功能特性、技术栈、目录结构、数据库结构、部署与使用指南、接口说明、CSV 格式、安全注意事项、已知限制
- 新增 .gitignore,排除 db/ 与 uploads/ 等运行时数据
2026-09-21 08:20:56 +08:00

739 lines
31 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// ============================================
// 文件: add.php (支持 OMDb 自动获取 + 票根裁剪)
// ============================================
require_once 'config.php';
checkLogin();
$admin = getCurrentAdmin();
$cinemas = getCinemas();
// 获取所有观影人
$db = getDB();
$stmt = $db->query("SELECT * FROM persons ORDER BY name");
$all_persons = $stmt->fetchAll();
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$title = trim($_POST['title'] ?? '');
$info = trim($_POST['info'] ?? '');
$watch_date = $_POST['watch_date'] ?? '';
$cinema_id = $_POST['cinema_id'] ?? '';
$viewer_selects = $_POST['viewer_select'] ?? [];
$viewer_news = $_POST['viewers_new'] ?? [];
// 票根裁剪数据
$ticket_crop = $_POST['ticket_crop'] ?? '';
// 新建电影院
$new_cinema_place = trim($_POST['new_cinema_place'] ?? '');
$new_cinema_name = trim($_POST['new_cinema_name'] ?? '');
$new_cinema_address = trim($_POST['new_cinema_address'] ?? '');
if ($cinema_id === 'new' && !empty($new_cinema_name)) {
$stmt = $db->prepare("INSERT INTO cinemas (place, name, address) VALUES (?, ?, ?)");
$stmt->execute([$new_cinema_place, $new_cinema_name, $new_cinema_address]);
$cinema_id = $db->lastInsertId();
} elseif ($cinema_id === 'new') {
$cinema_id = null;
} elseif (!empty($cinema_id) && is_numeric($cinema_id)) {
$cinema_id = (int)$cinema_id;
} else {
$cinema_id = null;
}
if (empty($title)) {
$error = '请输入电影名称';
} elseif (empty($watch_date)) {
$error = '请选择观影日期';
} else {
// ----- 处理海报(直接上传) -----
$poster_path = '';
if (isset($_FILES['poster']) && $_FILES['poster']['error'] === UPLOAD_ERR_OK) {
$ext = strtolower(pathinfo($_FILES['poster']['name'], PATHINFO_EXTENSION));
if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
$filename = uniqueFilename($_FILES['poster']['name']);
$target = POSTER_DIR . $filename;
if (move_uploaded_file($_FILES['poster']['tmp_name'], $target)) {
$poster_path = 'uploads/posters/' . $filename;
}
}
}
// ----- 处理票根(裁剪优先) -----
$ticket_path = '';
if (!empty($ticket_crop)) {
$new_path = saveBase64Image($ticket_crop, TICKET_DIR, 'ticket');
if ($new_path) {
$ticket_path = $new_path;
} else {
$error = '票根裁剪保存失败,请重试';
}
} elseif (isset($_FILES['ticket']) && $_FILES['ticket']['error'] === UPLOAD_ERR_OK) {
$ext = strtolower(pathinfo($_FILES['ticket']['name'], PATHINFO_EXTENSION));
if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
$filename = uniqueFilename($_FILES['ticket']['name']);
$target = TICKET_DIR . $filename;
if (move_uploaded_file($_FILES['ticket']['tmp_name'], $target)) {
$ticket_path = 'uploads/tickets/' . $filename;
}
}
}
// 如果没有错误,继续
if (empty($error)) {
// 插入电影
$stmt = $db->prepare("
INSERT INTO movies (title, info, poster_path, ticket_path, cinema_id, watch_date)
VALUES (?, ?, ?, ?, ?, ?)
");
$stmt->execute([$title, $info, $poster_path, $ticket_path, $cinema_id, $watch_date]);
$movie_id = $db->lastInsertId();
// ---- 处理合影照片(多张) ----
if (isset($_FILES['photos']) && is_array($_FILES['photos']['tmp_name'])) {
$photo_files = $_FILES['photos'];
for ($i = 0; $i < count($photo_files['tmp_name']); $i++) {
if ($photo_files['error'][$i] === UPLOAD_ERR_OK) {
$ext = strtolower(pathinfo($photo_files['name'][$i], PATHINFO_EXTENSION));
if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
$filename = uniqueFilename($photo_files['name'][$i]);
$target = PHOTO_DIR . $filename;
if (move_uploaded_file($photo_files['tmp_name'][$i], $target)) {
$photo_path = 'uploads/photos/' . $filename;
$stmt2 = $db->prepare("INSERT INTO movie_photos (movie_id, photo_path) VALUES (?, ?)");
$stmt2->execute([$movie_id, $photo_path]);
}
}
}
}
}
// ---- 处理观影人 ----
$person_ids = [];
foreach ($viewer_selects as $idx => $val) {
if ($val === 'new') {
$new_name = trim($viewer_news[$idx] ?? '');
if (!empty($new_name)) {
$chk = $db->prepare("SELECT id FROM persons WHERE name = ?");
$chk->execute([$new_name]);
$existing = $chk->fetch();
if ($existing) {
$person_ids[] = $existing['id'];
} else {
$ins = $db->prepare("INSERT INTO persons (name) VALUES (?)");
$ins->execute([$new_name]);
$person_ids[] = $db->lastInsertId();
}
}
} elseif (is_numeric($val) && $val > 0) {
$person_ids[] = (int)$val;
}
}
$person_ids = array_unique($person_ids);
if (!empty($person_ids)) {
$stmt = $db->prepare("INSERT INTO viewers (movie_id, person_id, name) VALUES (?, ?, ?)");
foreach ($person_ids as $pid) {
$stmt->execute([$movie_id, $pid, '']);
}
}
header('Location: detail.php?id=' . $movie_id);
exit;
}
}
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>添加电影 - 电影日志</title>
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.css">
<style>
.form-container {
max-width: 720px;
margin: 0 auto;
padding: 20px;
}
.form-card {
background: var(--card-bg);
border-radius: 16px;
padding: 32px 36px;
box-shadow: var(--shadow);
}
.form-card h2 {
font-size: 24px;
font-weight: 700;
margin: 0 0 8px;
color: var(--text-primary);
}
.form-card .sub {
color: var(--text-secondary);
font-size: 14px;
margin-bottom: 24px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
font-weight: 600;
font-size: 14px;
color: var(--text-primary);
margin-bottom: 6px;
}
.form-group label .hint {
font-weight: 400;
color: var(--text-secondary);
font-size: 13px;
}
.form-group input, .form-group textarea, .form-group select {
width: 100%;
padding: 12px 16px;
border: 1px solid var(--border-color);
border-radius: 10px;
font-size: 15px;
font-family: inherit;
background: var(--input-bg);
color: var(--text-primary);
transition: border-color 0.2s, box-shadow 0.2s;
box-sizing: border-box;
}
.form-group input:focus, .form-group textarea:focus, .form-group select:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 4px rgba(230,126,34,0.12);
}
.form-group textarea {
min-height: 100px;
resize: vertical;
}
.form-group input[type="file"] {
padding: 10px 12px;
background: var(--bg-secondary);
border: 1px dashed var(--border-color);
}
.form-group input[type="file"]:hover {
border-color: var(--primary);
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
.form-hint {
font-size: 13px;
color: var(--text-secondary);
margin-top: 4px;
}
.viewer-input-group {
display: flex;
gap: 10px;
align-items: center;
margin-bottom: 8px;
}
.viewer-input-group select, .viewer-input-group input {
flex: 1;
}
.viewer-input-group select {
width: 60%;
}
.viewer-input-group input[type="text"] {
width: 40%;
}
.btn-remove-viewer {
background: none;
border: none;
color: #e74c3c;
font-size: 20px;
cursor: pointer;
padding: 0 8px;
line-height: 1;
transition: transform 0.2s;
}
.btn-remove-viewer:hover {
transform: scale(1.2);
}
.btn-add-viewer {
background: var(--bg-secondary);
border: 1px dashed var(--border-color);
border-radius: 8px;
padding: 8px 16px;
color: var(--text-secondary);
cursor: pointer;
font-size: 14px;
transition: all 0.2s;
width: 100%;
}
.btn-add-viewer:hover {
border-color: var(--primary);
color: var(--primary);
background: rgba(230,126,34,0.05);
}
.form-actions {
display: flex;
gap: 12px;
margin-top: 28px;
padding-top: 20px;
border-top: 1px solid var(--border-color);
}
.form-actions .btn {
padding: 12px 32px;
font-size: 16px;
}
.btn-secondary {
background: var(--bg-secondary);
color: var(--text-primary);
border: 1px solid var(--border-color);
}
.btn-secondary:hover {
background: var(--border-color);
}
.error-box {
background: rgba(231,76,60,0.08);
border: 1px solid rgba(231,76,60,0.2);
color: #e74c3c;
padding: 12px 16px;
border-radius: 10px;
margin-bottom: 20px;
font-size: 14px;
}
.cinema-new-group {
margin-top: 12px;
padding: 16px 18px;
background: var(--bg-secondary);
border-radius: 10px;
border: 1px solid var(--border-color);
}
.cinema-new-group .form-group:last-child {
margin-bottom: 0;
}
/* 裁剪预览 */
.image-preview {
max-width: 120px;
max-height: 120px;
border-radius: 4px;
border: 1px solid var(--border-color);
margin-top: 4px;
}
.crop-btn {
display: inline-block;
padding: 4px 12px;
background: #3498db;
color: #fff;
border: none;
border-radius: 4px;
font-size: 12px;
cursor: pointer;
margin-top: 4px;
}
.crop-btn:hover { background: #2980b9; }
.modal-overlay {
display: none;
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.6);
z-index: 999;
justify-content: center;
align-items: center;
}
.modal-overlay.active { display: flex; }
.modal-content {
background: var(--card-bg);
max-width: 600px;
width: 90%;
padding: 24px;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0,0,0,0.5);
max-height: 90vh;
overflow-y: auto;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.modal-header h3 { margin: 0; }
.modal-header .close-btn {
background: none;
border: none;
font-size: 28px;
cursor: pointer;
color: var(--text-secondary);
}
.modal-body img { max-width: 100%; display: block; }
.modal-footer {
margin-top: 16px;
display: flex;
gap: 12px;
justify-content: flex-end;
}
@media (max-width: 600px) {
.form-card { padding: 20px 16px; }
.form-row { grid-template-columns: 1fr; }
.form-actions { flex-direction: column; }
.form-actions .btn { width: 100%; text-align: center; }
}
</style>
</head>
<body>
<?php include 'nav.php'; ?>
<main class="main-content">
<div class="form-container">
<div class="form-card">
<h2>🎬 添加新电影</h2>
<p class="sub">记录一部你曾看过的电影</p>
<?php if ($error): ?>
<div class="error-box"><?= h($error) ?></div>
<?php endif; ?>
<form method="POST" action="" enctype="multipart/form-data" id="addForm">
<!-- 电影名称 + 自动获取按钮 -->
<div class="form-group">
<label>电影名称 <span class="hint">*必填</span></label>
<div style="display: flex; gap: 10px;">
<input type="text" name="title" id="movieTitle" value="<?= h($_POST['title'] ?? '') ?>" placeholder="请输入电影名称" required style="flex:1;">
<button type="button" class="btn btn-primary" id="fetchBtn" style="white-space:nowrap;">📡 自动获取</button>
</div>
<div id="fetchStatus" style="font-size:13px;color:var(--text-secondary);margin-top:4px;"></div>
</div>
<!-- 电影信息 -->
<div class="form-group">
<label>电影信息</label>
<textarea name="info" id="movieInfo" placeholder="剧情简介、观影感受..."><?= h($_POST['info'] ?? '') ?></textarea>
</div>
<!-- 观影日期 -->
<div class="form-group">
<label>观影日期 <span class="hint">*必填</span></label>
<input type="date" name="watch_date" value="<?= h($_POST['watch_date'] ?? date('Y-m-d')) ?>" required>
</div>
<!-- 电影院 -->
<div class="form-group">
<label>电影院</label>
<select name="cinema_id" id="cinemaSelect" onchange="toggleNewCinema()">
<option value="">-- 不选择 --</option>
<?php foreach ($cinemas as $c): ?>
<option value="<?= $c['id'] ?>" <?= (isset($_POST['cinema_id']) && $_POST['cinema_id'] == $c['id']) ? 'selected' : '' ?>>
<?= h($c['place']) ?> · <?= h($c['name']) ?>
</option>
<?php endforeach; ?>
<option value="new" <?= (isset($_POST['cinema_id']) && $_POST['cinema_id'] === 'new') ? 'selected' : '' ?>> 新建电影院</option>
</select>
</div>
<div class="cinema-new-group" id="newCinemaGroup" style="display: <?= (isset($_POST['cinema_id']) && $_POST['cinema_id'] === 'new') ? 'block' : 'none' ?>;">
<div class="form-group">
<label>所在地方 <span class="hint">如: 万达广场</span></label>
<input type="text" name="new_cinema_place" value="<?= h($_POST['new_cinema_place'] ?? '') ?>" placeholder="如: 万达广场">
</div>
<div class="form-group">
<label>电影院名称 <span class="hint">*必填</span></label>
<input type="text" name="new_cinema_name" value="<?= h($_POST['new_cinema_name'] ?? '') ?>" placeholder="如: 万达影城(IMAX店)">
</div>
<div class="form-group">
<label>详细地址</label>
<input type="text" name="new_cinema_address" value="<?= h($_POST['new_cinema_address'] ?? '') ?>" placeholder="详细地址">
</div>
</div>
<!-- 观影人 -->
<div class="form-group">
<label>一起看的人</label>
<div id="viewerContainer">
<?php
$viewer_selects = $_POST['viewer_select'] ?? [];
$viewer_news = $_POST['viewers_new'] ?? [];
if (empty($viewer_selects)) {
$viewer_selects = [''];
}
foreach ($viewer_selects as $idx => $val):
$new_name = $viewer_news[$idx] ?? '';
?>
<div class="viewer-input-group">
<select name="viewer_select[]" onchange="toggleNewViewer(this)" class="viewer-select" style="flex:1;padding:8px;border:1px solid #ddd;border-radius:6px;">
<option value="">-- 选择 --</option>
<?php foreach ($all_persons as $p): ?>
<option value="<?= $p['id'] ?>" <?= ($val == $p['id']) ? 'selected' : '' ?>><?= h($p['name']) ?></option>
<?php endforeach; ?>
<option value="new" <?= ($val === 'new') ? 'selected' : '' ?>> 新增</option>
</select>
<input type="text" name="viewers_new[]" placeholder="输入新姓名" style="flex:1;display:<?= ($val === 'new') ? 'block' : 'none' ?>;padding:8px;border:1px solid #ddd;border-radius:6px;" value="<?= h($new_name) ?>">
<?php if ($idx > 0): ?>
<button type="button" class="btn-remove-viewer" onclick="removeViewer(this)">×</button>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<button type="button" class="btn-add-viewer" onclick="addViewerRow()"> 添加一位</button>
<div class="form-hint">选择已有观影人,或选择“新增”后输入姓名</div>
</div>
<!-- 海报(直接上传 + 预览) -->
<div class="form-row">
<div class="form-group">
<label>电影海报</label>
<input type="file" name="poster" accept="image/*" id="posterInput">
<div id="posterPreviewWrap" style="display:none;margin-top:6px;">
<img id="posterPreview" style="max-width:150px;max-height:200px;border-radius:4px;border:1px solid var(--border-color);">
<br>
<span style="font-size:12px;color:var(--text-secondary);">预览(仅供参考,仍需上传图片文件)</span>
</div>
<div class="form-hint">推荐比例 2:3</div>
</div>
<!-- 票根(带裁剪) -->
<div class="form-group">
<label>电影票扫描件</label>
<input type="file" name="ticket" id="ticketInput" accept="image/*" onchange="handleTicketSelect(this)">
<img id="ticketPreview" class="image-preview" style="display:none;">
<input type="hidden" name="ticket_crop" id="ticket_crop">
</div>
</div>
<!-- 观影照片(多张) -->
<div class="form-group">
<label>观影照片 <span class="hint">可多选</span></label>
<input type="file" name="photos[]" accept="image/*" multiple>
<div class="form-hint">按住 Ctrl(或 ⌘)可一次选择多张</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">✅ 保存电影</button>
<a href="index.php" class="btn btn-secondary">取消</a>
</div>
</form>
</div>
</div>
</main>
<!-- 裁剪模态框 -->
<div class="modal-overlay" id="cropModal">
<div class="modal-content">
<div class="modal-header">
<h3>✂️ 裁剪票根</h3>
<button class="close-btn" onclick="closeCrop()">&times;</button>
</div>
<div class="modal-body">
<img id="cropImage" src="">
</div>
<div class="modal-footer">
<button class="btn btn-outline" onclick="closeCrop()">取消</button>
<button class="btn btn-primary" onclick="cropSave()">✅ 确认裁剪</button>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.js"></script>
<script>
// ---------- 观影人 ----------
function toggleNewViewer(select) {
var parent = select.parentElement;
var input = parent.querySelector('input[name="viewers_new[]"]');
if (select.value === 'new') {
input.style.display = 'block';
input.required = true;
} else {
input.style.display = 'none';
input.required = false;
input.value = '';
}
}
function addViewerRow() {
var container = document.getElementById('viewerContainer');
var div = document.createElement('div');
div.className = 'viewer-input-group';
var selectHtml = '<select name="viewer_select[]" onchange="toggleNewViewer(this)" class="viewer-select" style="flex:1;padding:8px;border:1px solid #ddd;border-radius:6px;">';
selectHtml += '<option value="">-- 选择 --</option>';
<?php foreach ($all_persons as $p): ?>
selectHtml += '<option value="<?= $p['id'] ?>"><?= h($p['name']) ?></option>';
<?php endforeach; ?>
selectHtml += '<option value="new"> 新增</option>';
selectHtml += '</select>';
var inputHtml = '<input type="text" name="viewers_new[]" placeholder="输入新姓名" style="flex:1;display:none;padding:8px;border:1px solid #ddd;border-radius:6px;">';
var removeBtn = '<button type="button" class="btn-remove-viewer" onclick="removeViewer(this)">×</button>';
div.innerHTML = selectHtml + inputHtml + removeBtn;
container.appendChild(div);
}
function removeViewer(btn) {
var container = document.getElementById('viewerContainer');
if (container.children.length > 1) {
btn.parentElement.remove();
}
}
// ---------- 电影院 ----------
function toggleNewCinema() {
var select = document.getElementById('cinemaSelect');
var group = document.getElementById('newCinemaGroup');
group.style.display = select.value === 'new' ? 'block' : 'none';
}
document.addEventListener('DOMContentLoaded', function() {
toggleNewCinema();
document.querySelectorAll('.viewer-input-group').forEach(function(group) {
var select = group.querySelector('select');
if (select) toggleNewViewer(select);
});
});
// ---------- 票根裁剪 ----------
let cropper = null;
let currentFileInput = null;
function handleTicketSelect(input) {
const file = input.files[0];
if (!file) return;
if (!file.type.startsWith('image/')) {
alert('请选择图片文件');
input.value = '';
return;
}
currentFileInput = input;
const reader = new FileReader();
reader.onload = function(e) {
const img = document.getElementById('cropImage');
img.src = e.target.result;
document.getElementById('cropModal').classList.add('active');
if (cropper) cropper.destroy();
setTimeout(function() {
cropper = new Cropper(img, {
aspectRatio: NaN,
viewMode: 1,
dragMode: 'move',
autoCropArea: 0.8,
responsive: true,
restore: false,
});
}, 150);
};
reader.readAsDataURL(file);
}
function closeCrop() {
document.getElementById('cropModal').classList.remove('active');
if (cropper) {
cropper.destroy();
cropper = null;
}
}
function cropSave() {
if (!cropper) {
alert('请先加载图片');
return;
}
try {
const canvas = cropper.getCroppedCanvas({
width: 600,
height: 600,
imageSmoothingQuality: 'high',
});
if (!canvas) {
alert('裁剪失败,请重试');
return;
}
const base64 = canvas.toDataURL('image/jpeg', 0.9);
document.getElementById('ticket_crop').value = base64;
const preview = document.getElementById('ticketPreview');
preview.src = base64;
preview.style.display = 'block';
// 清空文件输入,避免同时提交原始文件
document.getElementById('ticketInput').value = '';
closeCrop();
} catch (e) {
alert('裁剪失败:' + e.message);
}
}
// 点击模态框外部关闭
document.getElementById('cropModal').addEventListener('click', function(e) {
if (e.target === this) {
closeCrop();
}
});
// ---------- OMDb 自动获取 ----------
document.getElementById('fetchBtn').addEventListener('click', function() {
const title = document.getElementById('movieTitle').value.trim();
const status = document.getElementById('fetchStatus');
const btn = this;
if (!title) {
status.style.color = '#e74c3c';
status.textContent = '⚠️ 请先输入电影名称';
return;
}
btn.disabled = true;
status.style.color = 'var(--text-secondary)';
status.textContent = '⏳ 正在获取...';
fetch('fetch_movie.php?q=' + encodeURIComponent(title))
.then(res => res.json())
.then(data => {
if (data.error) {
status.style.color = '#e74c3c';
status.textContent = '❌ ' + data.error;
btn.disabled = false;
return;
}
// 填充电影名称(自动补全)
document.getElementById('movieTitle').value = data.title;
// 组装信息文本
let infoText = '';
if (data.year) infoText += '📅 年份:' + data.year + '\n';
if (data.genre) infoText += '🏷️ 类型:' + data.genre + '\n';
if (data.runtime) infoText += '⏱️ 片长:' + data.runtime + '\n';
if (data.director) infoText += '🎬 导演:' + data.director + '\n';
if (data.actors) infoText += '👤 主演:' + data.actors + '\n';
if (data.imdbRating && data.imdbRating !== 'N/A') infoText += '⭐ IMDb评分:' + data.imdbRating + '\n';
if (data.plot && data.plot !== 'N/A') infoText += '\n📝 ' + data.plot;
document.getElementById('movieInfo').value = infoText;
// 显示海报预览
if (data.poster && data.poster !== 'N/A') {
const preview = document.getElementById('posterPreview');
const wrap = document.getElementById('posterPreviewWrap');
preview.src = data.poster;
wrap.style.display = 'block';
status.textContent = '✅ 已获取信息,海报仅供参考,仍需上传图片文件';
} else {
document.getElementById('posterPreviewWrap').style.display = 'none';
status.textContent = '✅ 已获取基本信息(无海报)';
}
status.style.color = '#27ae60';
btn.disabled = false;
})
.catch(err => {
status.style.color = '#e74c3c';
status.textContent = '❌ 网络错误,请稍后重试';
btn.disabled = false;
console.error(err);
});
});
// 回车触发获取
document.getElementById('movieTitle').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
document.getElementById('fetchBtn').click();
}
});
</script>
</body>
</html>