- 规则:只要有登录账号就能评价,与「是不是观影人」无关;评价归属 admins - 数据层 lib/reviews.php: · reviews(movie_id + admin_id 唯一索引,一个账号一部电影只一条) · review_comments(feelings 存感受 key 的 JSON 数组) · 感受目录 feelingCatalog():12 种,每种一个专属 emoji,文案与 emoji 不入库 - detail.php 新增「💬 评价与讨论」:1-10 打分(原生 radio,无 JS 也能用)、 评价正文、评价列表、每条评价下的讨论与多选感受、均分概况 - index.php:有评价的电影卡片显示 ⭐ 均分 - delete.php:删电影时显式清理评价与讨论(SQLite 外键级联默认未开启) - 顺带修一个隐患:delete.php 取一行后没关游标,读锁一直挂着, 后续同一连接上的 DELETE 拿不到写锁,页面会卡满 60 秒
174 lines
6.5 KiB
PHP
174 lines
6.5 KiB
PHP
<?php
|
||
// ============================================
|
||
// 文件: lib/db.php
|
||
// 说明: 数据库连接与初始化(建表 / 字段迁移 / 历史数据迁移 / 默认管理员)
|
||
// ============================================
|
||
|
||
// 数据库连接
|
||
function getDB() {
|
||
try {
|
||
$db = new PDO('sqlite:' . DB_PATH);
|
||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||
return $db;
|
||
} catch (PDOException $e) {
|
||
die('数据库连接失败: ' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
// 初始化数据库
|
||
function initDB() {
|
||
$db = getDB();
|
||
|
||
// 管理员表
|
||
$db->exec("
|
||
CREATE TABLE IF NOT EXISTS admins (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
username TEXT UNIQUE NOT NULL,
|
||
password TEXT NOT NULL,
|
||
avatar TEXT
|
||
)
|
||
");
|
||
|
||
// 电影院表
|
||
$db->exec("
|
||
CREATE TABLE IF NOT EXISTS cinemas (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
place TEXT NOT NULL,
|
||
name TEXT NOT NULL,
|
||
address TEXT,
|
||
color TEXT DEFAULT '#888888'
|
||
)
|
||
");
|
||
|
||
// 电影表
|
||
$db->exec("
|
||
CREATE TABLE IF NOT EXISTS movies (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
title TEXT NOT NULL,
|
||
info TEXT,
|
||
remark TEXT,
|
||
poster_path TEXT,
|
||
ticket_path TEXT,
|
||
photo_path TEXT,
|
||
cinema_id INTEGER,
|
||
watch_date DATE,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
FOREIGN KEY (cinema_id) REFERENCES cinemas(id) ON DELETE SET NULL
|
||
)
|
||
");
|
||
|
||
// 观影人表
|
||
$db->exec("
|
||
CREATE TABLE IF NOT EXISTS persons (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
name TEXT NOT NULL UNIQUE,
|
||
color TEXT DEFAULT '#888888',
|
||
avatar TEXT
|
||
)
|
||
");
|
||
|
||
// 观影关联表
|
||
$db->exec("
|
||
CREATE TABLE IF NOT EXISTS viewers (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
movie_id INTEGER NOT NULL,
|
||
name TEXT,
|
||
person_id INTEGER,
|
||
FOREIGN KEY (movie_id) REFERENCES movies(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (person_id) REFERENCES persons(id) ON DELETE SET NULL
|
||
)
|
||
");
|
||
|
||
// 多照片表
|
||
$db->exec("
|
||
CREATE TABLE IF NOT EXISTS movie_photos (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
movie_id INTEGER NOT NULL,
|
||
photo_path TEXT NOT NULL,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
FOREIGN KEY (movie_id) REFERENCES movies(id) ON DELETE CASCADE
|
||
)
|
||
");
|
||
|
||
// 系统设置表(键值结构,用于存储方式等配置)
|
||
$db->exec("
|
||
CREATE TABLE IF NOT EXISTS settings (
|
||
name TEXT PRIMARY KEY,
|
||
value TEXT,
|
||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
)
|
||
");
|
||
|
||
// 电影评价表
|
||
// 评价人是「登录账号」(admins)——不是观影人(persons / viewers):
|
||
// 没一起去看的人只要有账号,也能打分、写评价并参与讨论。
|
||
$db->exec("
|
||
CREATE TABLE IF NOT EXISTS reviews (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
movie_id INTEGER NOT NULL,
|
||
admin_id INTEGER NOT NULL,
|
||
rating INTEGER NOT NULL,
|
||
content TEXT NOT NULL,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
FOREIGN KEY (movie_id) REFERENCES movies(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (admin_id) REFERENCES admins(id) ON DELETE CASCADE
|
||
)
|
||
");
|
||
|
||
// 评价下的讨论(评论)。
|
||
// feelings 存的是感受 key 的 JSON 数组(如 [\"happy\",\"sad\"]),
|
||
// emoji 与文案不入库——统一在 lib/reviews.php 的目录里维护,改文案不用动数据。
|
||
$db->exec("
|
||
CREATE TABLE IF NOT EXISTS review_comments (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
review_id INTEGER NOT NULL,
|
||
admin_id INTEGER NOT NULL,
|
||
content TEXT NOT NULL,
|
||
feelings TEXT,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
FOREIGN KEY (review_id) REFERENCES reviews(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (admin_id) REFERENCES admins(id) ON DELETE CASCADE
|
||
)
|
||
");
|
||
|
||
// 一部电影每个账号只保留一条评价:再次提交就是修改(见 saveReview)
|
||
$db->exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_reviews_movie_admin ON reviews(movie_id, admin_id)");
|
||
$db->exec("CREATE INDEX IF NOT EXISTS idx_reviews_movie ON reviews(movie_id)");
|
||
$db->exec("CREATE INDEX IF NOT EXISTS idx_review_comments_review ON review_comments(review_id)");
|
||
|
||
// ===== 迁移字段 =====
|
||
try { $db->exec("ALTER TABLE cinemas ADD COLUMN color TEXT DEFAULT '#888888'"); } catch (PDOException $e) {}
|
||
try { $db->exec("ALTER TABLE admins ADD COLUMN avatar TEXT"); } catch (PDOException $e) {}
|
||
try { $db->exec("ALTER TABLE persons ADD COLUMN avatar TEXT"); } catch (PDOException $e) {}
|
||
try { $db->exec("ALTER TABLE movies ADD COLUMN remark TEXT"); } catch (PDOException $e) {}
|
||
try { $db->exec("ALTER TABLE viewers ADD COLUMN person_id INTEGER REFERENCES persons(id) ON DELETE SET NULL"); } catch (PDOException $e) {}
|
||
// 新增:管理员关联观影人
|
||
try { $db->exec("ALTER TABLE admins ADD COLUMN person_id INTEGER REFERENCES persons(id) ON DELETE SET NULL"); } catch (PDOException $e) {}
|
||
|
||
// ===== 迁移旧数据 =====
|
||
// 将 viewers.name 迁移到 persons
|
||
$stmt = $db->query("SELECT DISTINCT name FROM viewers WHERE name != '' AND name IS NOT NULL");
|
||
$names = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||
foreach ($names as $name) {
|
||
$chk = $db->prepare("SELECT id FROM persons WHERE name = ?");
|
||
$chk->execute([$name]);
|
||
if (!$chk->fetch()) {
|
||
$ins = $db->prepare("INSERT INTO persons (name) VALUES (?)");
|
||
$ins->execute([$name]);
|
||
}
|
||
}
|
||
$update = $db->prepare("UPDATE viewers SET person_id = (SELECT id FROM persons WHERE persons.name = viewers.name) WHERE person_id IS NULL AND name IS NOT NULL");
|
||
$update->execute();
|
||
|
||
// 默认管理员
|
||
$stmt = $db->prepare("SELECT COUNT(*) FROM admins");
|
||
$stmt->execute();
|
||
if ($stmt->fetchColumn() == 0) {
|
||
$hashed = password_hash('123456', PASSWORD_DEFAULT);
|
||
$stmt = $db->prepare("INSERT INTO admins (username, password) VALUES (?, ?)");
|
||
$stmt->execute(['admin', $hashed]);
|
||
}
|
||
}
|