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/ 等运行时数据
This commit is contained in:
laoyang
2026-09-21 08:16:25 +08:00
parent 7392b867c5
commit d7c6ac2559
24 changed files with 7238 additions and 2 deletions
+287 -2
View File
@@ -1,3 +1,288 @@
# MovieLog_Server
# MovieLog_Server · 电影全纪录
电影记录系统服务器端
一个轻量级的个人/家庭观影记录系统。纯 PHP 编写,使用 SQLite 作为数据库,**无需任何框架、无需 Composer、无需配置数据库服务**,上传到支持 PHP 的空间即可运行。
> 记录每一帧感动 —— 观影记录、影院、同行人、票根与照片,以及属于你的年度观影报告。
---
## 功能特性
### 观影记录管理
- **瀑布流首页**:按观影日期倒序展示所有电影,卡片显示海报、日期、影院(影院专属配色)、同行人头像。
- **添加电影**:支持电影名、剧情简介、观影日期、电影院、同行人、海报、票根、多张观影照片。
- **编辑 / 删除**:编辑页可替换或裁剪已有图片;删除电影时同步清理关联的图片文件。
- **电影详情**:海报大图、基本信息、备注、同行人列表(含头像)、影院信息、影像记录画廊(票根 + 观影照片,点击可查看原图)。
### 图片处理
- **内置裁剪器**:基于 Cropper.js,票根 / 海报 / 观影照片 / 观影人头像均可在浏览器内裁剪后再保存,服务端接收 Base64 图片落盘。
- **多图上传**:观影照片支持一次选择多张。
- **头像兜底**:未上传头像的观影人自动生成"首字母 + 配色"的 SVG 头像,配色由姓名哈希决定,同名同色。
- 上传目录按类型分离:`uploads/posters/``uploads/tickets/``uploads/photos/``uploads/avatars/`
### 信息辅助
- **OMDb 自动获取**:在添加页输入片名后点击「📡 自动获取」,自动填充年份、类型、片长、导演、主演、IMDb 评分与剧情简介,并预览海报(海报仅供参考,仍需本地上传)。
- **CSV 批量导入**:一次性导入历史数据,自动识别 UTF-8 / GBK / GB2312 编码,自动创建不存在的影院,影院名去重,全程事务保护(出错自动回滚),并输出逐行错误报告。
### 检索与统计
- **首页快捷搜索**:按片名模糊搜索。
- **高级搜索**:片名 + 影院 + 观影人 + 日期区间,多条件组合筛选。
- **统计仪表板**:总览卡片(电影数 / 影院数 / 观影人数 / 观影人次 / 时间跨度),按影院、按观影人、按年份、最近 12 个月的条形图排行。
### 年度报告
- **个性化年度报告**:以「当前登录账号所关联的观影人」为视角生成,而非全站数据。
- **报告内容**:年度观影总数、观影天数、最常去的影院、最常一起观影的人、单场最多人的电影、首末场日期、月均频率、平均间隔天数、备注关键词云、今年共同观影人排行、年末最近观看、年度观影记录墙(含海报与同行人头像)。
- **可视化**:月度观影分布、星期观影偏好(Chart.js 双图),整体为深色"影院感"主题。
### 多用户与权限
- **Session 登录**`password_hash` / `password_verify` 加盐哈希存储口令,全站页面均需登录。
- **用户管理**:可新增、编辑、删除管理员账号,可修改用户名与密码。
- **账号 ↔ 观影人绑定**:每个管理员账号可关联一个观影人,绑定后即可查看个人年度报告。
- **安全约束**:不允许删除最后一个管理员,也不允许删除自己。
- **个人资料**:修改自己的用户名与密码(需验证旧密码)。
### 基础数据维护
- **影院管理**:增删改查,支持「所在地方 / 影院名称 / 详细地址」三段式信息,内置 50 种预设配色,每个影院可用专属颜色区分;删除已被引用的影院时会给出醒目提示并要求二次确认(关联电影的影院字段将被置空)。
- **观影人管理**:增删改查,支持头像裁剪上传与专属配色;已被电影引用的观影人不允许直接删除。
### 界面与体验
- 复古票根色系(主色 `#e67e22` 橙)的响应式设计,移动端断点适配(600 / 768px)。
- 导航为下拉菜单,自动高亮当前页;顶部始终显示当前用户头像与用户名。
- 登录页为深色渐变 + 毛玻璃风格。
---
## 技术栈
| 项目 | 说明 |
| --- | --- |
| 语言 | PHP(过程式 + PDO |
| 数据库 | SQLite`db/movies.db`,首次运行自动建表) |
| 前端 | 原生 HTML / CSS / JavaScript,无构建步骤 |
| 第三方库 | [Cropper.js 1.5.13](https://github.com/fengyuanchen/cropperjs)(图片裁剪)、[Chart.js 4.4.0](https://www.chartjs.org/)(图表),均由 CDN 引入 |
| 外部 API | [OMDb API](http://www.omdbapi.com/)(电影信息查询,需申请 API Key) |
---
## 目录结构
```
MovieLog_Server/
├── config.php # 核心:常量、DB 连接、建表与迁移、公共函数、统计与年度报告查询
├── index.php # 首页:观影列表(瀑布流)+ 快捷搜索
├── add.php # 添加电影
├── edit.php # 编辑电影
├── detail.php # 电影详情
├── delete.php # 删除电影(连带清理图片文件)
├── search.php # 高级搜索
├── stats.php # 统计仪表板
├── annual_report.php # 年度报告
├── cinemas.php # 影院管理
├── persons.php # 观影人管理
├── import.php # CSV 批量导入
├── users.php # 用户(管理员)管理
├── change_password.php # 修改自己的用户名/密码
├── login.php # 登录
├── logout.php # 退出
├── nav.php # 导航栏组件(被各页面 include)
├── fetch_movie.php # OMDb 代理接口,返回 JSON
├── test_crop.php # 开发调试页:验证 Base64 图片落盘是否正常
├── css/style.css # 全局样式
├── js/main.js # 少量公共脚本
├── assets/.gitkeep # 静态占位资源目录
├── db/movies.db # SQLite 数据库(运行时自动生成,不纳入版本控制)
└── uploads/ # 上传图片(运行时自动生成,不纳入版本控制)
├── posters/ # 海报
├── tickets/ # 票根
├── photos/ # 观影照片
└── avatars/ # 观影人头像
```
---
## 数据库结构
建表逻辑集中在 `config.php``initDB()`,每次请求都会执行 `CREATE TABLE IF NOT EXISTS` 与幂等的 `ALTER TABLE` 迁移,因此**升级代码无需手动改库**。
| 表 | 作用 | 关键字段 |
| --- | --- | --- |
| `admins` | 管理员账号 | `username`(唯一)、`password`(哈希)、`avatar``person_id`(关联观影人) |
| `cinemas` | 电影院 | `place`(所在地方)、`name``address``color`(专属配色) |
| `movies` | 电影记录 | `title``info``remark``poster_path``ticket_path``photo_path`(历史遗留单图)、`cinema_id``watch_date``created_at` |
| `persons` | 观影人 | `name`(唯一)、`color``avatar` |
| `viewers` | 电影 ↔ 观影人关联 | `movie_id``person_id``name`(历史遗留字段) |
| `movie_photos` | 电影多图 | `movie_id``photo_path``created_at` |
外键约束:`movies.cinema_id → cinemas.id``ON DELETE SET NULL`)、`viewers.movie_id → movies.id``ON DELETE CASCADE`)、`movie_photos.movie_id → movies.id``ON DELETE CASCADE`)。
**历史数据迁移**`initDB()` 会自动把早期版本存在 `viewers.name` 里的姓名去重后写入 `persons`,并回填 `viewers.person_id`,老库可直接升级。
---
## 安装部署
### 环境要求
- PHP 7.4+(推荐 8.x),需启用扩展:`pdo_sqlite``fileinfo``mbstring``curl`
- Web 服务器:Apache / Nginx / PHP 内置服务器均可
### 步骤
1. **放置代码**:将项目文件放到 Web 根目录或其子目录。
2. **确保可写**:保证项目根目录可写,程序会自动创建 `db/``uploads/` 及其子目录;或手动创建并授权:
```bash
mkdir -p db uploads/posters uploads/tickets uploads/photos uploads/avatars
chmod -R 755 db uploads
```
3. **配置 OMDb API Key**(可选,仅影响「自动获取」功能):编辑 `fetch_movie.php`,将 `OMDB_API_KEY` 换成你在 [omdbapi.com](http://www.omdbapi.com/apikey.aspx) 申请的免费 Key。
4. **访问站点**:浏览器打开 `login.php`。
5. **首次登录**:数据库为空时会自动创建默认管理员:
- 用户名 `admin`
- 密码 `123456`
> **登录后请立即在「修改密码」中更换。**
### 本地快速运行
```bash
php -S localhost:8000
# 浏览器访问 http://localhost:8000/login.php
```
> 用 PHP 内置服务器时,`config.php` 中 `posterUrl()` 等函数返回的是以 `/` 开头的根路径,建议直接从项目根目录启动,或通过站点根目录访问。
### Nginx 参考配置
```nginx
server {
listen 80;
server_name movielog.local;
root /path/to/MovieLog_Server;
index index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
```
---
## 使用说明
### 添加一部电影
1. 顶部导航点击「➕ 添加电影」。
2. 输入片名后点「📡 自动获取」可自动填充影片信息(可选)。
3. 填写观影日期(必填)、选择或新建电影院。
4. 「一起看的人」逐行添加:选择已有观影人,或在下拉框中选「➕ 新增」并输入姓名,新姓名会自动进入观影人库。
5. 上传海报(推荐 2:3);上传票根会弹出裁剪框,裁剪结果以 Base64 提交。
6. 观影照片支持一次多选。
7. 保存后自动跳转到详情页。
### 生成年度报告
年度报告是**按人**生成的,需要先建立账号与观影人的绑定:
1. 进入「用户管理」,找到自己的账号,在「关联观影人」中选择对应的观影人并保存。
2. 进入「年度报告」,页面顶部切换年份即可查看。
3. 未绑定观影人时报告为空并给出提示。
### CSV 批量导入
CSV **共 9 列,顺序固定**
```
电影名称, 地点(忽略), 电影院名称, 观影日期, 观影人(空格分隔), 电影票图片路径, 海报图片路径, 备注, 合影图片路径
```
- **观影人**:多个姓名用空格分隔,例如 `张三 李四 王五`。
- **图片路径**:可带目录,系统只取最后一个 `/` 后的文件名;若整段被括号包裹(如 `(电影票/阿甘正传.jpg)`),会先取括号内内容再取文件名。
- **观影日期可为空**,空日期的记录会排在列表最后。
- **导入前**需先把图片文件放入 `uploads/tickets/`、`uploads/posters/`、`uploads/photos/`,文件名与 CSV 中提取出的保持一致。
- 编码支持 UTF-8 / GBK / GB2312,自动识别转换。
- 导入在事务中执行,失败会整体回滚;成功后显示「导入 N 条 / 跳过 M 条」及逐行错误原因。
示例行:
```csv
阿甘正传, , 万达影城, 2024-01-15, 张三 李四, (电影票/阿甘正传.jpg), (海报/阿甘正传.jpg), 经典励志片, (合影/阿甘正传.jpg)
```
### 接口:`fetch_movie.php`
供添加页前端调用,服务端代请求 OMDb 避免浏览器跨域。
- **请求**`GET fetch_movie.php?q=电影名称`
- **响应**`Content-Type: application/json`
- **成功**
```json
{
"title": "Forrest Gump",
"year": "1994",
"rated": "PG-13",
"released": "06 Jul 1994",
"runtime": "142 min",
"genre": "Drama, Romance",
"director": "Robert Zemeckis",
"actors": "Tom Hanks, Robin Wright, Gary Sinise",
"plot": "...",
"poster": "https://...",
"imdbRating": "8.8"
}
```
- **失败**`{"error": "错误说明"}`(如「未找到相关电影,请尝试更准确的关键词」)
---
## 安全注意事项
部署到公网前请务必处理以下事项:
1. **修改默认口令**:默认账号 `admin / 123456` 必须在首次登录后立即更换。
2. **更换 OMDb API Key**`fetch_movie.php` 中当前硬编码的 Key 为开发期临时使用,请替换为你自己的 Key;若仓库需要公开,建议将该值改为从环境变量读取。
3. **删除或保护 `test_crop.php`**:该文件是开发调试页,**没有登录校验**,仅用于验证 Base64 图片能否落盘,生产环境应直接删除。
4. **关闭调试输出**`config.php` 顶部当前为 `error_reporting(E_ALL)` + `display_errors=1`,上线前请改为关闭或仅写日志,避免泄露路径与数据库信息。
5. **启用 HTTPS 并校正证书校验**:`fetch_movie.php` 中 `CURLOPT_SSL_VERIFYPEER` 被设为 `false`,生产环境应改为 `true`。
6. **保护数据目录**`db/`(含 `movies.db`)与 `uploads/` 应禁止直接目录列举;SQLite 文件更应通过 Web 服务器规则**拒绝任何 HTTP 访问**。Nginx 示例:
```nginx
location ~ ^/(db|uploads/.*\.(db|sqlite)) { deny all; }
```
7. **限制上传目录执行权限**:确保 `uploads/` 下不允许执行 PHP。
---
## 已知限制与待改进
- `movies.photo_path` 与 `viewers.name` 是历史遗留字段,保留用于兼容旧数据与 CSV 导入,新代码统一使用 `movie_photos` 与 `person_id`。
- 除 `delete.php` 通过 GET 触发(带前端 `confirm`)外,其余写操作均为 POST;删除类接口未做 CSRF Token 校验。
- 暂无分页,数据量增大后首页与统计页需要补充分页或懒加载。
- `config.php` 的 `initDB()` 在每次请求都会跑一遍建表与迁移,数据量或并发上升后可改为一次性迁移脚本。
- 无「回收站」,删除电影与其图片文件不可恢复。
- `assets/placeholder-poster.jpg`、`assets/default-avatar.png` 为代码中的兜底引用,当前仓库未包含这两个文件;由于页面在检测到 placeholder 时会改用 CSS 占位块渲染,正常使用不受影响。
---
## 版本控制说明
以下内容为运行时产物或敏感数据,**不纳入版本控制**(见 `.gitignore`):
- `db/`SQLite 数据库文件)
- `uploads/`(用户上传的图片)
- `*.log`、编辑器与系统临时文件
---
## 许可
个人项目,未指定开源许可。