# album **Repository Path**: yhANDwf/album ## Basic Information - **Project Name**: album - **Description**: 一个跨多端同步的家庭相册:记录孩子成长的每一刻,也留下全家人的美好回忆 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-03 - **Last Updated**: 2026-10-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 家人时光(原「女儿成长记录」) > 2026-10-10 P1修复已发布(运行代码提交aa61906):持久解析队列、上传补偿与资源闸门、锁定语音导出隔离、SSH可信主机校验及部署/恢复保护。上传/导出各并发1,解析活动1、待处理全局100/家庭20;总multipart上限由backend/limits.py定义。实施与验收见[开发方案](docs/design/开发方案-P1问题修复-2026-10-10.md)。 家人时光让一家人一起讲述孩子的成长,把照片、荣誉和声音整理成可回看的共同记忆。第一批面向多代参与的育儿家庭;多台设备共享同一份家庭记录,写操作几十秒内另一端自动可见。 > 产品名已从「女儿成长记录」升级为「家人时光」,更契合「全家人一起记录」的定位。代码与文档中仍可能见到旧名,功能不受影响。 > > **接手请先读 [`AGENTS.md`](AGENTS.md)**(地图 + 铁律 + 自检清单);分类文档见 [docs/README.md](docs/README.md),脚本职责与风险见 [deploy/README.md](deploy/README.md);**变更历史**见 [`CHANGELOG.md`](CHANGELOG.md);**踩坑复盘**见 [`docs/incidents/事故档案.md`](docs/incidents/事故档案.md)。 > 最近更新:2026-10-08(产品定位聚焦多代家人共同讲述孩子成长;现有能力与试用前的署名文字故事缺口见 [产品定位与核心优势](docs/product/产品定位与增强路径-2026-09-16.md),功能和发布状态以本页及 CHANGELOG 为准)。 ## 技术栈 - 前端:Vue 3 + Vite + TypeScript - 后端:Python FastAPI + SQLite + **可插拔存储抽象层**(默认本地盘,可配置切换 S3 兼容云存储:阿里云 OSS / 腾讯云 COS / AWS S3) - 智能整理:标题优先 + MinerU 双通道(精准 / 轻量) - 多端同步:Redis 版本号 + ETag/304 + 30s 轻量轮询 + `visibilitychange` - 证件照工具:本地 rembg 抠图 + 标准证件照合成(独立 idphoto 容器,已部署) ## 核心功能 | 模块 | 能力 | 状态 | |------|------|------| | 家庭与身份 | 创建家庭 / 邀请码加入(幂等防重复)/ owner 转让 / 移除成员 / 跨设备 Onboard 引导(新设备加入优先 + 后端同名容错)/ 桌面侧栏「我是」切换下拉 + **移动端顶栏身份选择弹层** / 老用户 memberId 自动回填 / **本地身份失效自愈**(按姓名静默重绑,失败转选身份) | ✅ 已上线 | | 照片内容 | 上传(客户端预压缩 + XHR 进度 + 全屏遮罩)、时间线混排(照片+荣誉)、今日回忆 hero(重要瞬间优先级:手动标记 > AI 自动标记 > 兜底最新一张,删后仍能正确兜底)、点赞、重要瞬间、语音留言、多图角度、**回收站(软删除可恢复 / 彻底删除才清文件)**、**站内搜索**(标签/标题/日期/荣誉信息即时过滤);上传改**方案 B**——原图(全分辨率,50MB 上限,详情大图用)+ 缩略图(列表/时间线/hero 用)双存,缩略图前端预生成、后端 Pillow 兜底,异常自动降级为只用原图 | ✅ 已上线 | | 荣誉记录 | 证书 / 奖状 / 奖杯 / 奖牌,混排进主时间线 +「只看荣誉」筛选,多角度图(封面/侧面/底座…)与 `award_kind` 联动;可把某份荣誉「📌 置顶为封面」(仅 award,`pinned_at` 时间戳;荣誉殿堂封面置顶优先、未置顶兜底最新,不影响时间线排序契约) | ✅ 已上线(V3);HonorView 以能力发展线纵向聚合荣誉,并按成员生日算「当时几岁几个月」获奖年龄卡 | | 成长里程碑(B1) | 成员生日字段 `members.birthday`(纯日期,家人手填)+ `PATCH /api/families/{id}/members/{member_id}` 写入;为荣誉页「当时几岁几个月」提供数据源(前端年龄卡接入待排) | ✅ 后端已上线(2026-09-18) | | 家庭共建(A1) | 贡献统计 `GET /api/families/{id}/contributions`:服务端权威口径按成员聚合 total / 今年 / 照片 / 荣誉 / 最近记录;荣誉按**获奖日期**计今年(与 timeline/yearbook 同口径,前端旧聚合误用上传年);软删不计;名单保留未记录成员(正向不排名) | ✅ 后端已上线(2026-09-18) | | 年度画册(C1) | 传承页「年度画册」选年度生成**自包含可分享网页**(封面 / 章节 / ★重要瞬间 / 全部回忆 / 🎙声音 / ✉时间信封,未解锁🔒保密占位),浏览器打印另存 PDF 分享;与「📦 原图打包」zip 导出并存;数据来自 `GET /api/families/{id}/yearbook` | ✅ 已上线(2026-09-18) | | 家庭声音档案(C2) | 声音时光胶囊升格为**家庭级归档**(`GET /api/families/{id}/voices`,按年归档);未解锁🔒占位不可播,显示留言人 / 附着回忆 / 注记 / 写给谁;回收站内容的声音不进档案 | ✅ 已上线(2026-09-18) | | 家庭事件(B2) | 同一次出行 / 活动的照片聚成一组:创建 / 改名 / 删除 / 归入 / 移出,展开即分组视图,封面自动回落;`POST/GET/PATCH/DELETE /api/events/{id}` + 内容归组 | ✅ 已上线(2026-09-18) | | 长辈极简模式(A2) | 大字号 / 大按钮 / 默认只看 / 一键点赞 / 按住说话;偏好持久化(useElderMode,Home 开关 + ContentDetail 联动) | ✅ 已上线(2026-09-18) | | 拍摄时间自动整理 | 上传即读 EXIF `DateTimeOriginal` 写入 `contents.taken_at`(前端 `src/exif.ts` 先解析、后端 `backend/exif.py` 兜底,两端零依赖手写解析、无新增库);时间线排序键统一为 `COALESCE(awarded_at, taken_at, created_at)`,**老照片按拍摄年份落位**而非「最近上传」;无 EXIF(截图/微信转存)回落 `created_at` 不会错位;详情页显「拍摄于 … 上传于 …」 | ✅ 已上线(2026-09-21) | | 智能整理 | 上传后 MinerU 双通道 OCR → 摘要 / 标签 / 重要瞬间 / 原文(原文截断 8000 字防膨胀) | ✅ 已上线 | | 时间信封 | **「写给未来的话」**:给一张内容附一段文字(≤2000 字)+ 设定未来解锁日期(如孩子 18 岁生日),未到时间前正文对**所有人(含作者本人)**隐藏、只显 🔒 占位;点「提前拆封」经二次确认后立即解锁并可修改(拆封不可逆,但可重设日期重新封存) | ✅ 已上线(C3) | | 数据导出 | 一键导出家庭相册为 zip(照片 + 语音 + 元数据),只读不写库 | ✅ 已上线(V6) | | 多端同步 | 写操作后另一端 ≤30s 自动可见;ETag/304 + 30s 轮询 + visibilitychange;同步异常顶部红条;解析轮询 60s 守卫超时提示可重试 | ✅ 已上线(V2) | | 证件照工具 | 本地 rembg 抠图 + 标准证件照合成(一寸/二寸/六寸排版),独立 idphoto 容器,已部署上线 | ✅ 已上线 | | 体验 | LazyImage 加载骨架 + 淡入、客户端压缩提速 70–90%、串行上传守 1.8G 内存纪律、移动端窄屏友好化;**9/18 界面打磨**:视觉一致性令牌纪律收口(深色模式硬编码色 / 红不一致修正)+ 头像尺寸单一真相 + 鎏金描边 `.ring-owner` 工具类、移动端侧栏底部 / 成员与家庭设置弹窗 / 身份选择抽屉重设计、荣誉墙双列瀑布流零留白 | ✅ 已上线 | | 首页与浏览 | 主视觉 hero(重要瞬间优先:**手动标记 > AI 自动标记 > 兜底最新一张**,由 `key_moment_source` 区分来源,AI 解析不再覆盖家人手动星)+ 最新照片印章标签 + 双列等高 showcase:左列主视觉大图 + 今日回忆卡片,右列「家人的高光」精选面板(内嵌搜索 + 🏆 只看荣誉 + 嵌入荣誉殿堂);时光轴改为**章节式画册卡片**(章节号 + 标题),搜索栏内嵌;移动端四项 Tab(时光 / 荣耀 / 共建 / 传承) | ✅ 已上线(2026-09-10 重设计) | | 存储架构 | 可插拔**存储抽象层**:`file_path` 升格为「存储 key」(如 `{family_id}/{uuid}.jpg`);默认本地盘与线上 100% 等价,`STORAGE_BACKEND=s3` 可配置切换 S3 兼容云存储(OSS/COS/AWS),切云不动业务代码 / 数据库 / 前端;`url()` 产出直接喂 ``,`local_file()` 上下文管理器自动取本地路径并清理云临时文件 | ✅ 已上线(2026-09-11) | ## 目录结构 ``` / backend/ # FastAPI 后端 main.py # 入口 + CORS(expose ETag) + 路由 + 静态托管 db.py # SQLite 连接 + 增量迁移 + 常量单处化(AWARD_KINDS/IMAGE_KINDS/...) smart.py # 智能整理规则引擎 exif.py # 照片拍摄时间解析(零依赖手写 JPEG/EXIF 解析,见 §3.1 时间纪律) routers/ # 13 个:contents / families / uploads / parse / idphoto / awards / chapters / events / feeds / content_images / _common + deps(权限判据唯一出口,见 AGENTS.md §3.11) services/ # mineru_client / parser / parse_jobs / redis_client / idphoto_client storage/ # 可插拔存储抽象层:base / local / s3 / factory / receive / migrate_to_cloud uploads/ # 本地存储根目录(自动创建,已 gitignore) .dockerignore # 挡住本机 DB / uploads / __pycache__ 进镜像(.gitignore 管不到构建上下文) requirements.txt # 运行时依赖(唯一真相源;Dockerfile 直接读它) requirements-dev.txt # -r requirements.txt + pytest tests/ # pytest(含发布工具、安全与邀请码并发回归;当次用例数以 pytest 汇总为准;覆盖荣誉 / 置顶 / 存储抽象层 / 时区 / OCR / 身份与跨家庭隔离 / 拍摄时间 / 发布失败判据等) frontend/ # Vue3 前端 public/ # 品牌图标资产(favicon.svg/.ico、apple-touch-icon、android-chrome-*、manifest.json) scripts/gen_icons.py # 由「门与光」矢量定义生成各尺寸 PNG/ICO(需 Pillow;改图形后重跑) src/api/ # 后端 API 封装(含 ETag 缓存 + X-Member-Id 身份头) src/exif.ts # 前端拍摄时间解析(backend/exif.py 的镜像,上传前读掉省服务端 CPU) src/views/ # 7 个:Home / CreateFamily / JoinFamily / Onboard + HonorView / CoCreateView / LegacyView(四视图 IA) src/components/ # 16 个:展示型 MemoryCard / TimelineItem / TimelineSentinel / LazyImage / VisionHero / HonorWall / TagGroup / BrandMark / IdPhotoIcon + 容器型 ContentDetail / UploadMask / AwardUploadDialog / FamilyEvents / IdentityPanel / TrashDialog / IdPhotoTool src/composables/ # 7 个:核心 4(useParsePolling / useTimelineCache / useTrash / useUploadQueue)+ 界面 3(useTheme / useElderMode / useAppearance) deploy/ # 日常脚本与配置 + once/(完整速查表见 deploy/README.md) ssh_helper.py # paramiko 封装(put/run),所有服务器操作的唯一通道 deploy_frontend.sh # 前端一键部署(build → tar → upload → 原子交换 → verify → cleanup) da_deploy_backend.sh # 后端标准部署(:prev 回滚点 → tar → build → 重建容器) redeploy_run.sh # 只重建容器(配合单文件上传,规避 tar 传输失效) smoke_test.sh/.py # 服务器端只读冒烟(现有家庭的身份、时间线与 ETag) deploy.config.json # 服务器/路径/健康检查配置 checks/ # 独立诊断、链接校验与专项检查 maintenance/ # 数据维护工具(默认 dry-run) … # 备份恢复 / 时区探针见 deploy/README.md once/ # ⚠️ 已完成的一次性脚本(迁移/回填),默认不要跑 docs/ # 分类文档,入口 docs/README.md product/ # 产品方向、验证计划、工程待办 design/ # 存储/OCR/荣誉/署名故事等方案 engineering/ # 规范、代码库地图、维护、目录审计 operations/ # 部署拓扑与发布门禁设计 reviews/ # 架构/系统评审及验收记录 incidents/ # 事故档案与技术/流程复盘 archive/ # 历史规划、决策史和原型 AGENTS.md # ★ 唯一入口:接手指南(地图 + 文件准入 + 铁律 + deploy 速查表 + 自检清单) CHANGELOG.md # 变更历史(按日期倒序,含 commit 号) README.md # 本文件:现状权威(功能表 / API / 目录 / 部署 / 路线图状态) outputs/ # 交付与过程稿(设计稿、预览 HTML、修复说明;已 gitignore) ``` > **维护与交接**:模块职责、依赖链路见 [`docs/engineering/代码库理解与架构梳理-2026-09-17.md`](docs/engineering/代码库理解与架构梳理-2026-09-17.md);周期维护、风险及接手验收见 [`docs/engineering/维护与交接规划-2026-09-22.md`](docs/engineering/维护与交接规划-2026-09-22.md)。 ## 本地启动 前置:后端需要 `fastapi` + `uvicorn`(见 `backend/requirements.txt`),前端需要先装依赖。 ### 后端 ```bash cd backend python -m uvicorn main:app --reload --port 8000 ``` (若你的 `python` 不带 fastapi/uvicorn,用装了依赖的那个解释器,例如虚拟环境的 `Scripts/python.exe -m uvicorn ...`。本机便利脚本不在版本库里——含机器专属绝对路径,参见 `AGENTS.md`「文件准入与目录职责」。) ### 前端 ```bash cd frontend npm install npm run dev ``` ## 测试与构建 ```bash # 后端测试 cd backend && python -m pytest tests/ -q # 前端类型检查 + 构建 cd frontend && npx vue-tsc --noEmit && npx vite build ``` ## API 一览 ### 家庭与成员 | 方法 | 路径 | 说明 | |---|---|---| | POST | `/api/families` | 创建家庭(返回邀请码) | | POST | `/api/families/join` | 邀请码加入(幂等,同名成员不重复) | | POST | `/api/families/{id}/invite-code/rotate` | 管理员重新生成邀请码;旧码立即失效,已有成员不受影响 | | GET | `/api/families/{id}` | 家庭信息 | | GET | `/api/families/{id}/members` | 成员列表 | | DELETE | `/api/families/{id}/members/{member_id}` | 移除成员(上传者 / owner / admin) | | PATCH | `/api/families/{id}/members/{member_id}` | 设置成员生日(`birthday` 纯日期 YYYY-MM-DD,null=清除;本人 / owner / admin) | | POST | `/api/families/{id}/transfer-owner` | 转让 owner(解死锁) | | GET | `/api/families/{id}/export` | 导出相册 zip(只读) | | GET | `/api/families/{id}/chapters` | 章节名列表(仅家人自定义过的年份) | | PUT | `/api/families/{id}/chapters/{year_key}` | 写入章节名(任意家庭成员;空串=清除,回落「YYYY 年」) | | GET | `/api/families/{id}/yearbook?year=YYYY` | 年度画册结构化数据(只读;未拆封信封/未解锁语音不吐正文与 url) | | GET | `/api/families/{id}/voices` | 家庭级语音归档(未解锁语音不吐 url/file_path) | | POST | `/api/families/{id}/events` | 创建家庭事件(任意家庭成员) | | GET | `/api/families/{id}/events` | 事件列表(含封面回落、条数、时间范围) | | PATCH | `/api/events/{id}` | 改事件标题/描述/封面 | | DELETE | `/api/events/{id}` | 删事件(内容 event_id 置空,**内容本身保留**) | | POST | `/api/events/{id}/membership` | 内容批量归入/移出事件 | ### 内容与照片 | 方法 | 路径 | 说明 | |---|---|---| | POST | `/api/families/{id}/uploads` | 上传照片(`taken_at` 可选:前端已解析 EXIF 则直接传,未传则后端读原图 EXIF 兜底;触发 MinerU 智能整理) | | POST | `/api/families/{id}/awards` | 记录荣誉(证书/奖状/奖杯/奖牌,跳过 MinerU,多图+角度) | | GET | `/api/families/{id}/timeline` | 时间线(照片+荣誉混排,排序键 `COALESCE(awarded_at, taken_at, created_at)`;返回 `ETag`,`?type=award` 仅荣誉,`?limit=&cursor=` 游标分页) | | GET | `/api/families/{id}/contributions` | 贡献统计(成员级 total/今年/照片/荣誉/最近记录;荣誉按 `awarded_at` 计今年;只读不 bump) | | GET | `/api/families/{id}/memory` | 今日回忆 | | GET | `/api/contents/{id}` | 单条内容详情(含多图、署名故事及计数) | | PATCH | `/api/contents/{id}` | 改标题 / 标签 / 重要瞬间 / 荣誉元数据 / **时间信封**(`capsule_text` ≤2000 字、`unlock_at` 未来时间;`unlock_at` 传空串 = 清空即提前解锁,此时响应即返回明文正文)/ 能力类别 `ability` ≤20 字(成长里程碑按它聚合) | | POST | `/api/contents/{id}/like` | 点赞 | | POST | `/api/contents/{id}/key-moment` | 设/取消重要瞬间(手动操作记 `key_moment_source='manual'`;上传/后台解析三处写库统一走 `db.apply_parse_fields()`,遇 manual 保持不变,绝不覆盖家人手动标记) | | POST | `/api/contents/{id}/stories` | 追加本人署名故事(照片/荣誉,每人一段,1–1000 Unicode 字符) | | PATCH | `/api/contents/{id}/stories/{story_id}` | 作者编辑自己的故事 | | DELETE | `/api/contents/{id}/stories/{story_id}` | 作者或 owner/admin 删除故事 | | POST | `/api/contents/{id}/voice` | 语音留言 | | GET | `/api/contents/{id}/voices` | 语音留言列表 | | PATCH | `/api/contents/{id}/voices/{voice_id}` | 改语音时光胶囊 `unlock_at`/`for_member_id`/`note`(写=上传者·owner·admin;未解锁不吐 url) | | POST | `/api/contents/{id}/images` | 追加角度图 | | DELETE | `/api/contents/{id}/images/{image_id}` | 删角度图(封面同步重排) | | POST | `/api/contents/{id}/images/reorder` | 角度图排序 | | DELETE | `/api/contents/{id}` | **软删除**:打 `deleted_at` 标记移入回收站,物理文件与角度图/语音保留 | | GET | `/api/families/{id}/trash` | 回收站列表(按删除时间倒序,带 images 便于渲染缩略图) | | POST | `/api/contents/{id}/restore` | 从回收站恢复,重新进入时间线 | | DELETE | `/api/contents/{id}/permanent` | 彻底删除:先收集全部物理路径 → 删库 → 删文件(唯一清文件入口) | | GET | `/api/contents/{id}/parse` | 解析状态轮询 | | POST | `/api/contents/{id}/reparse` | 解析失败手动重试 | | POST | `/api/contents/{id}/pin` | 置顶/取消置顶一份荣誉为「荣誉殿堂」封面(仅 award;不传 `value` 则取反)。只影响殿堂封面选择,不改时间线排序契约 | ### 证件照与其他 | 方法 | 路径 | 说明 | |---|---|---| | POST | `/api/families/{id}/idphoto` | 本地生成标准证件照(独立 idphoto 容器,已部署) | | GET | `/api/health` | 健康检查 | | GET | `/uploads/{family_id}/{name}` | 静态文件托管 | > **身份与权限**(2026-09-15 收紧,详见 `AGENTS.md §3.11`):机制仍是邀请码 + `X-Member-Id` 声明式身份,**不是真鉴权**(猜到 `family_id` + 成员 id 即可冒充)。但**不再有任何降级**——header 缺失 / 非法 / 不属于该家庭一律 **401**,跨家庭读写一律拒绝;读接口要「家庭成员」、写接口(修改 / 删除 / 置顶 / 重新解析)要「上传者 / owner / admin」**403**。判据只在 `backend/routers/deps.py` 一处。家庭级共建元数据(章节命名 / 事件)的写特意用 `require_member`(任意家庭成员,非破坏性单值元数据),见 `routers/chapters.py` / `routers/events.py` 模块头。仅 `GET /families/{id}` 与成员名单刻意开放(App 靠它们做身份引导)。 ## 部署(1.8G 阿里云服务器纪律) - **后端**:`bash deploy/da_deploy_backend.sh` 配套本地上传;容器 `daughter-album-backend`,数据卷 `/www/dk_project/daughter-album/data:/data`(含 SQLite + uploads,**重建容器勿删**)。 - **前端**:`bash deploy/deploy_frontend.sh "<密码>"` 一条命令完成 build → 上传 → 暂存并原子交换 → 校验 → 清理;产物落到 `/www/wwwroot/120.27.247.229/dist/`,属主 `www:www`。 - **Redis**:共享容器 `redis_mbkx-redis_mbKX-1`,**db=1 + 前缀 `da:`**,与其他 app 隔离。 - **nginx**:站点 `html_120.27.247.229.conf`,`/api/` 与 `/uploads/` 反代到 8000;curl 验证须带 `-H "Host: 120.27.247.229"`。 - 发版冒烟:`bash deploy/smoke_test.sh`(**在服务器执行**;只读验证现有家庭、成员身份、时间线与 ETag;任何断言失败返回非零)。`release.sh` 自动投送并在服务器执行,同时比对镜像时间与前端产物哈希。 - 访问地址:`http://120.27.247.229/`(IP 直访,无 HTTPS)。 ### 备份与恢复(2026-09-09 演练通过) | 项 | 位置 / 周期 | 说明 | |---|---|---| | 每日备份 | cron `0 3 * * *` → `deploy/backup_data.sh` | 先复制文件、再取 SQLite 在线快照并核对引用与内容;SQL 可导入后发布到 `backup/auto/data-backup-*.tar.gz`,新格式滚动保留 7 份;2026-09-28 已定向更新并试跑成功(46 个有效文件引用通过,2 条历史孤立图片行告警) | | 每周校验 | cron `0 4 * * 0` → `deploy/restore_data.sh` | DRY-RUN:解到 `/tmp`,实际导入 SQL dump 并执行 `integrity_check`;不替换线上 `/data`。结果写 `backup/verify.log`。 | | 备份切换与恢复演练 | `deploy/install_backup_cron.sh`、`deploy/restore_data.sh` | 2026-09-28 新备份归档约 70 MB、storage 52 个文件;DRY-RUN 导入 dump 与 `integrity_check` 通过,未执行覆盖线上数据的 `--apply`。其他应用 cron 保留。 | **演练结果(9/9 03:00 那份备份)**:gzip OK、库可读 `contents=16 / members=10 / families=7`、原图 17 个文件,与线上(`contents=17`,当天新增 1 条)对得上 → **备份确实能恢复**。 **真要恢复时**(会覆盖线上数据;2026-09-14 已决定**不做**真实恢复演练,以下命令仅在确有需要时由人工执行): ```bash bash /www/dk_project/daughter-album/deploy/restore_data.sh # 先 DRY-RUN 看清楚用了哪份归档 bash /www/dk_project/daughter-album/deploy/restore_data.sh --apply [归档路径] # 停容器 → 替换 /data → 重启 → 探活 ``` 脚本兼容两种归档布局(`data/` 前缀 / 平铺)与两种命名(`data-*` / `data-backup-*`)。 ## 待办与路线图 > 历史规划见 `docs/archive/`(V4/V5 路线图)。**截至 2026-09-30:四视图 IA 与原规划 9 项功能全部落地;试用前仍有 P0 凭据安全债与真实设备验收门槛;多人署名故事已上线(2026-09-30)**。下表为状态总览;**当前产品验证与迭代计划见 `docs/product/产品验证与迭代计划-2026-09-29.md`**,**工程待办见 `docs/product/后续工作-V6-2026-09-14.md`**,**变更历史见 `CHANGELOG.md`**: > > ✅ **2026-09-17 · 全新 UI v0 已落地为 Vue 四视图**:「时光 / 荣耀 / 共建 / 传承」四界面 IA 落地为 HonorView / CoCreateView / LegacyView + Home 四 Tab(原型与设计说明仍在 outputs/ 留档)。✅ 年度画册(C1)与长辈极简模式(A2)已落地;邀请码轮换(管理员重新生成、旧码立即失效)与荣誉卡片统一打磨线上状态已由用户核实。 | 优先级 | 项 | 状态 | |--------|----|------| | P0 | 代码提交并推送 Gitee | ✅ 已完成(含 2e3e150 手动星优先、d29d52d 荣誉置顶、fe0dd28/76e00da/3305c08 首页重设计、c593309 手机端弹窗修复等均已 push 至 Gitee main) | | P0 | 生产数据 `/data` 备份演练(DB + uploads 可恢复验证) | ✅ 已完成(2026-09-09 演练通过:备份可恢复) | | P0 | 凭据安全债(遗留,**未处理**) | ⬜ Redis 密码曾明文硬编码进 `deploy/da_deploy_backend.sh` / `deploy/.env.example` 的**多个历史提交**(至今可从 git 历史析出真实密码);当前工作树已改为从 gitignored 的 `deploy/.env` 读取,但**本机 `deploy/.env` 与 `~/.git-credentials` 仍明文存密码**。需:① 轮换 Redis 密码 ② `git filter-repo` 改写历史清除明文 ③ 重建后端容器 ④ 清理本机凭据文件。改动前务必打 `:prev` 回滚点 | | P1 | 多人署名文字故事(试用前新需求) | ✅ 已上线并通过自动测试、浏览器及发布终态验收;每人每条一段,作者自管、管理员可删除,不覆盖原有标题。成员停用保留全部记录,同名重加入获得新身份。安全与真实设备门槛仍待通过。 | | P1 | 荣誉打磨(Phase C:角度拖拽排序、角标细化、side/base 联动) | ✅ 已上线(角标细化 + 级别预设微调 + 拖拽排序 + side/base 联动) | | P2 | 多成员体验(P02 身份切换下拉 / P09 老用户自动回填) | ✅ 已上线 | | P3 | 健壮性(G07 轮询 60s 守卫 / G06 raw_text 截断) | ✅ 已上线 | | P4 | hero 治理(G08 取最近标记 / G09 兜底)+ 移动端友好化(F27/F28) | ✅ 已上线 | | P5 | 运维加固(定期备份 / 探活 / 静态资源长缓存) | ✅ 已完成(nginx 静态长缓存已实测生效;恢复演练 DRY-RUN 通过。真实 `--apply` 会 `rm -rf /data` 覆盖全部家庭数据,**2026-09-14 已决定不做**) | | P6 | 全新 UI IA 重构(四界面:时光 / 荣耀 / 共建 / 传承) | ✅ 已落地(2026-09-17 起;规划 9 项 9/18 全部上线):HonorView / CoCreateView / LegacyView + Home 四 Tab;C1 年度画册 / A2 长辈极简已落地;邀请码轮换与荣誉卡片打磨线上状态已由用户核实 | ### 历史变更去哪看 本文件只描述**当前状态**。各批次的功能明细、修复过程与 commit 号已迁至根目录 **`CHANGELOG.md`**(按日期倒序);其中 14 起故障的完整根因分析在 **`docs/incidents/事故档案.md`**。 | 日期 | 摘要 | |---|---| | 2026-09-21 | 照片**按拍摄时间自动整理**(EXIF → `taken_at`,两端零依赖手写解析;排序键统一 `COALESCE(awarded_at, taken_at, created_at)`,schema v11) | | 2026-09-17 | 时间线卡片补时间信封占位(列表/详情解锁过滤闭环);产出全新 UI v0 原型(四界面 IA,评审中) | | 2026-09-16 | 时间信封 C3 上线 + 排期重构(路由拆分 / 迁移账本 / like 去重 / CORS 收敛 / Home 拆分)+ 移动端排版修复 | | 2026-09-15 | 时区修复(容器 UTC → Asia/Shanghai)+ 荣誉 OCR 自动标题修复 + 存量标题回填 + 文档治理(AGENTS.md / CHANGELOG / 事故档案) | | 2026-09-14 | 详情页三连修;运维加固 P5 核销(nginx 长缓存实测生效、恢复演练 DRY-RUN 通过) | | 2026-09-11 | 存储抽象层 / 上传反馈补全 / 品牌图标「门与光」/ 身份失效自愈 / 重要瞬间手动优先 | | 2026-09-10 | 首页重设计 / 荣誉置顶 / 上传方案 B / 证件照入口图标 | | 2026-09-03 ~ 09-09 | V1 MVP 上线 / 荣誉 V3 / MinerU 双通道解析 / 备份恢复演练通过 | ### 已决策不做 - 本地 AI 模型(RAM/Tag2Text):关键词库 + 手动 caption 已够用,不再引入大模型。 注:证件照用的 HivisionIDPhotos(MODNet+MTCNN,纯 CPU)走**独立容器 + `--memory` 上限 + 客户端降级**, 实测常驻 115MiB、单次 0.99s,已上线——所以本地 AI 不是"一律否决",而是"按形态评估"。 - SSE / WebSocket:多端同步用 ETag/304 + 30s 轮询已覆盖。 - IndexedDB 离线优先:与 MVP 不成比例。 - 真鉴权(JWT/session):不做。身份仍是 `X-Member-Id` 声明式的,只收紧了「不认识的 header 一律拒绝、跨家庭一律拒绝」——**能防误操作与串号,防不住知道 id 的人**。要做真鉴权是独立一轮,不是补丁。 - 真实 `--apply` 恢复演练:会 `rm -rf /data` 覆盖线上全部家庭数据,2026-09-14 决定不做(每日备份 + 5 分钟探活已在线,非必需验证)。