CHANGELOG

更新记录

LitePic 各版本的更新说明。

v3.7.0
2026年7月30日

多用户模式与安全加固

  • 可选邀请制 / 开放注册、OAuth、配额与内容归属(默认关闭)
  • 修复统计页门禁、私密相册所有者、上传非 JSON 响应、登录态/CSRF
  • 宝塔兼容 shim(/gallery/ 等)

详见 CHANGELOG.md

Full Changelog: https://github.com/gentpan/LitePic/compare/v3.6.2...v3.7.0

v3.6.2
2026年7月27日

Added

  • WebDAV 远程存储客户端 — 设置 → 存储可选 WebDAV 网盘后端,与 R2/S3 同级支持「远程备份 / 云端存储」;迁移 018_webdav_client_storage。

Removed

  • WebDAV 服务端 — 移除 /dav 挂载、/files 列视图与相关服务端协议栈;LitePic 不再对外提供 WebDAV。
v3.6.1
2026年7月26日

Added

  • 公开相册主题二 · 瀑布流 — 可切换宫格 / 瀑布流;瀑布流为 sabi 式马赛克(有大有小、黑底间隙、圆角),迁移 017_albums_theme。

Changed

  • 图片请求 Topundefined样式 — 金银铜名次、格式色标、全站占比,去掉冗余路径行。
  • 公开相册淡入 — 瀑布流 / 宫格保留错落淡入与悬停放大。
v3.6.0
2026年7月26日

Added

  • WebDAV 网络磁盘 — 挂载点 /dav,相册即文件夹,「未分类」与只读「按日期」视图;完整 DAV class 1+2(含 LOCK)。
  • 三种登录凭据 — 专用用户名密码、管理员密码、API Token(ltp_…)。
  • 设置页 WebDAV tab — 分区布局、开关、挂载地址复制、打开文件浏览。
  • 文件浏览页 — /files Finder 式列视图;拖拽移动 / Alt 拖拽复制。
  • 客户端兼容 — Finder / Windows 垃圾文件吸收、Win32 PROPPATCH、配额属性。

Changed

  • 图片删除统一走 ImageDeleter;WebDAV DELETE 尊重硬链接引用。
  • 文件浏览列表只用缩略图,不再用原图兜底。

Fixed

  • 「按日期」漏查 has_thumbnail 导致卡顿。
  • Finder 连接兼容(charset=、Content-Type、/dav 压缩与 Alt-Svc)。
  • Junk 路径 LOCK 500;相册 MOVE 失败回滚。
  • 设置页 WebDAV / Telegram 无法保存。
v3.5.1
2026年7月26日

Changed

  • 在线更新改为精确同步 — 受管目录(api/、app/、assets/、static/favicon/)覆盖后会删除新包中已不存在的旧文件;受管根文件若新包已移除也会删掉本地副本。数据/配置/上传目录仍受保护。同步逻辑放在包内 update_sync.php,安装时优先执行新包规则。版本检测仍优先 litepic.io/version.json,GitHub 兜底。
v3.5.0
2026年7月25日

Added

  • 图片扩展一键启用 — 设置页按当前探针(系统 / PHP / Web)生成 apt 命令;新增 bin/enable-image-ext.sh(识别 FrankenPHP ZTS、ProtectSystem 命名空间);支持 sudoers 授权后在网页一键安装并延迟重启。
  • 设置热读 — 压缩 / 转换 / 水印 / 保留原图等运行时改为 Config::liveBool / liveString,FrankenPHP worker 内保存后立即生效,无需等进程重启。
  • 公开相册体验 — 网格按每页张数自动行列(约 4:3)、视口铺满、底栏随滚动显示;分页选项为undefined/undefined/ 48。

Changed

  • 上传上限 — 单文件上限跟随 PHP / Caddy 运行时;单次队列固定 100、并发固定 3;设置页去掉可改但实际不改服务器的表单项,改为展示检测值。
  • 设置页深色模式 — 统一 shell / 抬高层背景与资源占用、环境信息卡片层级。
  • CPU 负载展示 — 空闲显示「空闲」、极低负载用更高精度;load 读取增加 /proc 与 snapshot 回退。

Fixed

  • 跨 Tab 保存冲掉开关 — 「基础」等 tab 保存时不再把图片处理 / Telegram 等未提交的 checkbox 写成 false。
  • 图片处理队列 — ImageProcessor 正确尊重任务里的 compress 标志;转换优先时与设置页互斥一致。
  • 一键启用 ZTS 扩展 — 逃出 systemd ProtectSystem 只读 /etc,正确写入 /etc/php-zts/conf.d/。
  • 服务器信息深色样式 — 环境信息与资源占用卡片对比度、图标与层级冲突。

完整说明: CHANGELOG.md

v3.4.7
2026年7月23日

Changed

  • 组件 CSS 迁移到 Tailwind @apply — 保留语义 class(.img-card、.drop-zone 等)与渐变/毛玻璃/伪元素/关键帧等手写规则;去掉与 @apply 重复的模板 utility。
  • 设置「环境信息」图标 — 元信息卡片图标改为左对齐的固定正方形(36×36),避免被拉成竖长 pill。

