线上可用 单人摄影档案系统 状态快照 · 2026-07-19

Stillframe
网站现状报告

从访客看到的摄影网站,到管理照片和相册的后台,再到服务器、数据模型与下一阶段扩展条件,一次说明当前系统究竟处在什么位置。

生产域名:liangmx.cn 数据口径:2026-07-19 13:21 CST 报告类型:代码 + 线上接口 + 服务器检查

Executive Summary

这是一个已经上线、可持续维护的摄影档案站,不再只是静态页面原型。

当前最准确的定位是:面向公众的静态摄影前台,配合一个受保护的单人内容后台。它适合当前 53 张照片、4 个相册和单管理员场景,但还不是多用户通用 CMS。

  • 公网状态HTTPS 正常
  • 内容发布后台保存后静态重建
  • 照片组织二级相册 + 多次引用
  • 主要待办备份、安全收口、内容同步
4已发布相册目前全部为一级相册
53照片资源原图资源库总数
52相册引用1 张照片当前未被相册引用
16首页精选每个相册 4 张
0缺失预览图53 张照片的衍生图均完整
核心业务可用

首页、相册目录、相册详情、后台编辑、图片上传和发布链路均已具备。

能力领先于数据

系统支持二级相册与一图多相册,但生产数据仍是 4 个平级相册,尚未验证真实分类规模。

有一个立即风险

服务器 Redis 6379 端口可从公网连接,应优先关闭公网访问或绑定到本机。

System Logic

系统采用“后台管理动态数据,前台发布静态结果”的双层结构。

访客请求不经过数据库和后台业务逻辑,直接由 Nginx 返回构建好的 HTML 与图片;只有管理员编辑时才进入 Node 后台。这使浏览速度、稳定性和维护成本符合个人摄影站的实际需求。

为什么当前结构合理

网站规模小、更新频率有限、写入者只有一人。使用 JSON 目录而不是数据库,减少了常驻服务、迁移和备份复杂度;使用 Astro 静态构建,让公开页面没有运行时查询负担。

一次内容更新会发生什么

管理员在后台修改相册或照片关系,Node 服务先验证引用并更新目录,再调用发布脚本生成新版本。Nginx 的 current 链接切换到新版本,公开站点随后展示新内容。

关键边界

静态前台与持久照片库分开:发布新版本不会重复复制线上原图,也不会因为删除旧发布版本而丢失照片。

公开访客首页 / 相册 / 关于 / 响应式照片
管理员Basic Auth 后进入管理界面
Nginx + HTTPS静态页面直出;照片与预览图长期缓存;/admin 与 /api 反向代理
Astro 静态站构建期读取 catalog.json,生成公开 HTML
Node 管理服务仅监听 127.0.0.1:8787,处理编辑、上传、删除和发布
持久数据catalog.json + 原图目录 + 预览目录
版本发布不可变 releases + current 链接,保留最近 5 版

Public Experience

前台围绕“先看代表照片,再进入完整相册”组织。

首页不是传统文字介绍页,而是一条视觉入口:完整 Hero 照片、精选照片墙,以及每行一个相册的轮播摘要。照片卡片不显示文件名,轮播箭头和圆点只移动当前相册照片,不误跳转到详情页。

Stillframe 首页完整 Hero 区域
首页第一屏:Hero 保持照片完整可见,以摄影本身作为第一视觉信号。
首页相册轮播区域
桌面端相册行:左侧名称与简介,右侧为可交互的多图轮播。
Stillframe 手机首页
手机端:内容改为单列并保持图像优先,轮播与导航仍可操作。
页面 / 能力当前逻辑状态
首页 Hero使用站点设置中的 Hero 照片;响应式 WebP,保留完整构图。已完成
精选照片墙从各相册的精选照片聚合,按文件名去重;点击进入所属相册。已完成
相册列表一行一个相册;父相册与子相册都可展示;轮播拥有独立箭头、圆点与滑动逻辑。已完成
相册详情一级路径为 /albums/slug/,二级路径为 /albums/parent/child/已完成
图片加载480 / 960 / 1600 / 2400 四档 WebP;原图与预览图由 Nginx 长缓存。已完成
搜索 / 筛选当前相册量很小,没有站内搜索、标签筛选或物种检索。按规模再做
SEO 与分享已有基础标题和 description;尚缺 Open Graph、sitemap、robots 与结构化数据。待完善

Admin Workflow

后台将常用动作放回相册上下文,目标是让一次编辑尽量只走一步。

管理员不需要先维护一套照片库、再去另一个页面建立关系。创建相册时可直接导入文件夹;打开相册后可上传新照片、引用库内照片、移除照片、设置封面和精选。

