Skip to content

Repository files navigation

溫習音樂計時

一款開源的離線溫習計時 PWA(漸進式網頁應用)。把「倒數計時」「番茄工作法」「階段提示音」與「自選背景音樂」整合在一起,自動記錄每日學習時長,幫你專心溫習、也知道「今天溫習了多久」。

  • 四個分頁:計時 / 日曆 / 音樂 / 設定
  • 平台:Android 手機(Chrome)+ Windows 電腦(Chrome / Edge)
  • 技術形態:PWA,可「加到主畫面」當 App,可安裝到桌面,斷網也能用

1. 項目解決什麼問題

溫習時常遇到的痛點:

  1. 想專心一段固定時間,但手機計時器不會自動記錄「今天累計溫習多久」。
  2. 番茄工作法能逼自己有規律地學,但原生鬧鐘沒有「階段輪流 + 自動統計專注時數」且休息不計入
  3. 想邊聽自己喜歡的音樂邊溫習,又不想每次重開 App 都重新選檔。
  4. 隱私與離線:不想登入、不想上傳任何資料到雲端,所有數據只存在自己設備上。
  5. 手機放後台 / 被系統清掉記憶體後,計時不準甚至歸零。

這個 App 把上述全部做成一個本地、離線、無登入的工具:計時準(用牆上時鐘追趕)、記錄自動累計、音樂一次存入、數據只存本機,且兩台設備各自獨立(靠匯出 / 匯入手動搬移)。


2. 主要功能

模塊 功能
倒數計時 自由設時長(分 / 秒);開始、暫停 / 繼續、重置、結束;快捷 25 / 45 / 60 分;結束播提示音 + 通知;進行中時間計入日曆。
番茄工作法 專注 / 短休息 / 長休息 / 循環數全部可調;自動輪流切換;切換播對應提示音;顯示「第 X/Y 個番茄 · 專注中」與進度;可跳過 / 提前結束;只有專注階段計入學習時長,休息不計。
提示音效 內置 4 款離線合成音效(輕快上行 / 溫和下行 / 鈴聲 / 單音叮),「開始學習」與「休息結束」可分別選;音量調節;手機可震動。
學習日曆 月曆每天顯示總時長(顏色深淺表示久短);點某天看明細(時段 + 來源:倒數 / 番茄專注);頂部顯示今日 / 本週 / 本月 / 連續天數
音樂播放器 首次啟動自動播種 9 首 AI 生成預設音樂;亦可從設備加入自己的音檔(以 Blob 存 IndexedDB,重開不丟);播放 / 暫停 / 上一首 / 下一首 / 循環 / 隨機;音量;與計時聯動(專注自動播、休息自動停,可關)。
設定 所有時間參數、提示音、主題(淺色 / 深色 / 像素二次元)、音樂聯動,全存本機,即時生效;匯出 / 匯入記錄。
後台計時準確 計時一律用 Date.now() 差值;每次狀態變更把執行快照寫入 localStorage;App 回到前景(visibilitychange)或重啟時,依牆上時鐘追趕後台期間流逝的時間,並重播已完成的番茄階段——放後台 / 被殺再回來,剩餘時間依然準確。
離線 / 安裝 Service Worker 預緩存全部資源,包含 9 首 mp3;可「加到主畫面」當 App,斷網照常使用。

兩個計時模塊完全獨立:切換倒數 / 番茄只換顯示,不會重置或互相干擾——另一個模塊會繼續在背景計時。


3. 安裝方法

3.1 開發環境需求

  • Node.js 18+(僅開發 / 打包需要;打包出的純靜態檔在手機上不需要 Node)
  • npm(隨 Node 附帶)

3.2 取得程式碼與安裝依賴

git clone https://github.com/youyou9179/study-timer.git study-timer
cd study-timer
npm install

3.3 常用指令

