- 移除 EventDetail.vue 未用的 computed 导入 - 移除 HeaderBar.vue 未用的 .btn-secondary CSS - store (updateEvent/splitEvent/toggleOccurrence): uid 缺失改抛错 (fail-fast), 不再静默 return - EventDetail onSplit: 捕获 splitEvent 抛错并提示用户 - DropZone/HeaderBar 解析失败: catch 内补 console.error - ical-io getZone: 时区未注册回退 UTC 时 console.warn - WeekPreview 周标签改用 i18n (weekPreview.rangeFmt), 与 MonthPreview 一致 - docs: 新增 error-handling.md; 修正 auto-save-design state 快照补 timezone - README: 补充部署说明 (经 zMainPage apache2 托管)
3.0 KiB
3.0 KiB
自动保存设计
本文档记录 src/composables/useCalendar.js 与
src/components/HeaderBar.vue 的保存模型重构。
背景
原设计有「dirty 标记 + 下载前确认弹窗 + 快照式 undo/redo(最多 50 步)」。
EventDetail 的表单已改为自动应用(watch(form) 即时写回 store,
commit 1c6ecf9),dirty 仅用于「下载前提示未保存」与红点显示。撤销是
独立的历史栈。
重构:移除 dirty / undo
纯前端工具,无持久化需求,所有编辑本就即时生效(自动应用 watch)。 dirty 标记与确认弹窗是冗余的仪式感;undo 栈在自动应用场景下也意义 有限(每次 keystroke 都会 push 历史,栈迅速填满噪声)。移除以降低 复杂度、减少状态字段。
删除的死代码(useCalendar.js)
state.history(快照栈)、state.dirtyMAX_HISTORY常量snapshot()、pushHistory()、restore()undo()action、canUndocomputedmarkSaved()action- 各 action(
organize/updateEvent/deleteEvent/addEvent/splitEvent/toggleOccurrence)内的pushHistory()与state.dirty = true调用 loadFile内的state.history = []、state.dirty = false- 不再使用的
cloneEvent导入(snapshot 曾用)
HeaderBar.vue 改动
- 移除「撤销」按钮
- 移除下载按钮后的红点
●(<span class="dirty-dot">)与.dirty-dot样式 onDownload():移除if (state.dirty && !confirm(...))确认弹窗与markSaved()调用;直接serialize()下载
自动保存语义
- 所有编辑即时生效:
updateEvent/deleteEvent/addEvent/splitEvent/toggleOccurrence直接 mutate 响应式state.events, 无中间缓冲。EventDetail 的watch(form, { deep: true })把表单变化 立即 patch 回 store。 - 下载兜底:
onDownload调serialize()序列化当前最新状态。 即便有任何未触发渲染的边界改动,下载时也会被序列化包含。文件名取 原文件名去.ics加.edited.ics。 - occurrences 不持久化:EventModel 不存 occurrences,
OccurrenceGrid渲染时实时调expandOccurrences(ev)计算,toggleOccurrence直接改exdates。无缓存,无不同步风险。
状态字段(重构后)
const state = reactive({
meta: null,
events: [],
selectedUid: null,
fileName: null,
viewMode: 'edit', // 'edit' | 'month' | 'week'
previewDate: todayISO(),
timezone: detectTimezone(), // 日历级默认时区 (新建事件 tzid / X-WR-TIMEZONE)
})
无 history、无 dirty、无 redoStack。store 仅承载当前状态与视图锚点。
取消确认弹窗的理由
原 onDownload 在 dirty 时弹「有未保存的更改,仍要下载?」。但自动
应用下,所有更改已在 store 中,下载即序列化 store,不存在「未保存」。
弹窗只会误导用户以为有数据丢失风险。移除后下载是一次性操作。