Fixed

  • 移动端底栏避让 — 页脚、批量操作条、批量进度卡避开底部导航与 safe-area-inset-bottom;能力网格改为断点响应(大屏undefined→ 平板undefined→ 窄屏undefined→ 极窄 1)。
v3.4.6
2026年7月23日

Changed

  • 系统中文字体与首页背景 — 统一中文字体栈;首页背景改为 static/images/background.webp(源码即配置,不再走设置上传覆盖)。
  • 部署适配 — bin/deploy.sh 与 126.uz / FrankenPHP 场景对齐;清理旧 JPG 背景与无用 favicon 产物。
v3.4.5
2026年7月15日

Changed

  • README 对齐 FrankenPHP 部署 — 修正默认密码登录表述、本地 :8080 地址、worker cron、build:js、目录树;.user.ini 改为示例模板,真实文件不再入库。
  • 保存按钮加载态 — 点击保存时改为圆形 spinner,不再旋转软盘图标。

Fixed

  • 设置保存「安全令牌无效」 — CSRF 优先绑定 ADMIN_SESSION_SECRET(与登录 cookie 同信任域),避免 PHP session cookie 在 CDN / FrankenPHP / Secure 不一致时丢失导致误判;同时认 X-CSRF-Token,改密后刷新页面令牌。
v3.4.4
2026年7月15日

Changed

  • 默认推荐 FrankenPHP — 新增根目录 Caddyfile(经典模式,对齐原 nginx 敏感路径拒绝 / 上传上限 / try_files 兜底);README 环境要求改为优先 FrankenPHP,Nginx 配置保留作可选。

Fixed

  • 后台 Web 服务器显示「未知服务器」 — ServerInfo::webServer() 原先只认 Nginx/OpenResty;FrankenPHP 的 SERVER_SOFTWARE 为纯字符串 FrankenPHP(无 Name/x.y),导致误判。现同时认 SERVER_SOFTWARE / SAPI / phpversion('frankenphp') / frankenphp_* 函数,并回填版本显示;设置页轮询也会刷新该卡片。
v3.4.3
2026年7月15日

Changed

  • 上传 / 路由 / Worker 精简 — 上传服务与响应后 detach 逻辑收敛;移除 PHP 内置服务器 router.php,文档与部署统一指向 Nginx;CSS 组件层清理冗余样式。
  • 上传并发上限 — UPLOAD_MAX_CONCURRENT 上限调整为 20(默认仍为 3)。

Fixed

  • CDN 缓存鉴权重定向 — 动态页与 API 统一 Cache-Control: no-store;新增 HttpCache / RequestContext,Passkey 与登录限流正确读取 X-Forwarded-Proto 与真实客户端 IP,避免边缘缓存导致已登录用户进不了上传页。
  • 系统信息公网 IP — NAT/CDN 架构下 serverIp() 优先通过云厂商元数据/外部服务取公网 IP(带缓存),不再误显内网地址。
  • 部署脚本迁移用户 — bin/deploy.sh 迁移步骤跟 LITEPIC_OWNER 提取 web 用户(兼容 www / www-data 等),并恢复脚本可执行权限。
v3.4.2
2026年6月3日

Fixed

  • AVIF / WebP 能力检测漏掉 Imagick — 系统状态「AVIF 支持」徽章和导入/上传「自动转 AVIF」开关原本只检测 GD 的 imageavif();在「GD 没编 libavif 但 Imagick 支持 AVIF」的服务器上误报「未启用」并强制关闭自动转换(实际转换器是 Imagick 优先、能正常产出合法 AVIF)。ServerInfo 的 avif/webp 检测改为同时认 Imagick queryFormats(与 heic 一致)。
v3.4.1
2026年6月3日

Fixed

  • 更新检查结果被缓存导致检测不到新版 — /api/v1/update/check 响应未带禁缓存头,浏览器/前置 CDN 会把「最新版本」结果缓存住(典型:站点挂了 CDN 时,旧的 latest 被长期缓存,后台一直显示旧版、「立即更新」点不动,误以为是 GitHub 限速/网络问题)。端点改为强制 Cache-Control: no-store, no-cache,前端检查请求加 cache: no-store + 时间戳破缓存参数,确保每次都拿实时结果。