创建相册填写名称、slug、简介,可选择父相册。
一次导入可空建,也可直接选择整个文件夹上传。
整理照片排序、选封面、选首页精选,或引用已有照片。
发布检查验证父子关系、图片存在性与公开状态。
保存发布重建静态站并切换线上 current 版本。

照片删除采用两层语义

从相册移除只删除这个相册对照片的引用,原始照片仍留在资源库,也不影响其他相册。

从照片库永久删除会先检查 Hero、相册照片、封面和精选等所有引用。存在任何引用时,后端返回冲突并拒绝删除;只有零引用照片才能连同衍生图一起删除。

这套逻辑解决了“一张照片属于多个相册”的问题

例如同一张白头鹎照片可同时出现在“拍鸟”和“白头鹎”中,磁盘只保留一份文件,目录中记录两次引用。

后台二级相册管理界面
功能验证截图:展示“拍鸟 / 白头鹎”父子相册结构。注意:这是测试夹具,不代表当前生产数据已经有二级相册。
后台能力操作方式系统保护
站点设置修改网站名称、描述、Hero 照片和导航。统一写入目录并触发发布。
新建相册可创建空相册,也可选择文件夹并一次导入全部 JPG。slug 唯一校验;上传分批处理。
二级相册创建或编辑时选择一个一级相册作为父级。最多两级;禁止循环或三级嵌套。
添加照片在相册内直接上传,或从资源库引用已有照片。相同内容按 SHA-256 复用,不重复存储。
相册内移除照片条目上的移除动作只解除当前相册关系。其他相册、Hero、原图均不受影响。
永久删除从照片库发起删除。后端检查全部引用;有引用则拒绝。
删除相册删除相册记录,不自动删除照片资源。删除一级相册时,其子相册提升为一级。
重建预览后台可为照片重新生成 JPEG 与 WebP 衍生图。原图保留不动,失败不提交半成品。

Content & Data

资源、相册和发布页面是三种不同对象。

理解这三个层次,就能理解为什么一张照片可以出现在多个相册、为什么从相册移除不会删掉原图,以及父相册如何汇总子相册内容。

照片资源

一份原图 + 一组衍生图,以文件名和内容哈希识别。它不天然属于任何相册。

相册引用

相册的 files 列表记录照片文件名。同一文件名可被多个相册引用。

公开页面

构建时将目录转换成首页与相册页面;父相册还会汇总已发布子相册照片并去重。

当前生产相册分布

雪后园林
14
室内光线
17
山路光线
10
海岸笔记
11
当前引用情况

4 个相册合计 52 个照片引用;资源库有 53 张照片,因此有 1 张资源当前没有相册引用。现有相册之间尚无重复引用,但系统已经允许重复引用。

相册照片精选日期
雪后园林1442026-01
室内光线1742026-02
山路光线1042026-03
海岸笔记1142026-04

二级相册现在怎样工作

  • 一级相册可以直接有照片,也可以只有子相册。
  • 父相册页面聚合自身照片和已发布子相册照片,并按文件名去重。
  • 子相册不能脱离未发布的父相册单独公开。
  • 首页相册列表允许同时展示一级和二级相册。

图片文件怎样生成

  • 每张原图生成最长边 1200 的渐进式 JPEG 预览。
  • 另生成 480、960、1600、2400 四档 WebP。
  • 浏览器根据视口与像素密度选择合适尺寸。
  • 原图仍可通过公开照片路径直接访问。

Deployment & Operations

生产环境健康,发布路径清晰,回滚与持久数据已经分离。

截至本次检查,Nginx 与 stillframe-admin 均为 active,API 健康检查正常,没有 failed systemd units。服务器资源仍有明显余量。

Web 服务

Nginx 监听 80/443,HTTP 自动跳转 HTTPS,TLS 1.2/1.3。

管理服务

systemd 托管 Node,绑定 127.0.0.1:8787,失败自动重启。

证书

Let's Encrypt,覆盖 liangmx.cn 与 www,有效至 2026-10-15,自动续期计时器正常。

磁盘

根分区使用约 5.7 / 40 GB,约 16%,当前容量不是瓶颈。

内存

使用约 691 MiB / 1.6 GiB;静态前台降低了常驻内存需求。

服务加固

NoNewPrivileges、PrivateTmp、ProtectHome、ProtectSystem 已启用。

发布目录

/var/www/stillframe/releases 保存不可变发布版本,/var/www/stillframe/current 指向当前版本,默认保留最近 5 版。

持久目录

