删除不彻底的根因是库里 file_path 存了旧 Windows 相对路径(uploads\xxx.epub),Linux 容器里 os.path.exists 永远为假:
- 新增 _upload_file() 归一化路径(取文件名挂到当前 uploads 目录),读/删都走它,老库迁移的文件也能定位;文件删除挪到后台任务,失败不影响接口
- 删除后对 SQLite 执行 VACUUM,让 db 文件真正缩小
- 删除时一并清理 reading_progress
阅读位置原来只存 localStorage,换设备丢失:
- 新增 reading_progress 表 + GET/PUT /books/{id}/progress 接口
- 前端打开时优先取服务端位置(本地兜底并双端拉齐),翻页防抖同步到服务端,关闭时把防抖窗口内的最后一页立即刷上去