升级: 后台「设置 → 检查更新 → 立即更新」即可;若站点前置 CDN 一直显示旧版,请在 CDN 给 /api/* 加不缓存规则,或在源站直接运行更新器。

v3.4.0
2026年6月3日

Added

  • 相册封面 — 相册编辑页每张图 hover 出现「设为封面」星标,点击即设为封面(当前封面高亮边框 + 「封面」角标,复用 update 接口的 cover_filename)。未显式设封面时,AlbumRepository 用关联子查询派生 cover_effective(相册第一张图)兜底,相册列表页和公开页不再显示空占位。
  • 公开相册沉浸式重构(参考 TimePlus) — 公开相册页 /a/<key> 改为独立全屏体验:隐藏站点导航,照片墙全幅铺满、无缝粘连(gap: 0);移除顶部头部,改为底部黑色磨砂 fixed 信息条(backdrop-filter,显示相册名 + 张数/日期 + 版权)。网格缩略图加载淡入;点图灯箱支持加载转圈 → 缩放放大 + 淡入(参考 poptrox 动效)、左右翻页、键盘 ← → Esc、标题/日期说明、模糊深色背景。
  • 批量转换「保留原图」开关 — 批量转 WebP / AVIF / JPG / PNG 的确认弹窗新增「保留原图」开关(默认保留),关闭则每张转换成功后自动删除原图(复用现有删除逻辑)。DialogManager.showConfirmDialog 支持可选 toggle 并回传状态。
  • 大图本地 Imagick 压缩兜底 — mode=tinypng 时,超过 5MB 的大图直接走本地 Imagick(TinyPNG 对大图常超时),且 TinyPNG 任何失败/超时也自动回退 Imagick,保证大图也能压缩。
  • 数据统计 v2 图表 — 清爽仪表盘风格:统一品牌配色主题(替换 Chart.js 出厂色)、极淡网格、圆角深色 tooltip、平滑折线、隐藏坐标轴边框。月度=纯色面积图、年度=直角柱、类型=环形、大小=饼图;两图等高等大、统一右侧分类图例。

Changed

  • 图库挑选器交互 — 相册编辑页「从图库挑选」改为整图点击即选中(去掉「选中」按钮),选中用品牌色高亮边框 + 「✓ 已选」角标;网格undefined张/行(平板undefined/ 手机 4),默认加载undefined行(32 张),「加载更多」再加undefined行。
  • 批量进度 toast 改undefined列布局 — icon | 标题+数字 | 百分比 | 关闭(✕),百分比移到右侧不再单独占行,新增可手动收起的关闭按钮。
  • 压缩失败返回明确错误 — 单图压缩失败时返回可读的 502(含压缩模式与体积提示),不再被脱敏成通用「服务器内部错误」500。

Fixed

  • 相册创建/列表经 PJAX 进入时操作失效 — album_edit.php / albums.php 的内联 <script> 原本在 [data-pjax-container] 之外,PJAX 只重跑容器内脚本,导致经 data-pjax 链接进入时表单 submit 不绑定 → 退回原生 GET、相册创建不了。脚本移入容器内修复。
  • 图库挑选器空白无法选图 — /api/v1/list 返回 {data:{items:[...]}},前端原本读 data.data(对象)→ 列表永远为空;改读 data.data.items,并把请求参数 limit 改为接口实际使用的 per_page。
  • 批量上传文件名溢出容器 — .progress-item 为 grid,网格子项默认 min-width:auto 不收缩,长文件名撑破容器;.progress-header/.progress-status 加 min-width:0 让省略号截断生效。
  • UPTIME 配色与默认范围 — 系统 uptime 路径下,建站(开机)之前的时段标记为「无数据」灰色而非「离线」红色且不计入在线率;is-no_data 类名与 JS 对齐修复无数据段显示绿色;默认范围随数据量递增(>30 天→90D / 满undefined天→30D / 不足→1D)。
  • 设置页 TinyPNG 表格 — 表头与状态列不再被挤成两行(nowrap),操作列「禁用/删除」按钮并排。
  • 数据统计两图大小不一 — 移除遗留的 #typeChart max-height:260px 覆盖(早期给已删除的占比明细列表留位),类型环形与大小饼图恢复等大。

Tooling

  • JS 构建管线 — 新增 npm run build:js(esbuild --minify --charset=utf8),bin/deploy.sh 部署时一并重建 main.min.js。此前 main.min.js 与源码 main.js 脱节(未真正压缩、缺当前组件),生产长期在跑旧 JS;现已真正压缩(231KB → ~132KB)并随部署自动同步。main.min.js 自此为构建产物,请勿手改。
v3.3.8
2026年5月29日

Added

  • 上传限制重新回到后台可配置:单文件上限、单次队列数量上限、上传并发数统一由设置页管理,并同步写入 .user.ini。

Changed

  • 批量上传默认并发调整为 3,延长上传超时,减少大批量图片上传时的连接中断。
  • 批量上传进度刷新不再反复重建队列 DOM,降低大量图片队列下的浏览器负担。
  • 413 / 连接中断上传错误提示更明确。

Fixed

  • 修复登录态缓存导致首页误判未登录的问题。
  • 修复设置页 AJAX 异常时只显示“服务器返回格式异常”的问题。
  • 修复 UPTIMEundefined天 /undefined天切换被缓存影响的问题。
v3.3.7
2026年5月14日

[3.3.7] - 2026-05-15

Added

  • 图库卡片文件名内联重命名 — 双击 .img-name 进入编辑态(contenteditable),Enter 保存,Esc 取消。后端新 action rename,只改 images.original_name 列,磁盘上的随机 hash 文件名 + 老链接 + 远程同步 key 都不动。扩展名始终保留原始的(用户输入的后缀会被剥掉)防 MIME 漂移。文件名清洗复用 Telegram caption 的白名单:剥目录段 + 去 control / 路径分隔符 / shell 元字符,最长undefined字符。事件在 document 上代理,所以 PJAX 重渲染后的新卡片自动获得行为。

Tooling

  • bin/deploy.sh 一键部署脚本 — 流式 tar 推 + 服务器端快照 + 维护模式 + 触发迁移 + HTTP 自检 + 一键回滚命令。tar excludes 同时挡 macOS 元数据(._*、.DS_Store)和站点状态(data/、uploads/、logs/、.env、.user.ini、.htaccess)。支持 --dry-run / --skip-build / --skip-snapshot。全部参数 env var 化(LITEPIC_HOST / USER / KEY / REMOTE / OWNER / URL)。背景:之前手动 tar | ssh tar 推到 Linux 时,BSD tar 的 pax 扩展头被 GNU tar 转成undefined个 ._FILENAME 影子文件落盘,包括 ._index.php / ._worker.php 这种会被 nginx 当静态文件 serve 出去的。新脚本同时设 COPYFILE_DISABLE=1 防 BSD tar 写元数据,部署前还 SSH 一次兜底清掉服务器残留 ._*。
v3.3.6
2026年5月14日

[3.3.6] - 2026-05-15

集中修复 v3.3.4 引入的安全 + 并发问题。整轮代码审查共发现undefined个 P0 /undefined个 P1 /undefined个 P2,本版本全部修复并加配套迁移 + worker 兜底清理。

Security

  • /i/<filename> 现在受相册可见性约束 — 私密 / 密码相册里的图片不再能通过直链绕开密码门。ImageServeService 新增 isAlbumAccessAllowed() 闸门:图片不在任何相册 / 至少在一个 public / unlisted 相册时正常服务;只在 private 相册时仅管理员可见;只在 password 相册时检查 lp_album_<key> HMAC cookie。返回 404(而非 403)避免攻击者通过响应码枚举受限文件名。
  • Telegram webhook 三层防御真正各自生效 — 之前 header secret 在 header 缺失时直接通过("三层"实际只有两层),URL secret 校验在 feature gate 之前所以禁用部署能被指纹识别,from.id 完全可由攻击者伪造。本版本把 URL secret + header secret + feature gate 全部串行化、统一返回undefined+ 无 body,把 enabled / disabled / bad-secret 三种状态压成同一种响应。
  • Telegram 下载加 size cap — TelegramApi::downloadFile 现在用 CURLOPT_MAXFILESIZE + CURLOPT_PROGRESSFUNCTION 双重防护,白名单内的攻击者也无法借 image/png MIME 标签的CURLOPT_PROGRESSFUNCTIONGB document 把 sys_get_temp_dir() 撑爆。默认上限继承 MAX_FILE_SIZE。
  • UploadService::storeFromPath() 加路径白名单 + 拒绝 symlink — 之前任意可读路径都能被吞,一个未来调用方不小心传了 $_POST['path'] 就成任意文件读取。Telegram 调用方现在显式传 [sys_get_temp_dir()],默认空数组也会回退到 tmp 目录而非"放行一切"。
  • Webhook 注册成功 banner 不再泄露 URL secret — Webhook 已注册,URL: …/webhook/abcd…1234 替代原来的完整明文 URL,view-source / 浏览器历史里都看不到完整 secret 了。

Fixed (correctness)

  • 导入队列的 row-claim 真正原子化 — ImportQueueRepository::nextBatch() 用 UPDATE ... WHERE id IN (SELECT ... LIMIT) 一次性把 pending 行 flip 到 processing 并打上 worker_id,然后只 SELECT 自己标记的那批。in-request shutdown drain 和 cron worker 同时跑时不会再双倍处理。新增 reclaimStale() 在每轮 drain 开头把 >10 分钟还在 processing 的行还回 pending(覆盖 worker 进程中途死亡的孤儿行)。
  • 同步缩略图加 wall-clock + 像素双闸门 — ThumbnailService::create() 拒绝 >undefinedMP 的图(那些走异步),createWithImagick() 设置 Imagick::RESOURCETYPE_TIME=8s + MEMORY=256MB + MAP=512MB。之前一张多页 TIFF 能让上传请求跑 30s+ 直接撞 XHR timeout,前端报失败但服务端记录已写入 → 留下"幽灵"图片。现在undefined秒做不完直接 fail,异步 worker 接手。
  • 缩略图 alpha-skip 改用 MIME 而非扩展名 — 之前 transparent.png 改名 .jpg 后,thumbnail 跳过 alpha 剥离 → 输出黑底。现在用 finfo MIME 判定。
  • Telegram /newalbum,/use 加 update_id dedupe — 新表 telegram_seen_updates 通过 PK 上的 INSERT OR IGNORE 做幂等闸门。网络抖动导致的 Telegram 24h retry 不再创建重复相册。Photo 上传本身已经有 SHA1 dedupe,这次覆盖剩下的 mutating 命令。
  • Telegram tempfile 用 try/finally 清理 — 之前 storeFromPath 在 Imagick OOM 时抛 throwable,后面的 @unlink($tmp) 永远跑不到。/tmp 残留垃圾在长期运行的主机上会累积。
  • Telegram caption-derived filename 加 sanitize — basename() + 去 control / 路径 / shell 元字符 +undefined字符截断。文件存盘名仍由 PathService::generateFilename() 生成,这里护的是 images.original_name 列在管理 UI 里的 XSS 表面。
  • /a/<id> 在 php -S 下不再 404 — router.php 跟 app/Http/router.php 的正则现在一致:^/a/(\d+|[a-z][a-z0-9-]{0,49})/?$ + $_GET['album_key'](canonical)。nginx 路由和 PHP 内置服务器路由不再分裂。
  • 迁移undefined用 regex 重写 + 写后断言 — 不再依赖字面量空白匹配。之前迁移undefined一改格式,012 就会静默 no-op,slug 仍是 NOT NULL,后续插入失败。现在用 /\bslug\s+TEXT\b[^,\n)]*?\bNOT\s+NULL\s*/i 匹配,写完检查 PRAGMA table_info 强行抛错。
  • 相册访问计数:从 cookie-only 改成 IP + cookie 双层 — 新表 album_visit_log(album_id, ip_hash, bucket_at) 作为 source of truth,cookie 退居 UX 快路径。隐身窗 / 清 cookie 不能再无限刷计数。IP 用 sha1(ip + ADMIN_SESSION_SECRET) 存,不留明文 IP。