/var/lib/stillframe/catalog.json 保存目录;photospreviews 保存原图与衍生图。它们不随发布版本删除。

后台代码

/opt/stillframe/app 保存应用代码。Nginx 仅把受 Basic Auth 保护的 /admin//api/ 转发到本机 Node。

1. 上传应用同步源码与管理端,保留服务器持久内容。
2. 构建 releaseAstro 读取当前目录,生成新静态版本。
3. 原子切换 current新版本就绪后才切换,避免访客看到半完成状态。
4. 验证并清理重启后台、检查 API 和 Nginx,保留最近 5 版供回退。
回滚版本不等于数据备份

release 可以回退页面和应用代码,但 catalog.json、原图与预览图属于持续变化的持久数据。当前仓库没有发现自动定时备份脚本,因此应把这三类数据单独做异地或对象存储备份。

Risks & Gaps

当前没有阻断使用的功能缺陷,但有一项服务器暴露需要立即处理。

风险优先级按“外部可利用性、数据损失影响、维护成本”排列。P0 应立即处理,P1 应在下一轮维护完成,P2 可随增长逐步建设。

P0 · Redis 6379 当前可以从公网建立连接

服务器上的 Redis 监听在 0.0.0.0:6379,且从外部网络实测可连接;UFW 当前未启用。这很可能是遗留服务,不属于 Stillframe 必需组件。应立即在云防火墙关闭 6379,并将 Redis 绑定到 localhost;若已无用途则停用服务。

级别事项现状与影响建议动作
P0Redis 公网暴露6379 可从公网连接,扩大未授权访问和数据破坏风险。云安全组关闭端口;绑定 127.0.0.1;不用则停用。
P1持久数据无自动备份证据发布回滚不覆盖目录与照片,误删或磁盘故障可能造成不可恢复损失。每日备份 catalog + 原图;保留多版本并做恢复演练。
P1站内说明已经过时“关于”页仍描述纯静态原型,“报告”页仍写没有报告,与当前后台和生产部署不一致。更新公开文案,避免使用者误判能力。
P1后台是单账号 Basic Auth适合单人使用,但没有会话、角色、审计、CSRF 令牌和细粒度权限。保持单人时可继续用;增加编辑者前先升级认证。
P1缺少部分安全响应头已有 nosniff 与 Referrer-Policy,尚未观察到 HSTS、CSP、Permissions-Policy。逐步补齐,先在报告模式验证 CSP。
P2原图可公开直访访客若知道照片 URL,可下载完整原图;对版权与带宽有影响。明确是否允许;否则公开站只暴露大尺寸 WebP 或加水印版本。
P2只接受 JPGHEIC、PNG、TIFF 等工作流需要先手工转换。有真实需求时再做导入转码,避免扩大处理面。
P2SEO / 分享信息不完整缺少社交分享图、sitemap 和结构化数据,搜索发现能力有限。补 Open Graph、canonical、sitemap、robots。
P2两级结构固定适合“拍鸟 → 白头鹎”,不适合无限层级或复杂标签体系。优先增加标签而不是继续加深目录层级。

Extension Roadmap

下一步不应先重写系统,而应先把现有系统变得可恢复、可发现、可扩容。

当前架构与规模匹配。只有当照片量、编辑人数或查询复杂度发生实质变化时,数据库和对象存储才会带来净收益。

现在:安全收口

关闭 Redis 公网入口;建立目录与原图自动备份;更新过时的关于和报告页面。

近期:内容可发现

正式录入二级相册;增加标签、拍摄地点、物种等字段;补充 SEO 与分享元数据。

增长期:媒体交付

图片迁移到对象存储与 CDN;增加缓存失效策略;选择是否隐藏原图。

协作期:后台升级

当出现多编辑者时,再引入账号体系、角色、审计日志、数据库与任务队列。

继续沿用当前架构的条件

  • 主要由一人编辑,更新频率不高。
  • 照片仍在数千张以内,目录文件可快速读写。
  • 分类以两级相册和少量标签为主。
  • 每次更新允许进行一次静态重建。

考虑数据库 / 对象存储的信号

  • 多位编辑者同时操作,需要权限和审计。
  • 照片达到约 5,000 张以上,筛选与批量操作明显变慢。
  • 需要复杂检索、EXIF 查询、标签组合或公开 API。
  • 源站带宽成为瓶颈,需要 CDN 和自动图像服务。
建议的下一轮工作顺序

1. 关闭 6379 公网访问;2. 建立并验证自动备份;3. 更新站内说明;4. 用真实“拍鸟 → 白头鹎”数据运行二级相册;5. 再根据检索需求设计标签,不急于迁移数据库。