5c81f1991f8d97fc815e04eb937e6fa712e0be70
用户原话(三段):
①「选择日期那个地方给,非常不好用。如果我不选日期,只选时间,框里面仍然是空白的,
也没有确定按钮,这个需要重新调整一下。」
②「现在上传附件,也就是在观影模块里面上传附件,怎么还是有问题?上传的附件现在
都没有保存,有时候我上传两个附件,它只保存一张。」
③「除了海报之外,票根、现场照片等等都不分类别,都只分一个类,放在一块。…
只有海报是单独的,因为它是从豆瓣里面下载回来的。其他的都放在一个模块就行,
然后所有照片都上传到一起,直接写"观影照片"就可以了。」
① 日期控件:**Semi 的时间面板根本不可用**(这条最费时间)
实测(独立最小复现页 + 真机):Semi 的 dateTimeRange 面板**只给日期网格**,
时间藏在 `.semi-datepicker-switch-time` 那个小时钟按钮后面;**点了它切到时间面板,
面板仍然是空的**(timeLists=0、无选项、无 footer、无"确定")→ 根本无法"只选时间"。
单点 dateTime 同样。⇒ 与用户描述完全一致。
修:弃用 Semi 的时间选择,改用**原生** date + time(step=1)
(24 小时制、精确到秒、点了就选、不选日期也有值、**不需要**确认按钮)。
原来的 时/分/秒 三个下拉**仍留在 DOM**(POST 契约 *_date/_hour/_minute/_second
一字不改),只是加 .dt-merged 视觉收起。
app.js 的 upgradeRange()/upgrade() 都不再挂 Semi;CSS 加 .is-native-range 系列
把 Semi 时代的"藏原生 / 两端让位"规则覆盖回来。
② 观影附件上传丢文件:**两条路径都断了**
· 暂存路径(拖放):上传框走"拖进来即刻上传到暂存区",令牌进 stage_token[];
而 movies/create|update 与 movies/photo_add **只读 $_FILES['photo']**
⇒ stage_token[] **从来没人认领** ⇒ 拖进去的一个都没存。
· Movie::update() **完全不写 photos**(那句"photos 由单独的删除路由维护"的注释下
根本没写),而路由明明算好了 $d['photos'] 传进来 ⇒ 编辑保存丢照片。
修:路由新增 stage_token[] 认领循环(与 $_FILES 路径并存);photo_add 加兜底;
Movie::update 补上 savePhotos。
③ 归并:表单去掉独立"票根"上传框,"现场合影"并入**一个**「观影照片」块;
详情页「影像记录」→「观影照片」、去掉票根/照片分类标签。
数据层本来就是平的(event_photos 只有 key/position);
⚠️ 旧数据 movie_details.ticket_key **仍要显示**(历史票根不能丢)+ 服务端仍接收
$_FILES['ticket'](向后兼容,直接 POST 仍可存)。
验证(全部真机跑,不是"看代码觉得对"):
· _fb_b34_dtrange.py 33/0(四个表单页:组可见 + 两端日期框可见 + 两端时间框
可见且 step=1 + 三个原生下拉仍在 DOM + 只选时间也能写回 *_hour/_minute/_second);
· _fb_b35_movie_media.py 14/0(点击上传 2 张→库里 2 行;真 HTTP 打 upload_stage.php
拿 stoken→随表单提交→落库;编辑补传→3 行;详情页补传→4 行;归并断言);
· 反向验证:_fb_b34_dtrange_falsify 4/0、_fb_b35_media_falsify 8/0;
· e2e 1503/0(两条断言随 v35 语义更新)、几何交互 92/0、各批真机/反向全绿、
部署脚本静态断言空跑通过;线上 app.js / form.php 的 SHA256 与本地一致。
顺带修掉的工具链脆弱(本轮暴露):
· push.sh 开头加"确保本地测试库在跑"的守卫(长时间跑流水线时 mysqld 会被环境
回收 → e2e/真机探针全崩,看着像代码坏了);
· 探针别用固定字符窗口找函数体(注释一长就假红)、断言别写死字段名前缀
(改期表单是 rev_ends_at_*)、set_input_files 的 id 要照 _stage_drop 的净化规则
(photo[] → sd-photo)、提交按钮要精确定位(编辑页有多个 submit)。
FamilyBook
家书,记录家庭的全部生活,一本用岁月写成的家谱。
把一个家的「人」「日子」「去过的地方、看过的电影」收进同一本书里。
它是什么
一个自托管的家庭生活系统。它不是又一个待办清单,而是这个家的长期档案 —— 十年之后还能翻出孩子第一次观影的票根、那年暑假走过的路线。
围绕三个圈展开:
- 人:家庭成员、亲友通讯录,以及他们之间的共享关系
- 时间:日历、日程、提醒,以及任务的期限
- 事件:观影、旅行、其他活动 —— 一切都落在同一条时间轴上
它在做什么
| 阶段 | 主题 | 内容 |
|---|---|---|
| 0 | 地基 | 名册、账号、登录、权限模型、安装向导 |
| 1 | 通信 | 通讯录、共享给某个成员、CardDAV 服务端 |
| 2 | 时间 | 日历本、重复日程、提醒、CalDAV 服务端 |
| 3 | 归一 | 观影与旅行迁入统一事件模型 |
| 4 | 任务 | 任务管理,期限自动映射成日历事件 |
| 5 | 回看 | 统计、年度家书、时间轴 |
当前进度:阶段 0 起步,仓库里只有图标与脚手架。
技术选型
- PHP 7.4+(无框架、无 Composer,上传到站点目录即可运行)
- MySQL 5.7+ / 8.0(
utf8mb4) - 前端为原生 HTML / CSS / JavaScript,无构建步骤
⚠️ 注意 CalDAV / CardDAV 是双向协议,和单纯的 .ics 文件导出不是一个量级的东西。
部署
- 把代码放到站点根目录;
- 复制
config.example.php为config.php,填写数据库与app_key; - 访问站点根,按引导页确认 PHP 版本、扩展、配置、数据库连接四项都通过。
config.php 不入库(已在 .gitignore 中忽略),其中包含数据库口令与加密密钥。
⚠️ app_key 一旦开始记录数据就不能再改(换掉即解不开已有数据),
并且它必须单独备份 —— 密钥丢失等同于数据永久丢失。
隐私
身份证号、手机号属于敏感个人信息,一律加密存储。 (就家庭自用而言,身份证号其实没有多少必须存的场景,启用前请三思。)
图标
见 assets/icons/。概念是「这本书就是家」:屋顶即一本摊开的书,
屋顶下纸做的墙上,三行横线是这个家写下的日子。
开源协议
Languages
PHP
81.6%
JavaScript
9.3%
CSS
9.1%