指令 說明
npm run dev 啟動本地開發伺服器(預設 http://localhost:5173),即時預覽
npm run build 打包成靜態檔到 dist/(含 PWA manifest + service worker)
npm run preview 本地預覽打包結果(http://localhost:4173
npm run test 執行全部單元測試(Vitest)
npm run test:watch 測試監看模式

3.4 安裝成手機 / 電腦 App(PWA)

  1. npm run build 產出 dist/
  2. dist/ 部署到任意靜態託管(GitHub Pages / Netlify / Cloudflare Pages 等,需 HTTPS)。
    • 本專案 base 設為 ./,可直接放在 https://youyou9179.github.io/study-timer/ 這類子路徑。
  3. 手機用 Chrome 開啟網址 → 選單「加到主畫面」;電腦用 Chrome / Edge 開啟 → 網址列「安裝」圖示。
  4. 安裝後即為獨立 App,且完全離線運作,資料只存在該設備。

託管只用作「安裝入口」與靜態檔下載;App 執行時不發出任何網路請求、不上傳資料,不違反「無雲端」約束。


4. 使用方法

開啟 App 後預設進入計時分頁。

計時分頁

  • 頂部切換 倒數 / 番茄
  • 倒數:點 25 / 45 / 60 設時長(或到設定改預設值)→ 按 開始;可 暫停 / 繼續重置
  • 番茄:按 開始 後自動輪流 專注 → 短休息 → …;可 跳過 當前階段、結束 整組。
  • 切換分頁或放後台都不影響計時;回到 App 會立即依真實時間校正。

日曆分頁

  • 看當月每天學習時長(顏色越深代表越久)。
  • 點某天看該日明細(時段與來源:倒數 / 番茄專注)。
  • 頂部顯示今日 / 本週 / 本月總時長與連續天數。
  • 切換月份。

音樂分頁

  • 首次啟動已有 9 首預設音樂,直接播放 / 暫停 / 上一首 / 下一首。
  • 點「加入音樂」從設備選自己的音檔(支援多選),會存入本機資料庫、下次免重選。
  • 切換循環 / 隨機、調音量;可刪除曲目釋放空間。
  • 設定中的「專注自動播 / 休息自動停」開關控制與計時聯動。

設定分頁

  • 倒數預設、番茄(專注 / 短休 / 長休 / 幾個後長休):即時生效。
  • 提示音:開始學習 / 休息結束分別選音效、音量、震動開關。
  • 外觀:淺色 / 深色 / 像素二次元。
  • 備份:匯出記錄 下載一份 study-timer-backup.json匯入記錄 選該檔還原(會覆蓋本機記錄)。

5. 輸入 / 輸出示例

5.1 倒數計時

輸入(設定倒數預設 25 分,或點快捷 25):

倒數預設 = 25 分

過程與輸出(大字顯示逐秒倒數):

25:00  →  24:59  →  …  →  00:01  →  00:00

結束時:播放「休息結束」提示音 → 彈系統通知「溫習完成:呢節倒數計時完成啦!」→ 把這 25 分鐘寫入當日日曆(來源:倒數)。

5.2 番茄工作法

輸入(設定:專注 25 / 短休 5 / 長休 15 / 4 個後長休):

pomodoro = { focusSec: 25*60, shortSec: 5*60, longSec: 15*60, cyclesBeforeLong: 4 }

自動輪流(每階段切換播對應提示音):

第 1 個番茄 · 專注中   (25:00 倒數)  → 短休息 (05:00) →
第 2 個番茄 · 專注中   → 短休息 →
第 3 個番茄 · 專注中   → 短休息 →
第 4 個番茄 · 專注中   → 長休息 (15:00) → 回到第 1 個番茄 …

統計規則:只有「專注」階段的秒數計入學習時長;短休 / 長休不計

5.3 時間格式(程式內部函式)

呼叫 輸出
formatTime(1500) "25:00"
formatTime(3661) "01:01:01"
formatDuration(1800) "30 分"
formatDuration(3900) "1 小時 5 分"
formatDuration(45) "45 秒"

5.4 學習日曆統計(日曆分頁頂部)

今日   1 小時 5 分
本週   4 小時 20 分
本月   12 小時 0 分
連續   6 天

點某天明細示例:

2026-08-30
總時長:1 小時 5 分
 - 倒數 · 25 分
 - 番茄專注 · 40 分

5.5 匯出備份檔結構(study-timer-backup.json

{
  "version": 1,
  "exportedAt": "2026-08-30T11:00:00.000Z",
  "settings": {
    "countdownDefaultSec": 1500,
    "pomodoro": { "focusSec": 1500, "shortSec": 300, "longSec": 900, "cyclesBeforeLong": 4 },
    "sound": { "startStudy": "chime-up", "breakOver": "chime-down", "volume": 0.7, "vibrate": true },
    "theme": "light",
    "musicLink": true,
    "playlistOrder": ["default_lofi_piano", "t_123456_abc"]
  },
  "sessions": [
    { "date": "2026-08-30", "totalSec": 3900, "entries": [
      { "startTs": 1756543200000, "endTs": 1756544700000, "source": "countdown", "sec": 1500 },
      { "startTs": 1756545000000, "endTs": 1756547400000, "source": "pomodoro-focus", "sec": 2400 }
    ] }
  ],
  "music": [
    { "id": "default_lofi_piano", "name": "Lo-fi 鋼琴 Lo-fi Piano", "mime": "audio/mpeg", "data": "<base64>" },
    { "id": "t_123456_abc", "name": "我的歌.mp3", "mime": "audio/mpeg", "data": "<base64>" }
  ],
  "playlistOrder": ["default_lofi_piano", "t_123456_abc"]
}

5.6 預設音樂清單(首次啟動自動播種)

曲名 檔案
木吉他 Acoustic Guitar music/acoustic_guitar.mp3
環境節拍 Ambient Beats music/ambient_beats.mp3
舒緩鋼琴 1–5 Chill Piano 1–5 music/chill_piano_1.mp3chill_piano_5.mp3
古典鋼琴 Classical Piano music/classical_piano.mp3
Lo-fi 鋼琴 Lo-fi Piano music/lofi_piano.mp3

播種只在每個設備發生一次(由 meta.seededDefaultMusic 標記保證);你刪掉預設曲也不會自動補回。

AI 生成音樂標註:以上 9 首預設背景音樂均由 ACE-Step 1.5(MIT) 於本機生成,其來源、授權狀態與免責聲明詳見 public/music/MUSIC_CREDITS.md


目錄結構

study-timer/
├─ index.html              # 單頁入口,掛載 #app
├─ package.json
├─ vite.config.js          # 含 vite-plugin-pwa 設定(manifest + service worker)
├─ public/
│  ├─ music/               # 9 首預設音樂 mp3(離線預緩存)
│  └─ icons/               # PWA 圖標 192 / 512 / maskable
├─ src/
│  ├─ main.js              # 啟動、分頁路由、主題套用、前景同步
│  ├─ state/
│  │  ├─ db.js             # IndexedDB 封裝:settings / sessions / music / meta
│  │  └─ store.js          # 中央狀態:設定、計時、音樂、後台追趕、匯出匯入
│  ├─ timer/
│  │  ├─ engine.js         # 計時核心(timestamp 精準、可序列化)
│  │  ├─ countdown.js      # 倒數模式
│  │  └─ pomodoro.js       # 番茄模式(自動輪流 + 階段切換 + 追趕)
│  ├─ audio/
│  │  ├─ sounds.js         # WebAudio 合成內置提示音 + 音量
│  │  ├─ notify.js         # 系統通知 + 震動
│  │  ├─ musicPlayer.js    # 本地音樂播放器
│  │  └─ defaultMusic.js   # 預設音樂清單 + 首次播種
│  ├─ modules/
│  │  ├─ timerView.js      # 計時分頁
│  │  ├─ calendarView.js   # 日曆分頁
│  │  ├─ musicView.js      # 音樂分頁
│  │  └─ settingsView.js   # 設定分頁
│  ├─ utils/
│  │  ├─ time.js           # 時間格式化、日期鍵、streak 計算
│  │  └─ backup.js         # 匯出 / 匯入(JSON + Blob base64)
│  └─ styles/
│     └─ main.css          # 主題變數、排版、手機/電腦響應式
└─ (sw.js 由 vite-plugin-pwa 自動生成,勿手改)

隱私與離線說明

  • 不登入、不聯網、無雲端:App 執行期間不發出任何網路請求,無上傳行為。
  • 數據全存本機:學習記錄、設定、音樂檔皆存於設備的 IndexedDB(等同本地檔);計時執行快照存 localStorage 以支援後台追趕。
  • 兩台設備各自獨立:手機與電腦不會自動同步;跨設備搬移唯一方式是設定頁的「匯出 / 匯入」。

測試

npm run test

涵蓋:計時核心(倒數 / 番茄)、後台真實時間追趕、模式獨立、預設音樂播種、提示音、日曆統計、備份匯出匯入、建置產物驗證等。


已知限制

  • PWA 無法像原生 App 那樣在通知欄常駐一條通知;本專案以「牆上時鐘追趕」保證計時準確(而非常駐通知)。
  • 預設音樂共 9 首(約 26MB),會隨網站一併預緩存;若想減小體積可改為外部連結或壓縮。
  • 手機安裝 PWA 需要 HTTPS;離線可用,但部分瀏覽器在長時間完全斷網後可能需重新整理一次以更新 service worker 快取。

授權 License

  • 程式碼MIT License 釋出,詳見 LICENSE
  • 預設背景音樂ACE-Step 1.5(MIT) 於本機生成,其授權與免責聲明見 public/music/MUSIC_CREDITS.md;音樂素材授權與程式碼授權獨立,使用時請另行保留該聲明。
  • 本專案為離線、無雲端工具;若你自行部署,託管服務僅作靜態檔下載與安裝入口之用。

About

開源離線溫習音樂計時 PWA:倒數計時、番茄工作法、階段提示音、本地背景音樂與學習日曆,斷網也能用。

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages