# task_system **Repository Path**: goper/task_system ## Basic Information - **Project Name**: task_system - **Description**: No description available - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-25 - **Last Updated**: 2026-10-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 个人工作台 · Daily Console 一个真实可用的个人效率管理系统:任务 / 番茄专注 / 时间计划 / 收支 / 心情 / 健康 / 英语学习 / 食谱 / 网站收藏,一站式记录与回顾。 - **前端**:原生 HTML + CSS + JS 单页应用(无构建步骤,界面与交互零依赖) - **后端**:Node.js ≥ 22.5(仅用内置模块,**零 npm 依赖**)+ 内置 SQLite - **认证**:注册 / 登录,JWT(HS256),scrypt 密码哈希,账号间数据完全隔离 - **部署**:单进程单文件数据库,支持 Docker 一键部署 ## 快速开始 ```bash # 1. 启动(无需安装任何依赖) cd server node src/index.js # 或 npm start # 2. 打开浏览器 # http://localhost:3000 → 注册账号 → 自动生成示例数据,立即上手 ``` 端口与配置(均可用环境变量覆盖): | 环境变量 | 默认值 | 说明 | |---|---|---| | `PORT` | `3000` | 监听端口 | | `HOST` | `0.0.0.0` | 监听地址 | | `DB_FILE` | `server/data/app.db` | SQLite 数据库文件 | | `JWT_SECRET` | 自动生成并落盘 | 生产环境建议显式指定 | | `JWT_TTL_SECONDS` | `604800`(7 天) | 登录态有效期 | | `SEED_DEMO_ON_REGISTER` | `1` | 设为 `0` 则新账号不生成示例数据 | | `ADMIN_USERNAME` / `ADMIN_PASSWORD` | `admin` / `admin123456` | 超级管理员账号,**固定在 `server/src/config.js`**,每次启动自动创建并同步密码,生产环境务必修改 | ## Docker 部署 镜像内只有 Node 官方运行时 + 应用源码(后端零第三方依赖),构建秒级完成。数据全部落在容器内 `/app/server/data`(SQLite 数据库 + JWT 密钥),挂载卷即可持久化。 ### 第 1 步:构建镜像 ```bash cd taskonline # 进入项目根目录(Dockerfile 所在处) docker build -t daily-console . ``` ### 第 2 步:启动容器 Linux / macOS / Windows(PowerShell 去掉续行符): ```bash docker run -d \ --name daily-console \ -p 3000:3000 \ -v daily-console-data:/app/server/data \ -e JWT_SECRET="$(openssl rand -hex 48)" \ -e ADMIN_USERNAME=admin \ -e ADMIN_PASSWORD='改成强密码' \ --restart unless-stopped \ daily-console ``` 说明: | 参数 | 作用 | |---|---| | `-v daily-console-data:/app/server/data` | 数据卷:数据库与 JWT 密钥落在卷里,容器删除/升级不丢数据 | | `-p 3000:3000` | 端口映射,改宿主机端口只需改第一个(如 `-p 8080:3000`) | | `-e JWT_SECRET=…` | 登录令牌签名密钥;**生产环境必须显式指定**(否则每次重建容器会生成新密钥,所有人被登出) | | `-e ADMIN_USERNAME / ADMIN_PASSWORD` | 超级管理员账号,不传则用配置文件默认值 `admin / admin123456` | | `--restart unless-stopped` | 开机自启、异常退出自动拉起 | ### 第 3 步:访问 浏览器打开 `http://服务器IP:3000` → 注册账号或用管理员登录。内置健康检查(`/api/ping`),`docker ps` 里状态应显示 `healthy`。 ### 数据持久化与备份 ```bash # 备份(把数据卷打包到当前目录) docker run --rm -v daily-console-data:/data -v "$PWD":/backup alpine \ tar czf /backup/daily-console-data.tar.gz -C /data . # 恢复 docker run --rm -v daily-console-data:/data -v "$PWD":/backup alpine \ sh -c "cd /data && tar xzf /backup/daily-console-data.tar.gz" ``` 也可以改用绑定宿主机目录(便于直接备份文件): ```bash docker run -d --name daily-console -p 3000:3000 \ -v /opt/daily-console:/app/server/data daily-console ``` > Windows PowerShell 绑定目录写法:`-v C:\data\daily-console:/app/server/data` ### 升级版本 ```bash # 拉取最新代码后: docker build -t daily-console . docker rm -f daily-console docker run -d ... # 同第 2 步,数据卷不变即数据不丢 ``` ### 常用运维 ```bash docker logs -f daily-console # 查看日志(含请求日志与 WebDAV 自动备份记录) docker restart daily-console # 重启 docker stats daily-console # 资源占用 docker exec -it daily-console sh # 进入容器排查 ``` > 时区:镜像默认 `TZ=Asia/Shanghai`(应用按本地日期记账),如需其他时区加 `-e TZ=Area/City`。 > 安全建议:生产环境修改 `ADMIN_PASSWORD` 与 `JWT_SECRET`;如需 HTTPS,在前面挂 Nginx / Caddy 反代。 ## 目录结构 ``` index.html / css/ / js/ 前端单页应用(由后端直接托管,同源无 CORS) js/api.js fetch 封装 + token 管理 js/store.js 数据门面:本地缓存 + 乐观更新,失败自动回滚 js/pages-*.js 仪表盘与各功能页 js/app.js 路由、番茄计时引擎、登录/注册界面 server/ src/index.js 入口:组装路由、启动服务 src/config.js 配置(环境变量) src/db.js SQLite 连接 + 版本化迁移 src/lib/http.js HTTP 微框架:路由/中间件/静态资源/错误处理 src/lib/auth.js scrypt 密码哈希、JWT、限流 src/lib/validate.js 白名单式参数校验 src/lib/store.js 数据访问与 bootstrap 组装 src/lib/seed.js 示例数据生成(注册/重置共用) src/routes/auth.js /api/auth/* src/routes/domain.js 任务/日程/专注/心情/收支/健康/单词/食谱 src/routes/data.js bootstrap / 设置 / 重置 / 清空 / 导入 test/smoke.js API 冒烟测试(27 项断言) ``` ## API 概览 所有接口返回 JSON;除 `POST /api/auth/*` 与 `GET /api/ping` 外均需 `Authorization: Bearer `。 | 方法与路径 | 说明 | |---|---| | `POST /api/auth/register` | 注册(用户名 + 密码,限流 10 次/分/IP) | | `POST /api/auth/login` | 登录,返回 JWT | | `GET /api/bootstrap` | 一次拉取当前账号全部业务数据 | | `GET/POST /api/tasks` · `PUT/DELETE /api/tasks/:id` | 任务增删改查 | | `GET/POST /api/schedules` · `PUT/DELETE /api/schedules/:id` | 日程 | | `POST /api/focus-sessions` | 专注记录 | | `PUT /api/mood/:date` | 心情按日期 upsert | | `GET/POST /api/finance` · `PUT/DELETE /api/finance/:id` | 收支 | | `PUT /api/health/:date` | 健康指标按日期 upsert | | `POST/PUT/DELETE /api/english/words[/:id]` | 单词本 | | `POST /api/recipes` · `DELETE /api/recipes/:id` | 食谱 | | `GET/POST /api/bookmarks` · `PUT/DELETE /api/bookmarks/:id` | 网站收藏(标题 / 网址 / 分类 / 备注,网址校验 http(s)) | | `GET /api/messages` · `PUT /api/messages/:id/read` 等 | 消息中心(列表 / 未读数 / 标记已读 / 删除) | | `GET/POST /api/notify-bots` · `PUT/DELETE /api/notify-bots/:id` / `POST /:id/test` | 通知机器人管理(仅本人)与测试推送 | | `POST /api/hooks/message` | **对外推送接口**:请求头 `X-Key-Id` + `X-Key-Secret` 认证,body 传 `title` / `content` / `level`(info/success/warn/error) / `source`,每密钥限流 30 条/分 | | `PUT /api/settings` | 每日目标等设置 | | `POST /api/data/reset` / `clear` / `import` | 示例重置 / 清空 / 整包导入 | | `GET/PUT /api/webdav/config` | WebDAV 配置(密码加密存储、不回传) | | `POST /api/webdav/test` | 测试连接(目录不存在会自动 MKCOL 创建) | | `POST /api/webdav/backup` / `restore` | 手动备份到 WebDAV / 从远端整包恢复 | | `GET /api/webdav/status` | 本地最近备份 + 远端文件时间与大小 | | `GET/POST /api/admin/users` · `PUT/DELETE /api/admin/users/:id` | 用户管理(仅超级管理员):列表含数据统计 / 新建 / 重置密码 / 禁用启用 / 删除 | | `GET/PUT /api/admin/settings` | 系统设置(注册开关等,仅超级管理员) | | `GET /api/auth/config` | 注册页公开配置(是否开放注册) | ## 用户管理与超级管理员 - 超级管理员账号密码**固定在 `server/src/config.js`**(`ADMIN_USERNAME` / `ADMIN_PASSWORD`,可被同名环境变量覆盖);服务每次启动会自动创建该账号、按配置同步密码并强制解除禁用 - 管理员登录后侧边栏出现「用户管理」:查看全部用户(含各自的任务 / 收支 / 专注 / 心情数据量与最近登录时间)、新建用户(空白初始态)、重置密码、禁用 / 启用、删除用户(级联清除其全部数据) - **注册开关**:管理员可在用户管理页一键开关闭用户注册;关闭后登录页隐藏注册入口并提示联系管理员,注册接口返回 403(设置存于数据库,重启保留) - 保护规则:不能禁用 / 删除自己;管理员账号不可被其他管理员修改或删除;被禁用 / 删除的账号,其已登录会话**立即失效** - 密码策略与注册一致(scrypt 哈希、至少 6 位);角色写入 JWT,接口层有 `requireAdmin` 门禁,普通用户访问管理接口返回 403 ## 通知机器人(飞书 / 钉钉 / 企业微信) 在「设置 → 通知机器人」添加群自定义机器人并勾选要订阅的事件,系统事件会自动推送到群里: | 事件 | 触发时机 | 通知对象 | |---|---|---| | 用户登录 | 任意账号登录成功 | 管理员的机器人 + 登录者自己的机器人 | | 新用户注册 | 有新账号注册 | 管理员的机器人 | | 完成任务 | 任务从未完成变为已完成 | 任务主人的机器人 | | 专注完成 | 番茄钟倒计时结束入库 | 任务主人的机器人 | | 收到推送消息 | 外部程序通过推送 API 发来消息 | 消息主人的机器人 | 支持三种平台(均为自定义机器人 webhook 文本消息):飞书、钉钉、企业微信。面板内可启停、编辑订阅事件、一键发送测试消息,最近推送状态(成功 / 失败原因)实时显示。 获取 webhook 地址:飞书群 → 设置 → 群机器人 → 添加自定义机器人;钉钉群 → 智能群助手 → 自定义机器人(安全设置建议勾选"自定义关键词");企业微信群 → 添加群机器人。`server/test/mock-notify.js` 提供本地假接收器用于联调测试。 ## 消息中心与外部推送 在「设置 → 消息推送密钥」生成密钥(KeyId + Secret,**Secret 仅在生成时显示一次**,服务端只存哈希),即可让 CI、监控、脚本等外部程序把消息推到你的消息中心: ```bash curl -X POST http://你的服务地址/api/hooks/message \n -H "X-Key-Id: mk_xxxxxxxx" \n -H "X-Key-Secret: msk_xxxxxxxx" \n -H "Content-Type: application/json" \n -d "{"title":"构建完成","content":"#42 部署成功","level":"success","source":"CI"}" ``` - `level`:`info` / `success` / `warn` / `error`,决定消息中心的图标与颜色 - `source`:来源名称(如 CI、监控告警),展示在消息上 - 每密钥限流 30 条/分钟,每账号最多 10 个密钥,消息保留最近 500 条 - 密钥可随时删除,删除后外部程序立即无法推送;前端每 30 秒轮询一次新消息,侧栏「消息中心」显示未读角标 ## WebDAV 数据同步 在「设置 → WebDAV 同步」中配置服务器地址、账号、密码(坚果云请使用应用密码)与远程目录: - **测试连接**:PROPFIND 校验地址与凭据,目录不存在时自动创建(MKCOL) - **备份到 WebDAV**:把当前账号全部数据打包为 JSON 上传(文件名含账号标识,多账号互不覆盖) - **从 WebDAV 恢复**:拉取远端备份,确认后整包覆盖本地(恢复前显示远端备份时间) - **自动备份**:可设每 30 分钟 / 1 / 3 / 12 / 24 小时,服务端内置调度器每分钟检查到期账号自动上传 多台设备同步的做法:所有设备的应用实例配置同一个 WebDAV 目录;在 A 设备「备份」,到 B 设备「恢复」即可迁移;开启自动备份后,备份文件始终是最近使用设备推送的最新快照(单设备写入场景等价于双向同步)。 WebDAV 密码使用 AES-256-GCM 加密后入库(密钥由 `JWT_SECRET` 派生),配置接口不回传明文。内置测试服务器 `server/test/mock-webdav.js` 可在没有真实网盘时做全流程验证。 ## 测试 ```bash # 先启动服务,然后: cd server && npm run smoke # 输出 71 项断言结果,覆盖认证、隔离、校验、CRUD、导入导出、WebDAV 同步、自动备份调度、用户管理、网站收藏 ``` ## 安全设计 - 密码使用 `scrypt`(N=16384)加盐哈希,校验采用恒定时间比较 - JWT HS256 签名,密钥支持环境变量注入;未配置时自动生成并保存到数据目录 - **API 全局认证门禁**:除公开路径外一律要求有效 token - 所有查询/写入强制 `user_id` 过滤,账号间数据物理隔离(越权访问返回 404) - 白名单式参数校验(类型 / 长度 / 枚举 / 日期时间格式),拒绝未知字段 - 认证接口按 IP 限流;安全响应头(nosniff / DENY frame / no-referrer) - 静态资源 ETag 协商缓存,防目录穿越 ## 备份与迁移 - 数据库为单文件 `server/data/app.db`,直接复制即备份;亦可停机后打包 `server/data/` - 前端「设置 → 导出数据」可随时导出 JSON,「导入数据」整包恢复 - 表结构变更走 `db.js` 中的版本化迁移(`schema_migrations` 表记录版本),升级不丢数据 ## 技术说明 - SQLite 通过 Node 内置 `node:sqlite`(要求 Node ≥ 22.5,推荐 24 LTS),无需编译原生模块 - 前端写入采用「乐观更新」:先改本地缓存即时渲染,后台同步服务端,失败自动回滚并提示 - 番茄计时状态保存在本机(会话级),完成的会话上报服务端入库