一個互動式的聖誕節交換禮物抽獎網頁應用程式,支援主持模式和多人連線模式。
當前版本: v0.12.0
線上體驗: https://lucky-draw-4s24.onrender.com/
GitHub: https://github.com/mechaserpent/lucky-draw
聯繫: maverick.hlc
- 抽到誰的禮物,就換誰抽!
- 使用 Mulberry32 PRNG 確保隨機性和可重複性
- Derangement 演算法確保不會抽到自己的禮物
- 由主持人操作所有抽獎流程
- 適合投影到大螢幕給所有人觀看
- 支援 2-100 人參與
- 可自訂參與者名單
- 進階選項:可設定特定配對(需密碼驗證)
- 🔒 資料僅存在本地瀏覽器
- 每個人用自己的裝置加入房間
- 輪到時自己按下抽獎按鈕
- 即時同步抽獎過程給所有人
- 主機可協助加入虛擬玩家
- 主機可強制開始遊戲
- 支援觀眾模式和斷線重連
⚠️ 資料暫存於伺服器資料庫,房間關閉後 30 分鐘自動清除
- 管理員密碼保護重置功能
- Seed 持久化,重新整理不影響結果
- 斷線重連令牌(24 小時有效)
npm installnpm run devnpm run buildnpm run previewdraw/
├── app/
│ ├── pages/
│ │ ├── index.vue # 首頁 - 模式選擇
│ │ ├── solo.vue # 主持模式
│ │ └── online.vue # 連線模式
│ ├── components/
│ │ ├── RouletteAnimation.vue # 輪盤抽獎動畫
│ │ ├── AdvancedSettings.vue # 進階固定配對設定
│ │ ├── PasswordModal.vue # 密碼輸入模態框
│ │ ├── SettingsPanel.vue # 房間設定面板
│ │ ├── AppSettingsPanel.vue # 應用程式設定面板
│ │ └── SocialShareModal.vue # 社交分享模態框
│ ├── composables/
│ │ ├── useGameState.ts # 遊戲狀態管理
│ │ ├── useWebSocket.ts # WebSocket 連線管理
│ │ ├── useDynamicConfig.ts # 動態配置管理
│ │ ├── useHistory.ts # 歷史記錄管理
│ │ └── useSiteConfig.ts # 網站配置
│ ├── layouts/
│ │ └── default.vue # 預設版面配置
│ └── app.vue # 根組件
├── server/
│ ├── routes/
│ │ └── ws.ts # WebSocket 伺服器端點
│ ├── database/
│ │ ├── index.ts # 資料庫連線
│ │ └── schema.ts # Drizzle ORM schema
│ └── services/
│ └── roomService.ts # 房間管理服務
├── i18n/
│ └── locales/
│ ├── zh-HK.json # 繁體中文翻譯
│ └── en.json # 英文翻譯
├── .env.example # 環境配置範例
├── nuxt.config.ts # Nuxt 配置
└── package.json
複製 .env.example 為 .env 開始設定:
cp .env.example .env| 變數 | 預設值 | 說明 |
|---|---|---|
NUXT_PUBLIC_SITE_TITLE |
聖誕交換禮物抽獎 | 網站標題 |
NUXT_PUBLIC_SITE_SUBTITLE |
連鎖式抽獎... | 網站副標題 |
NUXT_PUBLIC_SITE_ICON_LEFT |
🎄 | 左側圖示 |
NUXT_PUBLIC_SITE_ICON_RIGHT |
🎁 | 右側圖示 |
| 變數 | 預設值 | 說明 |
|---|---|---|
NUXT_PUBLIC_MIN_PLAYERS |
2 | 最小人數 |
NUXT_PUBLIC_MAX_PLAYERS |
100 | 主持模式最大人數 |
NUXT_PUBLIC_ONLINE_MAX_PLAYERS |
50 | 連線模式最大人數 |
NUXT_PUBLIC_ROOM_CODE_LENGTH |
6 | 房間代碼長度 |
| 變數 | 預設值 | 說明 |
|---|---|---|
NUXT_PUBLIC_THEME_PRIMARY |
#BF092F | 主色調(主要按鈕、重要元素) |
NUXT_PUBLIC_THEME_SECONDARY |
#3B9797 | 次要色調(次要按鈕、輔助元素) |
NUXT_PUBLIC_THEME_ACCENT |
#62B6B7 | 強調色(高亮、懸停效果) |
| 變數 | 預設值 | 說明 |
|---|---|---|
NUXT_PUBLIC_THEME_BG_FROM |
#102A43 | 背景漸層起始(深藍色) |
NUXT_PUBLIC_THEME_BG_TO |
#16476A | 背景漸層結束(中藍色) |
NUXT_PUBLIC_THEME_BG_DEEP |
#132440 | 深色背景(模態框、陰影) |
| 變數 | 預設值 | 說明 |
|---|---|---|
NUXT_PUBLIC_THEME_SURFACE |
rgba(255,255,255,0.08) | 卡片基礎表面 |
NUXT_PUBLIC_THEME_SURFACE_LIGHT |
rgba(255,255,255,0.12) | 較亮表面 |
NUXT_PUBLIC_THEME_SURFACE_HOVER |
rgba(255,255,255,0.16) | 懸停效果 |
| 變數 | 預設值 | 說明 |
|---|---|---|
NUXT_PUBLIC_THEME_TEXT |
#FFFFFF | 主要文字(純白) |
NUXT_PUBLIC_THEME_TEXT_SECONDARY |
rgba(255,255,255,0.8) | 次要文字 |
NUXT_PUBLIC_THEME_TEXT_MUTED |
rgba(255,255,255,0.5) | 弱化文字 |
| 變數 | 預設值 | 說明 |
|---|---|---|
NUXT_PUBLIC_THEME_SUCCESS |
#3B9797 | 成功狀態(青綠色) |
NUXT_PUBLIC_THEME_WARNING |
#F59E0B | 警告狀態(琥珀色) |
NUXT_PUBLIC_THEME_DANGER |
#BF092F | 危險/錯誤狀態(深紅色) |
NUXT_PUBLIC_THEME_INFO |
#62B6B7 | 資訊狀態(亮青色) |
| 變數 | 預設值 | 說明 |
|---|---|---|
NUXT_PUBLIC_FEATURES_SNOWFLAKES |
true | 雪花動畫 |
NUXT_PUBLIC_FEATURES_PASSWORD_PROTECTION |
false | 密碼保護(進階選項) |
本專案採用完整的設計系統,支援動態主題切換。詳細資訊請參閱 DESIGN_SYSTEM.md
特色:
- 16+ 個主題變數,完整控制視覺風格
- 毛玻璃效果(Glassmorphism)
- 動態光暈與背景動畫
- 按鈕光掃效果
- 自適應陰影系統
- 響應式設計支援
內建主題預設:
- 🎄 聖誕主題(紅綠配色)
- 🧧 新年主題(金紅配色)
- 🎉 派對主題(紫藍配色)
在 nuxt.config.ts 中配置:
- 預設語言:
zh-HK(香港繁體中文) - 支援語言:
zh-HK,en - 語言檔案位於
locales/目錄 - Cookie 儲存語言偏好(
i18n_locale)
年終活動主題:
NUXT_PUBLIC_SITE_TITLE=年終交換禮物
NUXT_PUBLIC_SITE_ICON_LEFT=🎊
NUXT_PUBLIC_MAX_PLAYERS=200新年主題:
NUXT_PUBLIC_SITE_TITLE=新年交換禮物
NUXT_PUBLIC_SITE_ICON_LEFT=🧧
NUXT_PUBLIC_THEME_PRIMARY=#d4af37
NUXT_PUBLIC_THEME_BG_FROM=#8b0000
NUXT_PUBLIC_FEATURES_SNOWFLAKES=false-
編輯
.env檔案# Windows notepad .env # Mac/Linux nano .env
-
修改相關設定值
- 改變標題:
NUXT_PUBLIC_SITE_TITLE - 改變圖示:
NUXT_PUBLIC_SITE_ICON_LEFT和NUXT_PUBLIC_SITE_ICON_RIGHT - 改變主色調:
NUXT_PUBLIC_THEME_PRIMARY(影響按鈕顏色) - 改變背景:
NUXT_PUBLIC_THEME_BG_FROM和NUXT_PUBLIC_THEME_BG_TO - 關閉雪花:
NUXT_PUBLIC_FEATURES_SNOWFLAKES=false
- 改變標題:
-
重新啟動伺服器
# 停止目前的伺服器 (Ctrl+C) # 重新啟動 npm run dev
-
色彩選擇建議
- 使用 Color Hunt 或 Coolors 尋找配色靈感
- 主色 (
THEME_PRIMARY) 應與背景有足夠對比度 - 背景漸層的兩個顏色不要差異太大,以免刺眼
- 在首頁選擇「主持模式」
- 設定參與人數(或手動編輯參與者名單)
- 首次使用需設定管理員密碼
- 點擊「開始抽獎」
- 依序點擊「抽獎」和「下一位」按鈕
- 主機選擇「連線模式」→「建立新房間」
- 輸入名字和人數上限
- 分享房間代碼給其他參與者
- 其他人選擇「加入房間」輸入代碼和名字
- 所有人準備好後,主機點擊「開始遊戲」
- 輪到誰就由誰按下抽獎按鈕
- 執行環境: Node.js v22.20.0
- 框架: Nuxt 4.2.2
- 前端: Vue 3.5.25
- 建置工具: Vite 7.3.0
- 伺服器: Nitro 2.12.9
- 即時通訊: WebSocket (Nitro 內建支援)
- 資料庫: SQLite + better-sqlite3
- ORM: Drizzle ORM 0.38.4
- 狀態管理: Vue Composables + localStorage
- 在主持模式設定頁面點擊「進階選項」
- 輸入管理員密碼
- 選擇 A → B 的配對(A 會抽到 B 的禮物)
- 此功能設計為隱藏,不會在介面上明顯顯示
- 需要管理員密碼
- 會生成新的隨機種子
- 建議在開始前設定好,避免中途更改
# 開啟 Drizzle Studio(資料庫 GUI)
npm run db:studio
# 訪問 http://localhost:4983如果需要完全重置資料庫(清除所有房間和玩家資料):
# 方法一:刪除資料庫檔案(推薦)
# Windows
del server\database\lucky-draw.db
# Mac/Linux
rm server/database/lucky-draw.db
# 重新啟動應用程式,資料庫會自動重建
npm run dev
# 方法二:在生產環境
# 停止服務
pm2 stop lucky-draw
# 刪除資料庫
rm .output/server/lucky-draw.db
# 重新啟動
pm2 start lucky-draw💡 注意: 刪除資料庫會清除所有房間資料,但不影響用戶的本地設定(儲存在瀏覽器 localStorage)。
本應用已針對低配置環境(512MB RAM / 0.1-1 CPU)進行優化:
啟動應用時會自動:
- 創建數據庫性能索引
- 配置 SQLite 最佳化參數(WAL 模式、64MB 緩存)
- 啟用 GPU 加速的 CSS 動畫
- 優化雪花動畫(20個,GPU 加速)
| 環境 | 支持房間數 | 內存使用 | CPU使用 |
|---|---|---|---|
| 512MB/0.1CPU | 10-15 | ~150MB | ~20% |
| 1GB/1CPU | 30-50 | ~200MB | ~15% |
| 2GB/2CPU | 100+ | ~350MB | ~10% |
# 方式 1:查看啟動日誌
npm run dev
# 應該看到:[DB] Database initialized with performance optimizations
# 方式 2:運行驗證腳本
node scripts/apply-optimizations.js
# 顯示所有已創建的索引和統計信息本專案使用 Nuxt 4 + SQLite,需要支援 Node.js 伺服器環境的平台部署(因為使用 WebSocket 和本地資料庫)。
- Node.js: v22.x 或更高版本
- npm: v10.x 或更高版本
# 1. 安裝依賴(會自動執行 postinstall 初始化 Nuxt)
npm install
# 2. 啟動開發伺服器(資料庫會在首次啟動時自動建立)
npm run dev
# 開發伺服器會在 http://localhost:8000 啟動💡 注意: 資料庫檔案
lucky-draw.db會在server/database/目錄自動建立,無需手動初始化。
- 在 Render 註冊帳號
- 連接你的 GitHub 儲存庫
- 建立新的「Web Service」
- 設定:
- Build Command:
npm ci && npm run build - Start Command:
node .output/server/index.mjs - Environment:
Node - Node Version:
22
- Build Command:
- 新增環境變數(可選,在 Environment 頁面設定)
- 點擊 Deploy
⚠️ Render 免費方案注意: 服務會在閒置 15 分鐘後休眠,SQLite 資料庫會在重新部署時重置。
- 在 Railway 註冊帳號
- 從 GitHub 建立新專案
- Railway 會自動偵測 Nuxt 專案
- 設定:
- Build Command:
npm ci && npm run build - Start Command:
node .output/server/index.mjs
- Build Command:
- 設定環境變數(如需要)
- 自動部署
# 安裝 flyctl
npm install -g flyctl
# 登入
fly auth login
# 建立應用程式
fly launch
# 部署
fly deploy# 確保 Node.js v22+ 已安裝
node -v # 應顯示 v22.x.x
# 克隆專案
git clone https://github.com/mechaserpent/lucky-draw.git
cd lucky-draw
# 安裝依賴(會自動執行 postinstall)
npm ci
# 建置生產版本
npm run build
# 使用 PM2 管理程序
npm install -g pm2
pm2 start .output/server/index.mjs --name "lucky-draw"
pm2 save
pm2 startup💡 資料庫位置: 生產環境的 SQLite 資料庫會建立在
.output/server/目錄下。
以下平台不支援 WebSocket 或 SQLite,無法使用連線模式:
- Vercel(Serverless 函數不支援持久連線和本地資料庫)
- Netlify(同上)
- GitHub Pages(純靜態)
- Cloudflare Workers(不支援 SQLite)
如果只需要主持模式,可以使用靜態部署:
# 修改 nuxt.config.ts,設定 ssr: false
npm run generate
# 將 .output/public 部署到任何靜態伺服器在部署平台設定以下環境變數(全部可選):
NUXT_PUBLIC_SITE_TITLE- 網站標題NUXT_PUBLIC_SITE_ICON_LEFT- 左側圖示NUXT_PUBLIC_SITE_ICON_RIGHT- 右側圖示NUXT_PUBLIC_THEME_PRIMARY- 主題色NUXT_PUBLIC_FEATURES_SNOWFLAKES- 是否顯示雪花
| 指令 | 說明 |
|---|---|
npm install |
安裝依賴(含 postinstall) |
npm run dev |
啟動開發伺服器 (localhost:8000) |
npm run build |
建置生產版本 |
npm run preview |
預覽生產版本 |
npm run db:studio |
開啟資料庫 GUI (localhost:4983) |
npm run db:push |
推送 schema 變更到資料庫 |
- 聖誕節主題配色(紅綠金)
- 雪花動畫背景
- 響應式設計,支援手機和電腦
- 抽獎動畫效果
- 完成時彩帶慶祝動畫
MIT License
🎁 祝大家聖誕快樂!Merry Christmas! 🎄