Client 端的對戰系統,同時支援抽籤抽獎功能
概要
BattleTree 是一個純前端對戰賽程工具。它支援建立多份對戰表、設定參賽名單、依序或隨機產生賽程、分組賽程、三強循環決賽、季軍戰、對戰表縮放拖曳、勝者與比分紀錄、抽籤展示、JPG 匯出,以及可替換 Logo / 背景圖的風格設定。 目前沒有後端服務,對戰表資料存在 localStorage,圖片資產存在 IndexedDB。 - 首頁開場畫面,顯示 BattleTree Logo 與「開始對戰」按鈕。 - 重新整理後會保留目前所在頁面,不會強制回首頁。 - 支援 Chrome 式多對戰表分頁,可同時開啟多場比賽並快速切換;手機版使用下拉選單。 - 關閉分頁只會收起頁籤並保留資料,可從「所有對戰表」重新開啟;刪除才會永久移除。 - Header 左上角 Logo 可回首頁,並詢問是否保留目前輸入內容。 - 預設建立 4 位參賽者。 - 參賽人數最少 2 人,目前沒有 64 人限制。 - 支援匯入 Google 試算表匯出的 CSV,固定讀取 姓名 欄位並覆蓋目前名單。 - CSV 匯入旁提供教學彈窗,說明如何從 Google 表單與試算表下載 CSV。 - 編號由系統產生並顯示,不可編輯。 - 名單列支援移除參賽者、主辦確認報名狀態,以及手動重新排序參賽編號。 - 支援依序配對與隨機抽籤配對。 - 三種賽制:自由編排(預設,手選格數、空格自由填人)、單淘汰、預賽+淘汰(小組循環後晉級淘汰賽)。 - 自由編排支援 8/16/24/32/48/64 格;24/48 格會由三條平衡淘汰分支產生三強,再以循環賽決定前三名。 - 自由編排模式可將第一輪敗者填回空格再戰一次、手動新增選手、或將空格確認為輪空。 - 支援不分組、2 組、4 組、8 組(單淘汰)。 - 分組對戰表使用分頁切換組別與總決賽,避免大量組別同時擠在畫面上。 - 對戰表支援標準、橫向、分組視角。 - 四強敗者確定後會產生第三名爭奪戰,賽果完成後榮譽榜會列出冠軍、亞軍、季軍、第四名。 - 對戰表可拖曳平移、縮放、重置、適合畫面。 - 桌機支援全螢幕與下載 JPG。 - 手機版隱藏不適合手機的全螢幕與縮放控制,保留重置與適合畫面。 - 抽籤功能支援名單預覽、勾選排除、華麗抽籤動畫與抽中彩花。 - 風格設定支援多組主題、暗色模式、自訂 Header Logo、自訂背景圖片。
README
BattleTree
BattleTree 是一個純前端對戰賽程工具。它支援建立多份對戰表、設定參賽名單、依序或隨機產生賽程、分組賽程、三強循環決賽、季軍戰、對戰表縮放拖曳、勝者與比分紀錄、抽籤展示、JPG 匯出,以及可替換 Logo / 背景圖的風格設定。
目前沒有後端服務,對戰表資料存在 localStorage,圖片資產存在 IndexedDB。
功能特色
- 首頁開場畫面,顯示 BattleTree Logo 與「開始對戰」按鈕。
- 重新整理後會保留目前所在頁面,不會強制回首頁。
- 支援 Chrome 式多對戰表分頁,可同時開啟多場比賽並快速切換;手機版使用下拉選單。
- 關閉分頁只會收起頁籤並保留資料,可從「所有對戰表」重新開啟;刪除才會永久移除。
- Header 左上角 Logo 可回首頁,並詢問是否保留目前輸入內容。
- 預設建立 4 位參賽者。
- 參賽人數最少 2 人,目前沒有 64 人限制。
- 支援匯入 Google 試算表匯出的 CSV,固定讀取
姓名欄位並覆蓋目前名單。 - CSV 匯入旁提供教學彈窗,說明如何從 Google 表單與試算表下載 CSV。
- 編號由系統產生並顯示,不可編輯。
- 名單列支援移除參賽者、主辦確認報名狀態,以及手動重新排序參賽編號。
- 支援依序配對與隨機抽籤配對。
- 三種賽制:自由編排(預設,手選格數、空格自由填人)、單淘汰、預賽+淘汰(小組循環後晉級淘汰賽)。
- 自由編排支援 8/16/24/32/48/64 格;24/48 格會由三條平衡淘汰分支產生三強,再以循環賽決定前三名。
- 自由編排模式可將第一輪敗者填回空格再戰一次、手動新增選手、或將空格確認為輪空。
- 支援不分組、2 組、4 組、8 組(單淘汰)。
- 分組對戰表使用分頁切換組別與總決賽,避免大量組別同時擠在畫面上。
- 對戰表支援標準、橫向、分組視角。
- 四強敗者確定後會產生第三名爭奪戰,賽果完成後榮譽榜會列出冠軍、亞軍、季軍、第四名。
- 對戰表可拖曳平移、縮放、重置、適合畫面。
- 桌機支援全螢幕與下載 JPG。
- 手機版隱藏不適合手機的全螢幕與縮放控制,保留重置與適合畫面。
- 抽籤功能支援名單預覽、勾選排除、華麗抽籤動畫與抽中彩花。
- 風格設定支援多組主題、暗色模式、自訂 Header Logo、自訂背景圖片。
- 背景圖片支援多種呈現方式,包含完整顯示、填滿置中、填滿靠上、原始置中。
技術棧
- Vue 3
- Vite
- @vueuse/core
- GSAP
- html-to-image
- IndexedDB
- localStorage
快速開始
npm install
npm run dev
Vite 預設會啟動本機開發伺服器。此專案設定了 base path,開發時依終端機顯示 URL 開啟即可。
可用指令
npm run dev
啟動本機開發伺服器。
npm run build
建立正式版輸出,輸出目錄為 dist/。
npm run preview
預覽正式版建置結果。請先執行 npm run build。
npm test
執行對戰引擎的賽制回歸測試。
使用流程
- 在首頁點擊「開始對戰」。
- 使用分頁列的
+建立對戰表,先選擇賽制與空白/複製目前名單;也可從「所有對戰表」開啟既有資料。 - 在設定頁輸入比賽名稱。
- 設定參賽人數,系統會自動建立名單。
- 編輯選手姓名,或使用「匯入 CSV」從 Google 表單報名資料一次匯入。
- 可勾選綠色確認按鈕標記報名成功,或移除不需要的參賽者。
- 移除參賽者後,原參賽編號會先保留;需要連續編號時再點擊「重新排序參賽編號」。
- 選擇配對方式:
依序配對:依照編號排序後相鄰配對,例如 1 vs 2、3 vs 4。隨機抽籤:隨機分配選手,首輪會避開編號相鄰的選手對上。
- 選擇分組數:
不分組2 組4 組8 組
- 點擊「產生對戰表」。
- 在對戰表中點擊勝者按鈕推進下一輪。
- 已有結果的比賽可輸入比分。
- 需要輸出時,在桌機使用全螢幕或下載 JPG。
CSV 匯入
設定頁的「匯入 CSV」可讀取 Google 表單回覆試算表匯出的 CSV。
規格:
- CSV 第一列必須是欄位名稱。
- 只讀取欄位名稱完全等於
姓名的欄位。 - 匯入後會覆蓋目前名單。
- 參賽人數自動等於有效姓名筆數。
- 編號會重新由 1 開始依序產生。
- 空白姓名列會被忽略。
- 至少需要 2 位有效參賽者。
- 支援標準 CSV 引號格式,例如姓名中包含逗號或雙引號。
- 匯入按鈕旁的「教學」會開啟操作說明,指引使用者從 Google 表單回覆開啟試算表,並下載
逗號分隔值檔案 (.csv)。
名單管理
- 每位參賽者包含姓名、參賽編號與報名確認狀態。
- 參賽編號只顯示不可編輯,必須是正整數且不可重複。
- 綠色勾勾代表主辦單位已確認該參賽者報名成功。
- 移除參賽者會直接刪除該列,後方名單往上遞補,但原參賽編號會保留。
- 「重新排序參賽編號」會依目前名單順序重新編為 1、2、3。
- 匯入 CSV 會覆蓋目前名單,並將報名確認狀態全部設為未確認。
對戰表規則
- 支援單淘汰、預賽+淘汰、自由編排三種賽制。
- 單淘汰:參賽人數不必剛好是 2 的次方,系統會補齊到下一個 2 的次方(例如 9 人會產生 16 人表),空位視為 bye 自動晉級、輪空平均分散左右半區。
- 空對空分支會隱藏,不會形成等待中的比賽。
- 預賽+淘汰:先分組循環累積戰績,各組第 1 名(不足時補成績最佳第 2 名)晉級固定規模淘汰賽,淘汰賽零輪空。
- 自由編排:主辦手動選 8/16/24/32/48/64 格,名單先排入並平均分佈;空格的對戰顯示「待定」不自動晉級,主辦可填入名單剩餘者、第一輪敗者(再戰一次)、手動新增的選手,或將該格確認為輪空。
- 24/48 格自由編排分別由三條 8/16 格淘汰分支組成,各分支產生 1 名三強選手;三強互打 3 場後依「勝場 → 兩人同勝場時直接對戰 → 得失分差 → 總得分 → 編號」排名。三人各 1 勝 1 敗時必須補齊比分。
- 自由編排可在單一待定格中隨機選擇 1 位可用的第一輪敗者,也提供「隨機填入敗者」與「剩餘全部輪空」批次操作;已填的格位可隨時換人或清空,受影響的下游成績會先告知場數並確認後連鎖清除。
- 標準淘汰樹若有兩位四強敗者,系統會產生第三名爭奪戰;24/48 格則由三強循環直接產生前三名。
- 冠軍戰與第三名爭奪戰都有結果後,榮譽榜會列出前四名。
- 修改選手、移除選手、重新排序編號、配對方式、分組數後,已產生的對戰表會回到設定狀態並清空既有賽果。
- 改變某場勝者時,後續輪次中不合法的結果會被清除,避免晉級資料不一致。
- 分組時會先在各組內產生小型單淘汰表,再由各組勝者進入總決賽。
視角與操作
對戰表目前有三種呈現方式:
標準:縱向樹狀,由下往上收斂到冠軍。橫向:以橫向輪次排列,適合部分寬螢幕檢視。分組:分頁顯示各組與總決賽,適合大量參賽者。
操作能力:
- 滑鼠拖曳平移。
- 滾輪縮放。
- 桌機工具列可縮小、放大、重置、適合畫面。
- 手機保留重置與適合畫面,避免工具列過度擁擠。
- 勝者選取不會自動把畫面重設成適合畫面。
抽籤功能
工具列的「抽籤」會開啟抽籤展示視窗。
名單來源包含:
- 全部選手。
- 已有結果的指定輪次敗者。
抽籤流程:
- 先顯示名單預覽。
- 名單預設全部勾選。
- 取消勾選會把該人移出本次抽籤名單,卡片透明度降至 40%。
- 開始抽籤後不可再修改名單。
- 抽籤舞台顯示抽籤狀態與抽籤池。
- 抽中時顯示彩花動畫。
- 抽中者移入已抽出清單。
風格設定
Header 最右側與首頁桌機右上角有風格按鈕。點擊後會開啟風格設定彈窗。
彈窗包含:
- 主題色方格選項。
- 上傳 Header Logo。
- 還原 Header Logo。
- 上傳背景圖片。
- 移除背景圖片。
- 背景圖片呈現方式。
目前主題:
- 黑白灰
- 暗色模式
- 冷藍
- 森林
- 赤銅
Logo 規格:
- 只替換進入網站後 Header 左上角 Logo。
- 首頁 BattleTree Logo 永遠保持預設,不會被商家 Logo 替換。
- 暗色模式不會改變自訂 Logo 顏色,上傳什麼就顯示什麼。
- Logo 檔案大小上限為 2MB。
背景圖規格:
- 背景圖會以固定層蓋在頁面後方。
- 目前背景圖透明度為 50%。
- 對戰表 viewport 本身有 30% 透明主題底色,讓背景圖仍可透出。
- 背景圖檔案大小上限為 6MB。
- 背景圖呈現方式:
完整:前景圖片完整顯示;背後同圖用cover放大填滿、水平垂直置中並blur(6px)。填滿:cover,水平垂直置中。靠上:cover,水平置中並對齊上方。原始:原始大小,水平垂直置中。
資料儲存
BattleTree 不需要後端服務。
localStorage:
battletree:brackets:所有對戰表資料。battletree:currentId:目前選取的對戰表 ID。battletree:openTabs:目前開啟的對戰表分頁 ID 與順序。battletree:view:目前停留在首頁或應用頁。battletree:theme:目前主題。battletree:background-fit:背景圖片呈現方式。
IndexedDB:
- DB:
battletree-images - Object store:
images custom-logo:自訂 Header Logo 圖片 Blob。background-image:自訂背景圖片 Blob。
圖片顯示時會使用 URL.createObjectURL(blob) 產生暫時 URL,替換或移除時會釋放舊 object URL。
資料只存在目前瀏覽器與目前網域中。若清除瀏覽器資料、更換瀏覽器或更換裝置,資料不會自動同步。
專案結構
.
├── public/
│ ├── favicon.svg
│ └── logo.png
├── src/
│ ├── assets/
│ │ ├── logo.svg
│ │ └── logo-w.svg
│ ├── components/
│ │ ├── BracketTabs.vue
│ │ ├── BracketListModal.vue
│ │ ├── BracketSetup.vue
│ │ ├── BracketView.vue
│ │ ├── LotteryModal.vue
│ │ ├── MatchCard.vue
│ │ ├── NewBracketModal.vue
│ │ ├── PlayerSlot.vue
│ │ ├── ScorePopover.vue
│ │ ├── ThemePicker.vue
│ │ └── Toolbar.vue
│ ├── constants/
│ │ └── bracketOptions.js
│ ├── composables/
│ │ ├── useBracketEngine.js
│ │ ├── useBracketExport.js
│ │ ├── useBrackets.js
│ │ ├── useImageStorage.js
│ │ ├── useLottery.js
│ │ └── usePanZoom.js
│ ├── App.vue
│ ├── main.js
│ └── style.css
├── package.json
├── package-lock.json
├── vite.config.js
└── README.md
核心模組說明
src/App.vue:應用主入口,管理首頁/應用狀態、主題、圖片資產、工具列、設定頁、對戰表與彈窗。src/components/Toolbar.vue:Header 工具列與風格設定入口。src/components/BracketTabs.vue:桌機分頁列與手機對戰表下拉切換。src/components/NewBracketModal.vue:選擇賽制及空白/複製名單後建立新分頁。src/components/ThemePicker.vue:風格設定彈窗,處理主題切換、Logo 上傳、背景上傳與背景模式切換。src/components/BracketSetup.vue:比賽名稱、參賽人數、配對方式、分組數與選手名單設定。src/components/BracketView.vue:對戰表畫布、視角切換、SVG 連線、分組分頁、縮放拖曳與冠軍顯示。src/components/MatchCard.vue:單場比賽卡片。src/components/PlayerSlot.vue:選手顯示、勝敗狀態與晉級按鈕。src/components/ScorePopover.vue:比分輸入。src/components/LotteryModal.vue:抽籤展示與抽籤動畫。src/composables/useBracketEngine.js:賽程大小、相鄰配對、bye、分組、季軍戰、晉級、冠軍與賽果清理等核心邏輯。src/composables/useBrackets.js:對戰表 CRUD、localStorage 儲存、選手更新、分組更新、自由編排格位操作與賽果更新。src/composables/useImageStorage.js:IndexedDB 圖片儲存。src/composables/useBracketExport.js:全螢幕與 JPG 匯出。src/composables/useLottery.js:抽籤名單、動畫狀態與抽出結果管理。src/composables/usePanZoom.js:對戰表平移與縮放操作。
注意事項
- 目前沒有帳號系統、伺服器同步或多人協作功能。
- JPG 匯出使用目前對戰表 DOM 為來源,並以 2 倍 pixel ratio 輸出。
- 全螢幕能力取決於瀏覽器 Fullscreen API;手機版已隱藏相關按鈕。
- localStorage / IndexedDB 均屬瀏覽器本地資料,不適合跨裝置同步。
推奨ツール
別のキーワードを試すか、フィルタを外してください。
インストール
npx skillfish add mikecheng1208/battletree