# 晨风书屋 — CHANGELOG

> **当前版本：V2.3.0** | 2026-07-12

---

## V2.3.0 — 2026-07-12

**服务器数据同步、封面修复与按变化备份**

- 修复批量补封面未持久化 `cover` 字段的问题，封面批量更新使用独立事务接口
- 封面查询移到同源服务器，优先豆瓣元数据并回退 OpenLibrary
- 新录入封面绑定到待保存书籍，不再依赖未定义的旧版 `dbPut`
- 分类修正限制为每批最多 10 本，并记录已核对状态，避免触发国图限流
- L9 收藏标签从浏览器本地存储迁入服务器设置表，支持跨设备同步
- 每天 22:00 比较数据库逻辑指纹，仅在数据发生变化时生成 SQLite 一致性备份
- 导入后的 912 本正式数据建立不可变基线，完整性和书架位置检查通过

## V2.2.1 — 2026-07-12

**管理员认证与生产数据保护**

- 管理员密码必须通过服务器 `/auth/verify` 验证，错误输入不会显示任何管理按钮
- 已保存的当前标签页会话在刷新时重新验证，401 会立即清除失效会话
- API 禁止浏览器和代理缓存，页面每次启动从服务器读取最新书目
- 发布前自动执行 SQLite 完整性检查和一致性快照，发布后核对完整性及记录数基线
- 每日备份携带数据库 SHA-256、完整性状态和记录总数
- 提高深浅主题文字对比度，统一页面底部名称和版本显示
- 左上角移除含义模糊的“已连接”，顶部右侧改为明确的网站服务器状态

## V2.2.0 — 2026-07-12

**手机扫码、移动管理与并发位置保护**

- 新增手机摄像头 ISBN 扫码入口，使用原生 `BarcodeDetector` 识别 EAN-13
- 手机扫码后只查询和填充书目，必须人工核对并点击确认，不再自动写入
- 摄像头权限拒绝、不支持识别、关闭窗口和页面进入后台均有明确状态并停止视频轨道
- 手机端支持管理员登录、录入、编辑、导入导出、统计等完整操作，录入弹窗适配小屏滚动
- 增加深色/浅色主题切换，选择保存在当前浏览器并在刷新后保持
- 服务器为书架位置增加唯一索引、范围校验和稳定的 `location_conflict` 错误码
- 新增位置冲突时刷新服务器数据并安全重试一次；批量重排支持事务内交换位置
- 新增书目检索与 DeepSeek 分类补全规划，明确模型只提供候选和分类建议
- DeepSeek Key 改为服务器独立环境文件，删除浏览器保存、输入和直连能力
- 完整 JSON 导出改为管理员权限，访客保持浏览、搜索和统计

## V2.1.0 — 2026-07-12

**服务器数据治理与旧版备份兼容**

- 兼容 V1 CSV、V2 JSON 和常见 IndexedDB 包装格式
- 桌面 2026-07-12 旧备份 912 条通过本地全量预检，实体位置原样保留
- 导入改为“前端预检 + 服务器复检 + SQLite 快照 + 单事务替换”
- 导出每次重新读取服务器数据，生成 schema 2.1.0 版本化 JSON
- 每日站点备份加入 SQLite 一致性快照和 SHA-256
- P09 增加 `--library-only` 隔离发布、校验和回滚边界
- 新增书舍数据管理与现行发布文档

---

## V2.0 — 2026-06-28

**云端迁移**

- IndexedDB 迁移到服务器 SQLite
- 新增 Flask REST API、访客只读与管理员写入模式
- 2026-06-30 源码从 P22 合并到 P09，P22 删除

---

## V1.12.15 — 2026-06-02

**修复：OpenLibrary 占位图根治**

- OpenLibrary URL 加 `?default=false`，无封面时直接返回 404 而非占位图
- 彻底解决尺寸检查无法拦截"合法尺寸但内容为空"占位图的问题

---

## V1.12.14 — 2026-06-02

**修复：豆瓣封面也可能返回小占位图**

- `tryDoubanCover` 拿到 URL 后用 `tryImg` 验证尺寸，占位图不再存入
- `fetchCover`（单书扫码流程）豆瓣部分同步加尺寸校验