Changed (performance / hygiene)

  • LivenessTracker::recordOnce() 按需写入 — 主机 /proc/uptime 可读时直接 short-circuit(uptime UI 已经走 OS 数据,无需写表了),每请求一次的 INSERT 减为 0。沙盒主机(BT 锁 /proc / Windows-PHP)仍正常写,后续 series() fallback 也仍工作。
  • ImageInfo::preload() 批量预热 — public album / album_edit 渲染undefined张相册之前 =undefined次 SELECT ... WHERE filename = :f round-trip。新增 preload(array $filenames) 走一条 IN (...) 全拉回来塞进 per-instance 缓存。两个页面已切换到新流程。
  • ServerInfo::databaseSummary() 加 per-process 缓存 — 设置页一次渲染期内重复调用不再每次对每表跑 COUNT(*)。新请求总是看到新快照。
  • /api/v1/uptime 加 60s 浏览器缓存 — 数据本来就是分钟粒度,后端无谓重算。
  • 浏览器并发上传undefined→ 8 — 跟 PHP-FPM warm workers 对齐,避免 9-20 号 XHR 在 accept 队列里等到 timeout。
  • worker.php 清理三张小表 — 每次 cron 跑完 drain 后顺手清:liveness_pings > 90d、telegram_seen_updates > 24h(Telegram retry 窗口)、album_visit_log > 1h(30min dedupe bucket + 安全裕量)。三张表都不再无界增长。

