# timeTableFix - 纯前端 ICS 日历整理器 浏览器内解析、去重、编辑 ICS 日历文件,全程无需后端服务。拖入 `.ics` -> 整理去重 -> 编辑 -> 下载。 ## 功能 - 📥 拖入即用:拖拽或选择 `.ics` 文件,浏览器内直接解析 - 🔁 智能去重:自动检测重复模式,将扁平事件合并为 RRULE 重复事件 + EXDATE - ✏️ 可视化编辑:编辑标题/地点/时间/重复规则,点击网格切换排除日期 - ✂️ 拆分事件:把一个重复事件按日期拆成前后两段 - ➕ 增删事件:新增单次/重复事件,删除任意事件 - ↶ 撤销重做:快照式 undo/redo,最多 50 步 - ⬇️ 导出 ICS:下载整理后的 `.ics`,可直接导入日历应用 ## 项目结构 ``` timeTableFix/ ├── index.html Vite 入口 ├── package.json ├── vite.config.js 构建配置(含 preview.allowedHosts) ├── vitest.config.js ├── .npmrc npmmirror 镜像加速 ├── src/ │ ├── main.js 应用挂载 │ ├── App.vue 布局装配 │ ├── composables/ │ │ └── useCalendar.js 中心 store + 快照 undo/redo │ ├── lib/ │ │ ├── weekday.js 星期常量与工具 │ │ ├── date.js 日期工具 │ │ ├── ical-io.js ICS 文本 <-> plain model │ │ ├── recur.js RRULE 网格展开 │ │ ├── organize.js GCD 去重算法 │ │ ├── event-factory.js 事件构造工厂 │ │ └── split.js 事件拆分逻辑 │ └── components/ │ ├── HeaderBar.vue 顶栏:整理/撤销/重做/导入/下载 │ ├── DropZone.vue 拖拽/选择文件 │ ├── EventList.vue 侧栏事件列表 │ ├── EventDetail.vue 编辑表单 + 拆分 │ └── OccurrenceGrid.vue 排除日期网格 ├── test/ Vitest 单元测试 │ ├── golden-org.ics 测试用例(61 事件的真实课表) │ ├── weekday.test.js │ ├── ical-io.test.js │ ├── recur.test.js │ └── organize.test.js └── docs/ 设计文档 ``` ## Ubuntu 从零安装 ### 1. 安装 Node.js 18+ ```bash curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo apt-get install -y nodejs node --version # 确认 v18.x ``` ### 2. 克隆并安装依赖 ```bash git clone https://git.zikai.wang/zikai/timeTableFix.git cd timeTableFix npm install # 已配 npmmirror 镜像加速 ``` ### 3. 构建生产版本 ```bash npm run build # 产物输出到 dist/ npm test # (可选)运行单元测试 ``` ### 4. 部署为系统服务(systemd) 创建服务文件 `/etc/systemd/system/timetable-fix.service`: ```ini [Unit] Description=timeTableFix ICS Calendar Organizer After=network.target [Service] Type=simple WorkingDirectory=/path/to/timeTableFix ExecStart=/path/to/timeTableFix/node_modules/.bin/vite preview --host 0.0.0.0 --port 8888 Restart=on-failure RestartSec=3 Environment=NODE_ENV=production StandardOutput=append:/var/log/timetable-preview.log StandardError=append:/var/log/timetable-preview.log [Install] WantedBy=multi-user.target ``` > 将上述 `WorkingDirectory` 和 `ExecStart` 中的路径替换为实际的 `timeTableFix` 绝对路径。 加载并启动: ```bash sudo systemctl daemon-reload sudo systemctl enable --now timetable-fix ``` ### 5. 放行防火墙端口 ```bash sudo ufw allow 8888/tcp ``` 浏览器访问 `http://<服务器IP>:8888` 即可。若通过域名访问(如 `f.zikai.wang`),需在 `vite.config.js` 的 `preview.allowedHosts` 中添加该域名。 ## 使用(启动 / 关闭) 服务由 systemd 管理,开机自启、崩溃自动恢复。 ```bash # 启动 sudo systemctl start timetable-fix # 关闭 sudo systemctl stop timetable-fix # 重启 sudo systemctl restart timetable-fix # 查看状态 sudo systemctl status timetable-fix # 查看日志 tail -f /var/log/timetable-preview.log ``` 开发模式(无需 systemd,前台运行): ```bash cd timeTableFix npm run dev # http://localhost:5173 ``` ## 技术栈 | 项 | 选择 | |----|------| | 框架 | Vue 3.5(SFC,`