新增讀取 Telegram 出席名單功能,讀取指定日期改為自動 fallback

根本原因:
Node-RED 的 Telegram bot「建喵打羽球」已把報名名單寫進同庫的 attendance 表,但配對器沒有任何入口讀取,每次仍需手動把出席者一個個打進名單。

影響:
- 新增 GET /api/attendance/:time,用既有 pool 讀 attendance 表,沒資料回 404
- 「讀取指定日期」改為兩段:先讀 badminton 配對資料,該日還沒配對時自動改載入出席名單
- 新增「讀取今日出席」按鈕可直接載入出席名單
- attendance 表沒有分區資訊,出席者一律先放 A 區、清空 B 區與既有配對,由使用者自行分配
- badminton 表結構與上傳流程不變

修法:
server.mjs 新增 attendance 端點;App.tsx 新增 findAttendance / loadAttendance / applyAttendance,loadResults 改用 findMatchResults 判斷後 fallback,移除不再使用的 loadMatchResults;README 補上讀取今日出席章節與 attendance 表結構。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 11:46:13 +08:00
co-authored by Claude Fable 5
parent 4633412407
commit 121a5fee4c
3 changed files with 185 additions and 21 deletions
+35 -8
View File
@@ -14,19 +14,46 @@
- 產生配對後可用按鈕手動上傳資料到資料庫
- 若指定日期已經有資料,上傳前會先詢問是否覆蓋
- 可讀取指定日期的資料庫內容並回填到畫面
- 若指定日期沒有資料,畫面會顯示「指定日期沒有資料」
- 組隊結果產生後可一鍵主動推播到指定 LINE 對話
- 若指定日期沒有配對資料,`讀取指定日期` 會自動改抓 Telegram bot 的出席名單帶入 A 區
- 也可直接按 `讀取今日出席`,把出席名單帶進 A 區後再自行分配到 B 區
- 兩邊都沒有資料時,畫面會顯示對應的錯誤訊息
- 組隊結果產生後可一鍵主動推播到指定 LINE 對話(需按兩次確認)
- 支援換行、半形逗號、全形逗號與頓號輸入
- 會自動去除空白與重複名稱
## 操作流程
1. 輸入 A 區與 B 區名單
2. `產生三組配對`
3. 選擇 `目標日期`
4. 按下 `上傳資料` 將資料寫入 DB
5. 若需要,可按 `讀取指定日期` 載回既有資料
6. 組隊結果顯示後,可按 `推送到 LINE`
1. 選擇 `目標日期`
2.`讀取今日出席` 帶入 Telegram 報名名單(或手動輸入 A 區與 B 區名單)
3. 把 A 區的人自行搬一部分到 B 區
4. 按下 `產生三組配對`
5. 按下 `上傳資料` 將資料寫入 DB
6. 若需要,可按 `讀取指定日期` 載回既有資料;該日還沒配對時會自動改載入出席名單
7. 組隊結果顯示後,可按 `推送到 LINE`(按兩次確認才會送出)
## 讀取今日出席
出席名單來自 Node-RED 的 Telegram bot「建喵打羽球」:群組成員按「參加」後會寫進同一個資料庫的 `attendance` 表,按「不參加」則直接刪除,所以表裡的就是當天出席名單。
- 使用現有的 `DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_DATABASE` 連線,不需要新的環境變數
- API`GET /api/attendance/:time``time``YYYYMMDD`),回傳 `{ ok: true, data: { time, names: [...] } }`;沒資料回 404
- `attendance` 表沒有 A / B 區資訊,載入後所有人會先放在 A 區,請自行分配到 B 區
- 載入時會沿用名單去重邏輯,並清空 B 區與既有配對結果
`attendance` 表結構:
```sql
CREATE TABLE attendance (
poll_date INT(11) NOT NULL COMMENT '場次日期 YYYYMMDD',
user_id BIGINT NOT NULL COMMENT 'Telegram user id',
nickname VARCHAR(64) NOT NULL COMMENT '顯示名稱(就是要放進 personnel 的名字)',
tg_name VARCHAR(128) NULL COMMENT 'Telegram 顯示名',
joined_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '報名時間',
PRIMARY KEY (poll_date, user_id)
) CHARSET utf8mb4;
```
bot 另外還有 `tg_poll`(報名訊息 id)與 `tg_members`(暱稱記憶)兩張表,這個專案不會讀寫。
## 使用方式