UI

  • 深色模式 Toast 取消渐变 — 顶部 notification-process / convert / compress 和右侧 notification-container toast 在深色下都改成纯深色底(#0f1116),只保留左侧 4px accent 竖条 + icon 的素色识别。之前的 135deg / 90deg 渐变在 OLED 屏上发糊,侧边 toast 还有个 bug 在深色下渐变到 #ffffff 白色。浅色模式渐变完整保留。修了一同处:侧边 toast 在深色下的标题/副本/关闭按钮字色从黑字切到浅字(之前在白色渐变末端能勉强读到,改纯深色底后必须切)。

Infrastructure

  • .user.ini / nginx-litepic.conf 与 CHANGELOG 3.3.4 宣传值对齐 — 之前实际是 upload_max_filesize=20M / client_max_body_size 50m,文档却写 200M。现在统一改成:upload_max_filesize=200M、post_max_size=220M、max_input_time=600、client_max_body_size 200m、client_body_buffer_size 32m、client_body_timeout 600s。
  • 新迁移 014_idempotency_tables.php — 一次性创建 telegram_seen_updates + album_visit_log 两张小表,worker 自带 retention。
  • 新仓库类 — app/Repository/TelegramSeenUpdateRepository.php、app/Repository/AlbumVisitLogRepository.php。
  • 新 helper — app/Repository/AlbumImageRepository::visibilityFor()、app/Repository/ImageRepository::findMany()、app/Service/Image/ImageInfo::preload()、app/Service/Upload/UploadService::pathInsideAny()、app/Service/Stats/LivenessTracker::osUptimeAvailable()、app/Repository/ImportQueueRepository::reclaimStale()。
v3.3.4
2026年5月8日

Added

  • Telegram 机器人集成 — 全新 设置 → Telegram tab,绑定一个 BotFather 拿到的 Bot Token + 白名单用户 ID 后,机器人即可:
  • 直接发图片(或图片文档)到机器人 → 自动上传到 LitePic,回复公开链接
  • /list [N]、/albums、/album <key>、/newalbum <名称>、/use <key>、/me、/help 一整套指令
  • 三层安全:URL secret(32-hex,一键轮换) + Telegram secret_token header + TELEGRAM_ALLOWED_USER_IDS 白名单
  • 每用户「默认上传相册」状态(新表 telegram_user_state)
  • 新文件:app/Service/Telegram/{TelegramApi,TelegramHandler}.php、app/Repository/TelegramUserStateRepository.php、api/telegram.php、迁移 013_telegram_settings.php
  • 底部批量进度卡 — assets/js/main.js ImgEt.BatchProgress 单例 + 新 CSS。批量压缩 / 转换 / 删除时,顶部 toast 只发状态广播,底部固定卡显示实时 N/M + 进度条 + 百分比;三色 variant(绿/紫/红)对应三种操作。
  • UploadService::storeFromPath() 公共方法 — 服务端 ingest 路径,把已经在磁盘上的文件走完整上传流水线(供 Telegram 用,未来也可供 CLI 导入)。
  • nginx 详细 timing log_format — wall_time + upstream_time 字段,以后排查上传性能问题不用靠猜。

Changed

  • 相册 URL 默认数字 ID,slug 可选 — 迁移 012_albums_slug_nullable.php 通过 writable_schema 把 albums.slug 改成 NULLABLE。新建相册不填 slug → 公开 URL 是 /a/<id>(数字);填 slug → /a/<slug>。Router、Controller、Repository 全部支持 findByKey($key) 双模式。新增 AlbumService::urlKey($album) 作为单一 URL 构造源。
  • 上传性能 10× 优化 — 综合多层调优,典型 2-3MB 照片从「100 秒级」体感降到「1-3 秒级」:
  • PHP-FPM pm = ondemand → dynamic(8 worker 常驻,消除 burst 冷启动 50-150ms)
  • ThumbnailService Imagick 加 jpeg:size DCT-domain 降采样 hint + JPEG 跳过 mergeImageLayers / setImageAlphaChannel(4032×3024 大图缩略图 794ms → 74ms,10×)
  • 同步生成缩略图 — UploadService::storeFromPath / handleSingle 在响应内做完缩略图,响应一返回前端立刻显示真实 thumbnail URL,无需轮询;失败自动退回到异步队列
  • getimagesize 透传给 ThumbnailService::create($id, $force, $info) 避免重复读图片头
  • LivenessTracker::recordOnce() 改 1/8 抽样,burst 上传时 SQLite 写锁竞争 -87.5%(uptime 桶分辨率仍保持分钟级)
  • 浏览器并发上传 MAX_CONCURRENT: 3 → 20(自托管/局域网图床,带宽是自己的)
  • 后端处理状态轮询从 setInterval(2500ms) 改成指数退避 400 / 700 / 1100 / 1700 / 2500ms(缩略图典型 1-2 次内拿到 'done',总等待 <400 / 700 / 1100 / 1700 / 2500ms秒)
  • 新增 cron 兜底:每分钟跑 worker.php 处理队列(用户离开页面后还能继续 drain)
  • 基础设施门限 — PHP upload_max_filesize / post_max_size 50M → 200M,memory_limit 128M → 256M,max_input_time 60s → 600s;nginx client_max_body_size 50m → 200m,client_body_buffer_size 512k → 32m(32MB 以下完全在内存,不再 spool 到磁盘)
  • 删除相册 — 改用自定义 ImgEt.DialogManager.showConfirmDialog(danger: true),不再用浏览器原生 confirm(),跟删除图片走同一套样式。
  • 能力卡帮助图标 — ? 链接直接跳 litepic.io/docs#<anchor>,移除之前在应用内做但有 CSS 渲染问题的「一键启用命令」弹窗。文档统一在官网维护。

Fixed

  • 修复迁移 012 早期版本里 PDO->beginTransaction() 在 Migration runner 已开启的事务里抛 "There is already an active transaction" — 改用 writable_schema + schema_version bump 在已有事务里直接修改 sqlite_master。
  • 修复某些情况下 findByHashWithBackfill 在历史无 hash 图片很多时遍历整库 sha1_file 导致上传慢(本版本未改 API,但 sync thumbnail 的延迟提升让这个潜在风险显形 — 若用户报告慢可建议跑一次 backfill 命令)。

Infrastructure

  • 服务器侧调优(部署文档已更新):BT 面板用户建议 pm = dynamic,nginx client_body_buffer_size 32m,PHP memory_limit 256M,以及 cron * * * * * php /<root>/worker.php。
v3.3.1
2026年5月5日

Added

  • 程序自动更新:后台从 GitHub Release 下载 ZIP,只替换程序文件,保护 .env、.user.ini、.htaccess、data、uploads、logs、static/images。
  • 新增 /api/v1/update/check 和 /api/v1/update/install。

Changed

  • 版本号统一升至 3.3.1,页脚、版权说明和后台更新面板读取同一个 LITEPIC_VERSION。
  • 系统状态接口统一到 /api/v1/system/status。
  • 清理废弃背景上传样式、access.log 旧配置和 Docker 调度文案。

Validation

  • 全量 PHP 语法检查通过。
  • assets/js/main.js 与 assets/js/main.min.js 通过 node --check。
  • CSS min 产物已同步。
v3.2.0
2026年5月3日

LitePic v3.2.0

本次更新

  • README 完全重写,精简结构,聚焦核心特性与快速开始流程
  • 配置文件清理,移除冗余旧文件
  • 版本号升至 3.2.0

升级说明

查看 CHANGELOG.md 了解完整变更。

v3.1.0
2026年5月1日

主要新特性

异步处理流水线 — 上传请求把图片入库后立即返回,缩略图 / 压缩 / WebP / AVIF / 水印 / R2 同步全部走 SQLite 队列后台 drain。worker.php 可作为 docker compose sidecar 长驻或 cron 拉起,跟 in-request drain 共享同一数据库。ResponseDetacher 让 PHP-FPM / LiteSpeed 在响应发出后继续跑后处理。

Passkey / WebAuthn 登录 — 指纹 / Face ID / 硬件 key 无密码登录,支持注册多个凭证。自实现undefined行 CBOR 解码器和 ES256 签名验证,零 composer 依赖。

SQLite 数据库备份 — VACUUM INTO 在线热备,支持手动 / 定时调度 / 保留份数 / R2/S3 异地容灾 / UI 一键恢复。

残留数据清理 — 设置 → 数据库 tab 新增「扫描 + 清理」流程,5 类残留可选择性清理,绝不动磁盘文件 / 活动队列 / 设置 / Token / Passkey。

图库卡片右键菜单 — 重新生成缩略图 / 复制链接 / 下载原图、WebP、AVIF、缩略图 / 转换反向偏好格式(默认 WebP 时菜单显示「转换 AVIF」反之亦然)。其他位置右键仍是浏览器原生菜单。

自定义 URL 前缀 — 后台可把 \/uploads/\ 改成 \/img/\、\/photo/\、\/p/foo-bar/\ 任意单词前缀,全部经 \image.php\ 走访问统计。Apache、Nginx、OpenResty、Caddy、PHP \-S\ 五种部署方式都有等价配置随仓库分发。

Web 服务器自动检测 + 版本号 — 服务器信息 section 显示当前 Nginx / OpenResty / Caddy / Apache / LiteSpeed 类型 + 版本号;能力卡片(GD / ImageMagick / AVIF / WebP / 上传上限)未启用时带 \?\ 图标链到 litepic.io/docs 对应章节。

兼容性变化

  • 文件名格式:从 \uniqid() + '_NNN'\ 改成 \bin2hex(random_bytes(16))\undefined位十六进制。老文件名保持不变,只影响新上传。
  • 配置存储:所有后台开关从 \.env\ 移到 SQLite \settings\ 表。\.env\ 仍作为首次安装的初始默认值来源;装好之后改设置不需要重启。
  • 本地 \/docs\ 和 \/api\ 页面下线:完整文档迁移到 litepic.io/docs 和 litepic.io/api。
  • 首页背景:移除后台动态切换 UI,固定从 \static/images/background.jpg\ 读取。
  • 「最大上传大小」输入框删除:改成纯展示服务器实际允许的值;调大请改 PHP-FPM / Web 服务器配置(详见 docs)。

UI 优化

  • 设置undefined个 tabs 全部用路径化 URL(\/settings/<tab>\)+ PJAX 切换不刷整页 + Plan A 直角设计
  • 转换按钮按后台「转换优先格式」自动切换显示
  • 压缩 toast 显示实际调用的引擎(GD / TinyPNG / ImageMagick)
  • 页脚 Powered by LitePic shields.io 风格徽章(Ubuntu 字体 + 黑底品牌蓝)
  • Favicon 切到小米undefined同款 squircle 风格(n≈4 superellipse)
  • 多处图标 + 中文对齐错位修复(equal-height inline-flex 模式 + 1px 校准)
  • 图库分页箭头改用 FA 矢量图标(替代 \«‹›»\ HTML 实体)

完整变更见 CHANGELOG.md。

v3.0.0
2026年4月29日

Changelog

All notable changes to this project will be documented in this file.

[3.0.0] - 2026-04-29

Breaking Changes

  • CSS Architecture: Migrated from custom CSS modules to Tailwind CSS v4 with CSS-first configuration. All legacy assets/css/modules/*.css files removed.
  • Documentation Routes: Split docs.php into usage.php + api.php. Routes changed from /docs to /docs (usage) and /api (API docs).

Added

  • Tailwind CSS v4 build pipeline with @tailwindcss/cli and component-layer CSS architecture.
  • Gallery link in navigation bar for logged-in users (/gallery).
  • Custom scrollbar theming for WebKit and Firefox, following light/dark mode.
  • Favicon suite: apple-touch-icon, Android Chrome icons (192x192 / 512x512), favicon-16x16, favicon-32x32, and site.webmanifest.
  • Light/dark theme-aware logo switching via CSS custom properties (avoids Tailwind v4 Lightning CSS optimization bugs).
  • Scrollbar gutter stabilization (scrollbar-gutter: stable) to prevent layout shift.

Changed

  • Logo: Replaced SVG logo with PNG (logo.png / logo-dark.png) for better cross-browser rendering.
  • Footer layout: Reorganized into three-column layout—GitHub link on the left, centered copyright/stats/docs/API/login/theme-toggle row.
  • Navigation bar:
  • Guest: Home + Stats + Upload (CTA)
  • Logged-in: Home + Stats + Gallery + Settings + Upload (CTA)
  • Docs/API links moved to footer.
  • Home page hero card: Light mode now uses the same glassmorphism effect as dark mode (semi-transparent white gradient + backdrop blur).
  • Upload button colors: Fixed light-mode CTA button to use #0052D9 background with white text.
  • Documentation: Restructured usage guide intoundefinedchapters with AVIF/Passkey/fullscreen-upload coverage and environment config cheat sheet.

Fixed

  • Dark-mode selector optimization bug: Replaced html[data-theme="dark"] element selectors with CSS custom properties to avoid Lightning CSS dropping dark-mode prefixes.
  • Login panel display conflict: Removed HTML hidden class to prevent Tailwind v4 utility layer from overriding component layer.
  • Transform property conflict: Notification animations now use --tw-translate-x + translate property instead of transform, avoiding conflicts with Tailwind v4 independent transform properties.

[2.3.0] - 2025-03-28

Added

  • AVIF format support via ImageMagick.
  • Preferred format setting (WebP / AVIF) in settings panel.
  • Fullscreen upload mode.
  • Distro detection in system status.
  • Self-healing open_basedir sandbox.

Changed

  • UI overhaul with improved settings panel.

[2.2.0] - 2025-02-20

Added

  • WebAuthn / Passkey login support.
  • Docker support with Dockerfile and docker-compose.yml.

Fixed

  • Session headers-already-sent warning in Docker.
  • Root .htaccess php_flag engine off issue.
v2.3.3
2026年4月28日

The settings page now correctly reports OS, CPU cores, memory and uptime on hosts that wrap PHP in an open_basedir sandbox (宝塔/aaPanel/1Panel default config), and walks the operator through the one config tweak it can't make on its own.

Highlights

Distro detection

  • System version row now shows "Debian 13" + the right FontAwesome Brands icon instead of Linux 6.12.74+deb13+1-amd64.
  • Supported brand marks: Debian / Ubuntu / Fedora / CentOS / Red Hat / SUSE / openSUSE / Arch / Alpine. Anything else falls through to fa-linux.
  • Reads /etc/os-release when reachable; sniffs php_uname('v') / php_uname('r') for the brand + version when the file is sandboxed.

Sandbox-friendly metrics

  • Memory and CPU-cores now read /proc/meminfo and /proc/cpuinfo directly via @file_get_contents — no longer dependent on shell_exec, which most hardened PHP setups ban.
  • Uptime text is derived from $uptime_seconds (e.g. "2 天undefined小时") so it works without the uptime command.
  • is_readable() probes that leaked open_basedir warnings have been removed; @file_get_contents does the right thing on its own.

AVIF detection

  • Capability check now ORs Imagick::queryFormats('AVIF') with imageavif() (GD), so hosts with Imagick AVIF support stop falsely reporting "AVIF 未启用".

Self-healing setup banner

  • When the sandbox blocks /proc/{cpuinfo,meminfo,uptime}, the settings page renders a top banner with a 「一键修复」 button.
  • Clicking it appends theundefinedpaths to the site's .user.ini (auto-backup first), all done by LitePic itself — no ssh access needed.
  • Theseundefinedfiles are world-readable system info; whitelisting them costs nothing security-wise versus the misleading fallback numbers.
  • PHP-FPM caches .user.ini for user_ini.cache_ttl (default 300s), so the banner copy notes the 5-minute lag and the option to restart PHP-FPM for instant effect.

Graceful UX when sandboxed

  • Blocked metrics now show "受沙箱限制" instead of 4 MB / 256 MB (which was actually PHP process RSS, not system RAM) or 不可用 核 (null cpu_cores).

Other

  • Logged-in nav order swap: 统计 now sits before 设置.
v2.3.2
2026年4月28日

Patch release for hosts that restrict PHP via open_basedir (e.g. 宝塔面板 default).

What broke

The settings page surfaced a PHP warning the first time it tried to read uptime:

> Warning: is_readable(): open_basedir restriction in effect. File(/proc/uptime) is not within the allowed path(s)

is_readable() is not silenced by @, so the probe leaked the warning even though the next line already wrapped file_get_contents() in @.

Fix

Removed the redundant is_readable() probe in get_server_uptime_seconds() (functions.php). @file_get_contents('/proc/uptime') already returns false silently when access is denied, and the existing shell_exec fallback still kicks in.

Settings page now renders without the warning. Uptime simply shows N/A on hosts where neither /proc/uptime nor shell_exec is reachable — expected behavior under hardened sandboxes.

v2.3.1
2026年4月28日

Hotfix for a parse-time SyntaxError that broke the frontend bundle in v2.3.0 — login page failed to load with:

> Uncaught SyntaxError: Private field '#showConvertResult' must be declared in an enclosing class

What broke

ImageProcessor called this.#showConvertResult(data, format) and this.#addConvertedCard(data, imgCard), but neither method was declared in the class. The original #showWebPResult / #addWebPCard implementations were left orphaned — the AVIF refactor renamed the callers but forgot to rename the declarations.

Fix

  • Renamed #showWebPResult(data) → #showConvertResult(data, format)
  • Renamed #addWebPCard(data, imgCard) → #addConvertedCard(data, imgCard)
  • Threaded the format arg into the dialog title (so AVIF no longer shows "WebP" copy)
  • Rebuilt assets/js/main.min.js