JianMiau 40cb2f01d7 功能:新增更新紀錄分頁、勝利後鎖記分與結算後自動選隊、報分語音改唸個位數
摘要:
- 新增「更新紀錄」分頁,依 git commit 自動產生日誌(scripts/generate-changelog.mjs → src/data/changelog.json)
- 比賽分出勝負後鎖住記分按鈕,需先結算才能開下一場
- 結算(上傳或不上傳)完成後自動打開選隊伍面板並清空已選,方便直接排下一場
- 得分播報只唸個位數(10→0、19→9、20→0),同分改唸「N 平」

根本原因:
- 想在 App 內直接看到版本更新內容,原本沒有頁面
- 勝利後仍可繼續點加分,容易誤觸超過該局比分
- 一場打完要手動回去重設下一場對戰,流程多一步
- 報分連十位數一起唸(十九、二十)冗長,現場聽不直覺

影響:
- 新增 scripts/generate-changelog.mjs、src/pages/ChangelogPage.tsx;package.json 加 predev/prebuild/gen:changelog;tsconfig.app.json 開 resolveJsonModule;.gitignore 排除產生的 changelog.json
- src/types.ts 新增 ChangelogEntry/ChangelogData;src/App.tsx 加導覽與路由、結算後發 nextMatchSignal、recordPoint 加勝負防呆
- src/lib/match.ts 將 hasWonGame 抽出並 export 供記分板共用
- src/pages/ScoreboardPage.tsx:勝負時 canScore=false、收到 nextMatchSignal 自動清空並打開選隊 picker、報分組字改個位數與「平」
- src/App.css 新增更新紀錄卡片樣式

修法:
- changelog 於 dev/build 前自動產生,正式版讀打包後的 JSON 顯示
- hasWonGame 統一判斷(達標分/Deuce 領先 2 分/30 分上限),App 與記分板共用
- 結算成功才遞增 nextMatchSignal,記分板以「render 期間依 prop 變化調整 state」開啟選隊面板
- 報分以 servingScore % 10 / opponentScore % 10 組字,同分輸出「N 平」

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 12:15:28 +08:00

羽毛球記分板

這是一個使用 Vite + React + TypeScript + Node.js 製作的羽毛球記分板專案,提供手機優先的記分介面、歷史戰績、房間觀戰、語音播報、PWA 安裝,以及 Docker / NAS 部署方式。

功能特色

  • 選隊伍頁面
    • 可依指定日期從資料庫讀取分組資料。
    • 若當天沒有資料,可手動輸入 A、B 區名單建立配對。
    • 點進記分板時會直接帶入該組對戰。
  • 記分板
    • 兩隊隊員可自由交換上下、左右位置。
    • 畫面編號固定為左上 1、右上 2、右下 3、左下 4
    • 先攻只能在開局設定一次,之後不會跟著發球權改變。
    • 點擊分數直接加分,沒有加一減一按鈕。
    • 第一分開始後,設定隊伍 會改成 上一步
    • 比賽結算 需要長按 1 秒才會觸發,避免誤觸。
    • 達標分數後有獲勝動畫與結算流程。
    • 手機上會盡量壓縮成單頁滿版,避免上下滑動。
  • 羽球規則
    • 預設 21 分制,可在設定隊伍時調整目標分數。
    • 支援 Deuce20:20 後需領先 2 分才獲勝。
    • 29:29 時第 30 分直接獲勝。
    • 發球方依羽球規則處理,0 分在右發球區。
    • 畫面以下方隊伍為我方、上方隊伍為對方。
    • 上方隊伍採鏡像顯示,所以我方 0:0 在右邊發球時,對方會在左邊接發。
  • 語音播報
    • 只在按下加分當下播報,不會因復原或其他操作重複報分。
    • 可選擇是否播報得分與發球者。
    • 同隊連續得分才會播報 換邊發球
    • 支援調整語速,最高可到 10x
    • RURU 會做大小寫無關判斷並以指定發音播報。
  • 歷史戰績
    • 可從資料庫讀取歷史列表。
    • 點開單筆可查看得分過程。
    • 每筆資料可刪除,刪除前會顯示確認提示。
  • 房間觀戰
    • 記分板帶入隊伍後會自動建立房間。
    • 房間列表可查看目前直播中的比賽。
    • 觀戰者只能看,不能操作記分。
    • 分數、房間狀態、比賽結算會即時同步給觀戰者。
    • 房間失效、重整、重選隊伍後也會通知觀戰者。
    • 房間列表有 重新取得列表,並帶有 5 秒冷卻。
  • PWA
    • 可安裝到 iPhone / iPad / Android 主畫面。
    • 支援 Web App 模式啟動。
    • 新版本部署後會提示重新整理或重新安裝。

本機開發

Port

  • Client: 3501
  • Server: 8788

安裝

npm install

啟動開發模式

npm run dev

啟動後:

  • 前端:http://localhost:3501
  • APIhttp://localhost:8788

檢查

npm run lint
npm run build

記分板滿版模式

  • 記分板頁面會套用 100dvh 高度。
  • 手機進入記分板時會關閉頁面捲動與 overscroll。
  • viewport 已加上 viewport-fit=cover,較能貼合 iPhone / iPad 安全區。
  • 若手機高度較矮,會再縮小字級、按鈕與分數區,盡量維持整頁顯示。

環境變數

請先建立 .env

DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASSWORD=your_password
DB_DATABASE=badminton
DB_TABLE=badminton
DB_HISTORY_TABLE=history
PORT=8788

Docker / NAS 部署

對外服務配置:

  • 容器內 Node / API8788
  • 對外 HTTPS 網址:3501

部署指令:

sudo docker compose up -d --build

部署完成後可用:

https://你的網域或 NAS IP:3501

每次執行 sudo docker compose up -d --build 都會重新建置前後端與 PWA 靜態資產。

SSL 憑證

Docker Compose 會掛載以下目錄:

/volume1/homes/JianMiau/www/certificate/

需包含:

  • RSA-cert.pem
  • RSA-chain.pem
  • RSA-privkey.pem

之後只要更新這個目錄內的憑證檔案,再重新部署容器即可套用新 SSL。

資料表格式

history

  • id
  • time
  • dayOfWeek
  • score
  • winScore
  • type
    • 0: 雙打
    • 1: 單打
  • players
    • 依照 1 ~ 4 固定編號順序儲存玩家名單。
  • team
    • 12 一隊
    • 34 一隊
  • scoreList
    • 格式:[round, 發球者編號, 連勝數, 得分隊伍(0 或 1)]

PWA Icon

目前使用:

  • public/favicon.png
  • public/apple-touch-icon.png
  • public/pwa-192.png
  • public/pwa-512.png

Git 中文顯示

若要讓 git log / commit 顯示中文,建議設定:

git config i18n.commitEncoding utf-8
git config i18n.logOutputEncoding utf-8
git config core.quotepath false
S
Description
羽毛球記分板系統,可用於即時顯示比分、回合進度與比賽狀態。
https://jianmiau.tk:3501/
Readme 1.9 MiB
Languages
TypeScript 60%
CSS 25.8%
JavaScript 12%
Shell 1.4%
HTML 0.5%
Other 0.3%