Files
timeTableFix/README.md
timeTable2 dev e4f549f848 docs: add README
2026-07-13 18:53:39 +08:00

126 lines
5.5 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.

# timeTable2 - 纯前端 ICS 日历整理器
浏览器内解析、去重、编辑 ICS 日历文件,全程无需 Python 或后端服务。拖入 `.ics` → 整理去重 → 编辑 → 下载。
## 功能
- 📥 **拖入即用**:拖拽或选择 `.ics` 文件,浏览器内直接解析
- 🔁 **智能去重**:自动检测重复模式,将 61 个扁平事件合并为 5 个 RRULE 重复事件 + 3 个独立事件
- ✏️ **可视化编辑**:编辑标题/地点/时间/重复规则,点击网格切换排除日期
- ✂️ **拆分事件**:把一个重复事件按日期拆成前后两段(如后半学期换教室)
- **增删事件**:新增单次/重复事件,删除任意事件
-**撤销重做**:快照式 undo/redo最多 50 步
-**导出 ICS**:编辑完成下载整理后的 `.ics`,可直接导入日历应用
## 快速开始
```bash
# 安装依赖(使用 npmmirror 镜像加速,已配在 .npmrc
npm install
# 启动开发服务器
npm run dev
# 构建生产版本
npm run build
# 运行单元测试
npm test
```
浏览器打开 `http://localhost:5173`,拖入 `.ics` 文件即可。
## 使用流程
1. **导入**:拖入 `.ics` 文件(或点击选择),左侧显示所有原始事件
2. **去重**:点击顶栏「🔁 整理去重」,自动合并重复事件为 RRULE + EXDATE
3. **编辑**:点击左侧事件,右侧展开编辑表单
- 修改标题/地点/描述/时间
- 调整重复规则(频率/间隔/星期/重复到)
- 点击 occurrence 网格切换排除日期(绿色=包含,红色删除线=排除)
4. **拆分**(可选):点击「✂ 拆分此日程」,选日期,把重复事件拆成前后两段
5. **新增/删除**:点「➕ 新增日程」或「删除此日程」
6. **撤销**:「↶ 撤销」/「↷ 重做」最多 50 步
7. **下载**:点「⬇ 下载 ICS」导出整理后的 `.ics`(有未保存更改时会提示确认)
## 项目结构
```
timeTable2/
├── index.html Vite 入口
├── package.json
├── .npmrc npmmirror 镜像加速
├── vite.config.js
├── vitest.config.js
├── src/
│ ├── main.js 应用挂载
│ ├── App.vue 布局装配
│ ├── composables/
│ │ └── useCalendar.js 中心 store + 快照 undo/redo
│ ├── lib/
│ │ ├── weekday.js 星期常量与工具(统一 getDay 索引)
│ │ ├── ical-io.js ICS 文本 <-> plain modelical.js 封装)
│ │ ├── recur.js RRULE 网格展开
│ │ └── organize.js GCD 去重算法(移植自 Python 版)
│ └── components/
│ ├── HeaderBar.vue 顶栏:整理/撤销/重做/导入/下载
│ ├── DropZone.vue 拖拽/选择文件
│ ├── EventList.vue 侧栏事件列表
│ ├── EventDetail.vue 编辑表单 + 拆分
│ └── OccurrenceGrid.vue 排除日期网格
└── test/ Vitest 单元测试34 个)
├── golden-org.ics 测试用例61 事件的真实课表)
├── weekday.test.js
├── ical-io.test.js
├── recur.test.js
└── organize.test.js
```
### 三个核心 lib 模块
| 文件 | 作用 |
|------|------|
| `ical-io.js` | ICS 文本解析为普通对象、序列化回 ICS 文本ical.js 封装) |
| `organize.js` | GCD 间隔检测 + 系列分组 + EXDATE 生成(移植自 `ical_organizer.py` |
| `recur.js` | 从 RRULE + EXDATE 按需展开 occurrence 网格 |
## 算法
去重算法从 `timeTable/ical_organizer.py` 1:1 移植:
1. 按 (标题 + 地点 + 开始时间 + 时长 + 星期) 将事件分组
2. 计算组内相邻日期间隔的 **GCD**,识别:
- GCD = 7 → `FREQ=WEEKLY`(每周,含 `BYDAY`
- GCD = 1 → `FREQ=DAILY`(每天)
- GCD = 14 → `FREQ=WEEKLY;INTERVAL=2`(每两周)
3. 构建期望网格,网格上缺失的日期写入 `EXDATE`(如假期)
4. 不符合规律的组(跳过次数 ≥ 事件数)保留为独立事件
5. 合并后保留首个事件的原始 UID避免重新导入冲突
**验证**:对 `org.ics`61 事件)整理后输出 8 个事件5 重复 + 3 独立),与 Python 版 `ical_organizer.py --verify` 结果一致。下载的 ICS 用 Python `recurring-ical-events` 展开61 个 occurrence 与原始文件完全匹配。
## 技术栈
| 项 | 选择 |
|----|------|
| 框架 | Vue 3.5SFC`<script setup>` |
| 构建 | Vite 6 |
| ICS 库 | ical.js 2.x仅用于文本↔对象转换 |
| 状态管理 | composable 单例 store无 Pinia |
| 测试 | Vitest |
| 包源 | npmmirror.com中国镜像加速 |
## 与 timeTable 的关系
`timeTable`Python 版)使用 Flask + icalendar 库,需创建 venv 并启动本地服务器。
`timeTable2` 是纯前端等价实现:零安装、双击即用、算法行为一致。
| 对比 | timeTable (Python) | timeTable2 (前端) |
|------|--------------------|--------------------|
| 运行方式 | venv + Flask 服务器 | 浏览器直接打开 |
| 依赖 | icalendar, flask, recurring-ical-events | ical.js |
| 整理器 | `ical_organizer.py` 命令行 | 网页内「整理去重」按钮 |
| 编辑器 | `ical_editor.py` + `editor.html` | Vue3 组件 |
| 验证 | `recurring_ical_events` 展开 | 网页内 occurrence 网格 |
| 导出 | 保存到磁盘 / 下载 | 下载 `.ics` |