Files
timeTableFix/docs/auto-save-design.md
zikai d32f8be018 refactor: 清理死代码 + 提前失败 + 错误记录控制台
- 移除 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 托管)
2026-07-28 11:08:06 +08:00

75 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 自动保存设计
本文档记录 `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.dirty`
- `MAX_HISTORY` 常量
- `snapshot()``pushHistory()``restore()`
- `undo()` action、`canUndo` computed
- `markSaved()` 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`。无缓存,无不同步风险。
## 状态字段(重构后)
```js
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不存在「未保存」。
弹窗只会误导用户以为有数据丢失风险。移除后下载是一次性操作。