---

## V1.12.13 — 2026-06-02

**修复：OpenLibrary 1×1 占位图被误存为封面**

- `tryImg` 和 `fetchCover` 加尺寸校验（宽高需 > 10px），过滤掉无内容的占位图
- 每次点击「补封面」前先清除已存的无效封面（`_purgeFakeCovers`），再重新抓取

---

## V1.12.12 — 2026-06-02

**修复：封面显示位置错误**

- 封面应在点击书脊弹出的详情面板（`openDetail`）中显示，而非编辑表单
- 有封面时在详情面板标题下方居中显示（最高 140px），无封面时不占位

---

## V1.12.11 — 2026-06-02

**Modal 封面显示**

- 点开书籍详情时，若已有封面图，在标题下方居中显示缩略图（最高 120px）
- 无封面时区域隐藏，不影响录入新书的表单布局

---

## V1.12.10 — 2026-06-02

**重复书提示改进**

- 扫到已录入 ISBN 时，弹确认框显示已有书的书名和位置
- 用户可选择"确定"再录入一本（同书多册），或"取消"跳过
- 取消后自动清空 ISBN 字段并聚焦，继续扫下一本

---

## V1.12.9 — 2026-06-01

**补封面批量抓取优化**

- 运行中点击「补封面」按钮可直接中止，不再弹错误提示
- 按钮运行中显示「停止 (x/total)」，明确进度与可操作性
- 每批完成后立即 `renderShelf()`，封面逐批显示无需等全部结束
- 中止与正常完成显示不同 toast 提示
- 保存逻辑优化：只对本批有封面的书执行 put

---

## V1.12.8 — 2026-06-01

**补封面并行批次 + 豆瓣 CORS 来源**

- 批量获取封面改为并行处理（每批 8 本）
- 新增豆瓣 CORS 代理作为来源 2（中文书覆盖更好）
- 每批完成后保存 IndexedDB，进度实时更新按钮文字

---

## V1.12.7（稳定版）2026-06-01

**修复：** `rebuildLayout()` 中旧代码块未清除导致 `const classes` 重复声明，引发 `SyntaxError`，页面完全无响应。

---

## V1.12.6 — 2026-06-01

**等比例预留分配算法（`proportionalAlloc`）**

- 新增 `proportionalAlloc(classes, totalCells)` 公共函数
- 两步算法：① 存量保底 `ceil(count/15)` ② 剩余格按比例分缓冲
- 确保总格数精确 = 78（不再出现 79 > 78 的溢出）
- Z 类（3本）→ 1 格 → **G13 最后一格（G13-L8）**
- `buildCellPlan()` 和 `rebuildLayout()` 共用同一算法

---

## V1.12.5 — 2026-06-01

**修复统计面板图表空白**

- 根因：顶栏 `<div id="statsBar">` 与统计 canvas `<canvas id="statsBar">` ID 重名
- `document.getElementById('statsBar')` 返回 div，`div.getContext('2d')` 抛 TypeError
- 修复：canvas 重命名为 `statsAuthorBar` / `statsPubBar`
- 修复作者提取：去除"著/编著/主编/译"后缀、括号内年份
- 修复出版社提取：去除年份后缀、"出版集团/出版公司"后缀

---

## V1.12.4 — 2026-06-01

比例分配初版（存在 allocSum=79 的 off-by-one bug，已在 V1.12.6 修复）

---

## V1.12.3 — 2026-06-01

**重排逻辑重写 + 多项改进**

- 重排放置改为顺序填入（去除"跳层"逻辑），彻底消除混放
- 溢出全局兜底：分类区满时找 G1-G13 任意空位，不留书在旧位置
- G14 L1 显示橙色"儿童"列标识，G15 L1 显示紫色"相册"列标识
- L9 底层支持点击编辑自定义标签（手办/杂志/手机盒等）
- 统计面板：移除月度趋势，保留作者 Top10 + 出版社 Top10

---

## V1.12.2 — 2026-06-01

**DeepSeek API 集成**

