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>
58 lines
1.7 KiB
JavaScript
58 lines
1.7 KiB
JavaScript
// 從 git log 產生更新紀錄資料,輸出到 src/data/changelog.json
|
||
// 正式版(build 後)沒有 git 也能直接讀 JSON 顯示;dev 與 build 前會自動重新產生。
|
||
import { execFileSync } from 'node:child_process'
|
||
import { mkdirSync, writeFileSync } from 'node:fs'
|
||
import { dirname, resolve } from 'node:path'
|
||
import { fileURLToPath } from 'node:url'
|
||
|
||
const here = dirname(fileURLToPath(import.meta.url))
|
||
const outFile = resolve(here, '../src/data/changelog.json')
|
||
|
||
const UNIT = '\x1f' // 欄位分隔(unit separator)
|
||
const RECORD = '\x1e' // 紀錄分隔(record separator)
|
||
|
||
function readGitLog() {
|
||
const format = ['%H', '%h', '%ad', '%s', '%b'].join(UNIT) + RECORD
|
||
const raw = execFileSync(
|
||
'git',
|
||
['log', `--pretty=format:${format}`, '--date=format:%Y-%m-%d'],
|
||
{ cwd: resolve(here, '..'), encoding: 'utf8', maxBuffer: 1024 * 1024 * 16 },
|
||
)
|
||
|
||
return raw
|
||
.split(RECORD)
|
||
.map((chunk) => chunk.replace(/^\s+/, ''))
|
||
.filter(Boolean)
|
||
.map((chunk) => {
|
||
const [hash, shortHash, date, subject, body = ''] = chunk.split(UNIT)
|
||
return {
|
||
hash,
|
||
shortHash,
|
||
date,
|
||
subject: subject.trim(),
|
||
body: body.trim(),
|
||
}
|
||
})
|
||
}
|
||
|
||
function main() {
|
||
let entries = []
|
||
|
||
try {
|
||
entries = readGitLog()
|
||
} catch (error) {
|
||
console.warn('[generate-changelog] 讀取 git log 失敗,輸出空清單:', error.message)
|
||
}
|
||
|
||
const payload = {
|
||
generatedAt: new Date().toISOString(),
|
||
entries,
|
||
}
|
||
|
||
mkdirSync(dirname(outFile), { recursive: true })
|
||
writeFileSync(outFile, JSON.stringify(payload, null, 2) + '\n', 'utf8')
|
||
console.log(`[generate-changelog] 已輸出 ${entries.length} 筆更新紀錄到 ${outFile}`)
|
||
}
|
||
|
||
main()
|