laoyang
|
275bd9d80f
|
评价区改成「按钮展开表单」,评论支持两级回复
页面默认不出现任何输入框,要写什么就点对应那个按钮:
- detail.php:评价区的「写评价 / 修改我的评价 / 评论 / 回复」都做成按钮,
用原生 <details>/<summary> 折叠,点开才展开表单,提交后整页刷新自动收起。
零 JS、键盘可用。没评价过只在顶部有「写评价」;评价过则该按钮消失,改在自己
那条评价下面出现「修改我的评价」。一条评价都没有时显示「还没有评价,等你来评一个。」
- lib/reviews.php:评论改两级平铺。parent_id 为空 = 顶层评论,非空 = 对某条评论的
回复;写「回复的回复」时由 addReviewComment 规范化回顶层评论,所以库里最多两层、
页面永远只缩进一次,来回多少轮都不会越缩越窄。被回复者另存 reply_to_admin_id
(存「人」不存评论 id,对方那条被删也不会悬空),页面用「回复 @某某」标出。
deleteReviewComment 删顶层评论时连带清掉它的回复。
- lib/db.php:review_comments 增 parent_id / reply_to_admin_id 两列 + 幂等迁移,
并给 parent_id 建索引。**修一个会让老库升级白屏的顺序 bug**:新列上的 CREATE INDEX
必须排在 ALTER TABLE 补列之后 —— 建表用的是 CREATE TABLE IF NOT EXISTS,对线上
已存在的旧表不生效,索引跑在补列之前会报 no such column: parent_id,整个 initDB
挂掉。全新安装看不出来,是 e2e 的「造旧库再跑一遍初始化」专测抓到的。
- README.md:命名由「评价与讨论」改为「评价与评论」,补上按钮交互、两级平铺、
回复 @某某 与新表字段的说明。
回归:reviews_e2e 84/84、fetch_movie 76/76、storage 196/196;A/B 47 个响应中
仅详情页相关 6 个有差异,且经折叠区块比对确认差异全部限定在评价区内。
线上 PHP 7.4.30 / 8.1.7 双版本迁移与写链路(顶层评论→回复→回复的回复→清理)全部通过。
|
2026-09-22 16:09:48 +08:00 |
|
laoyang
|
dc5e788f27
|
评价本身也能填「观后感受」
- lib/db.php:reviews 表新增 feelings 列。建表语句里带上,同时补一条
ALTER TABLE 迁移 —— 上一版已经上线过没有该列的 reviews 表,老库要能自动补列。
- lib/reviews.php:saveReview() 接收感受并落库;getMovieReviews()/getMyReview()
把 feelings 解析成 key 列表(旧记录为 NULL → 空数组,不报错)。
- detail.php:评价表单加了「我看完的感受(可多选)」,与讨论用的是同一套感受;
修改评价时原勾选自动回填,取消勾选即清空;已保存的感受在评价正文下方以只读标签展示。
感受仍然只存 key(happy/sad/…),emoji 与文案统一在 feelingCatalog() 里维护。
|
2026-09-22 13:03:04 +08:00 |
|
laoyang
|
a2c26ad002
|
新增评价与讨论:打分 1-10 + 观后感受 emoji
- 规则:只要有登录账号就能评价,与「是不是观影人」无关;评价归属 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 秒
|
2026-09-22 11:42:27 +08:00 |
|
laoyang
|
7d199d5b3a
|
feat: 详情页图片改用本页灯箱,不再 window.open 弹新窗口
以前点图片会 window.open 弹一个新窗口,没有关闭按钮、来回切换很别扭。
现在把「海报 → 票根 → 观影照片」收进一个序列,点任一张在当前页弹出查看。
交互
- 左右箭头循环翻看,底部显示「3 / 8」进度与图片说明,✕ 关闭。
- 键盘 ← / → 翻页、Esc 关闭;点画面空白处关闭(点图片或按钮不关)。
- 移动端左右滑动切换;手机上箭头缩小并内收,给图片让出更多宽度。
- 弹出时给 <body> 加锁滚动;预取相邻两张,翻页不白屏。
- 只有一张图时不显示左右箭头;关闭后焦点回到原来点开的那张图。
- 英雄区海报也变成可点开(占序列首位);无真实海报时维持占位块不变。
实现
- 图片序列在页面顶部一次性组装,英雄区与图库共用同一套 data-lb-index 下标,
不再两处各算一遍;渲染与判断都统一走 storageExists / storageUrl。
- GALLERY 通过 json_encode 输出,带 JSON_HEX_TAG / HEX_AMP / HEX_APOS / HEX_QUOT,
避免豆瓣侧或文件名里的 </script> 截断脚本。
- 候选文本一律经 textContent / caption 写入,不拼 HTML。
两个实现坑(本批修掉)
- 作者样式 .lb-btn{display:flex} 优先级高于 UA 的 [hidden]{display:none},
单图时箭头实际隐藏不掉 —— 必须显式写 .lb-btn[hidden]{display:none}。
- 灯箱复用同一个 <img>,而 main.js 的破图兜底会给 <img> 打上
data-fallback-applied 后就不再处理;每次换图要 removeAttribute 重新武装,
否则只要有一张失败过,后续图片就不再有占位兜底。
验证
- php -l 通过;内联 JS/CSS 用「模拟 PHP 渲染」方式校验通过。
- 新增 lightbox_test.js(jsdom,对真实渲染出的详情页跑):38 项全通过,
覆盖打开/翻页/循环/键盘/Esc/点空白关闭/点图片不关/单图隐藏箭头/破图标记复位。
这两个坑正是它抓出来的(delete dataset.x 在 jsdom 下不生效,故改用 removeAttribute)。
- fetch_movie 端到端 76 项、storage 回归 196 项全通过。
- A/B 47 个响应:只有详情页(及会重定向到详情页的提交响应)6 个有差异,其余 41 个不变。
- 线上双 PHP(7.4/8.1)用真实数据渲染通过:4 张图序列、URL 为本站代理地址、
结构齐备、无 window.open。
(注:以 movie 身份跑 CLI 时 db/.settings.key 不可读,云端配置会被判为未完成、
所有图片都判成「不存在」;冒烟脚本改为向进程内缓存注入一份假配置绕过,
不写库、不碰真实密钥。这只影响探针,不影响以 www 运行的站点。)
|
2026-09-22 08:59:12 +08:00 |
|
laoyang
|
673a8abf78
|
feat: 云端图片存储(OSS/COS/七牛)+ 服务端代理读取,并补全文档
新增存储抽象层:图片可存本地或云对象存储,切换存储方式不影响已有图片。
存储层
- lib/storage.php 存储门面:本地优先读取、URL 生成、上传/删除、批量迁移、
服务端读取(storageRead)与访问方式判定(storageAccessMode)
- lib/storage/{local,oss,cos,qiniu}.php 四种后端驱动;http.php 共用 cURL 客户端;
meta.php 实例元数据鉴权(ECS RAM 角色 / CVM CAM 角色,免密钥)
- lib/settings.php 设置读写;云厂商密钥以 enc:v1:gcm 密文落库(db/.settings.key)
- 文件名改为内容指纹(md5 前 12 位_6 位随机[_角色].ext),内容不变则名不变,
因此可下发 immutable 长缓存
两种图片访问方式
- 直连存储:storageUrl() 产出对象存储地址(桶需允许匿名读)
- 服务端代理:media.php 鉴权后由服务器签名读取并同源回吐,桶可保持私有
· 未登录返回 403 纯文本(刻意不用 302,否则 <img> 会拿到一段 HTML)
· 对象键白名单防目录穿越;Content-Type 按扩展名白名单决定 + nosniff(防同源 XSS)
· 透传 If-None-Match / Range,上游 304 直接短路;private + immutable 长缓存
· 鉴权后立即 session_write_close(),避免排他会话锁把并行图片请求串行化
内网 endpoint 判定(修「开了代理后慢到不可用」)
- 内网地址只在与桶同地域的 ECS 上可路由;跨地域时 DNS 能解析但 TCP 连不通,
无脑「内网优先」会让每次读取先白等满一次连接超时(默认 10 秒)
- 改为先比本机 ECS 地域与桶地域(零成本、结论确定)→ 不同即跳过;
结论落缓存;内网只给 2 秒连接超时,传输层失败立刻标记且短期内不再重试
- 「测试连通性」升级为 PUT → GET 回读 → DELETE,并显式报出内网判定结论
界面与页面
- settings.php 系统设置页:驱动选择、各云配置、图片访问方式、连接测试、迁移进度
- storage_api.php 提供 stat / migrate / test 三个 JSON 接口
- detail / edit / annual_report / persons 原先直接拼本地路径(file_exists / '/'.$path),
迁云后会整块不渲染或 404,统一改为走存储门面
- js/main.js 增加破图占位兜底;config.php 统一下发 Referrer-Policy: same-origin
文档
- README 新增《图片存储与对象存储》整章:设计约定、两种访问方式取舍表、
直连存储逐项配置说明(桶 ACL / 防盗链白名单 / 跨域 CORS 与 crossorigin /
强制下载 / endpoint 地域 / 自定义域名)与上线检查清单、服务端代理实现要点、
迁移步骤、12 条踩坑记录、可直接复制的排障命令手册
|
2026-09-21 22:06:02 +08:00 |
|
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 |
|