- 顶栏新增 🤖 按钮，设置/清除 DeepSeek API Key（localStorage 存储）
- 分类优先级：NLC → DeepSeek → 关键词匹配
- 国图失败后的所有数据源（豆瓣/OpenLibrary/Google）自动 await DeepSeek
- 无 ISBN 旧书手动录入时，🔍 搜索后也触发 DeepSeek 分类
- `fillBookData()` 新增 `skipAutoSave` 参数，等 DeepSeek 返回后再保存
- 新增 `applyClcBadge(clc, source)` 统一更新分类 badge

---

## V1.12.1 — 2026-06-01

**手动录入改进 + 混放检测**

- 书名字段旁新增 🔍 按钮，显式触发书名搜索（无 ISBN 时使用）
- `searchByTitle(explicit)` 参数控制触发条件
- 重排弹窗新增混放格子检测，列出所有 CLC 混放的格子名称
- 修复区域文字与坐标文字重叠：有 zone 时清空 `data-label`

---

## V1.12.0 — 2026-06-01

**统计面板重设计**

- 布局：2×2 网格（分类饼图 + 作者排行 + 月度趋势 + 出版社）
- 饼图改为甜甜圈图 + 侧边图例（分类名/数量/占比），不再把文字塞进扇区
- KPI 卡片新增：ISBN 覆盖率、书架利用率
- 出版社 Top5
- 月度录入趋势（近 12 个月）

---

## V1.11.9 — 2026-06-01

**区域可视化**

- 空格显示所属分类名标签（如"I 文学"）
- 所有格子带分类色极淡底色
- 区域首格带左侧/顶部竖线边框
- 有 zone 的空格不再显示无意义的坐标文字

---

## V1.11.8 — 2026-06-01

**布局排序修正**

- 删除硬编码 `LAYOUT_PLAN`
- `buildCellPlan()` 改为动态按 `CLC_ORDER`（A→Z）比例分配
- `allocateLocation()` fallback 限制在 G1-G13，不再进入 G14/G15
- `refreshData()` 每次重置 plan cache

---

## V1.11.7 — 2026-06-01

**书名显示 + 统计修复**

- 书名字数：`≤4本→10字 / ≤9本→8字 / ≥10本→6字`（原为固定 2 字）
- 修复统计按钮无响应：改用 `classList.add/remove('active')`

---

## V1.11.6 — 2026-06-01

**书架层/列规则修正**

- `START_LAYER=3`、`END_LAYER=8`（L1-L2 保留，L9 杂志区）
- `buildCellPlan()` 从 START_LAYER 开始
- L1-L2 渲染为虚线"保留"格，L9 渲染为虚线"杂志区"格
- 统计分母 `/135` → `/78`
- 活跃层 80% 时顶栏显示提示

---

## V1.11.5 — 2026-06-01

**10 项 Bug 修复**

| # | 问题 | 影响 |
|---|------|------|
| 1 | `applyZoom` 未更新 `currentZoom` | 缩放失效 |
| 2 | `CLC_MATCH` 重复 key F/T | 分类关键词丢失 |
| 3 | `renderShelf` L1-L3 书籍不可见 | 已分配书籍不显示 |
| 4 | `renderShelf` 循环到 `l<=10` 超出 9 行网格 | L10 布局错乱 |
| 5 | `updateStats` 显示 "X/135/135" | 统计重复 |
| 6 | `moveBook` position 差一 | 拖拽位置错误 |
| 7 | `importCSV` 不更新 `booksByLocation` | 批量导入位置冲突 |
| 8 | `fillBookData` 未传 `dbText` | 豆瓣关键词未用于分类 |
| 9 | `tryFetch` 非 AbortError 中断查询链 | 网络错误跳过备用源 |
| 10 | `mouseout` tooltip 永不消失 | tooltip 卡住 |

另：移除重复 Ctrl+Wheel 监听器

---

## V1.11.4 — 2026-06-01

**功能版本：云备份、封面、CSV、统计、9层书架**

- 云端备份/恢复（自动 + 手动）
- 封面显示（OpenLibrary）+ 补封面按钮
- CSV 导入导出（UTF-8 BOM）
- 统计面板（饼图 + 柱状图）
- 9 层书架（L1-L9）
- Ctrl+滚轮缩放
