統一發票對獎器(React)
台灣統一發票對獎的 React 元件:輸入發票號碼末 3 碼或全 8 碼即時比對獎號(獎號由 props 提供),中獎噴彩帶、獎金滾動、獎項徽章,未中獎則溫和搖頭並可一鍵再對下一張。
這是 WebberUI Pro 元件
上線活動期間免費:註冊或登入後,在上方預覽區按「複製安裝指令」就能直接安裝,不需付費、不用綁信用卡。下方那條指令未登入時會回 401。
台灣統一發票每兩個月開獎一次,對獎是全民活動。這個元件把「期別標題+ 8 格數字輸入+結果面板」包成一個自足的對獎器:獎號由 prizes 傳入,內建 matchInvoice() 依財政部公告的給獎規則判定特別獎、特獎、頭獎系列(末 8~3 碼)與增開六獎;也支援只輸入末 3 碼的快速模式(僅能判定六獎/增開六獎,並提示補完整號碼確認更高獎項)。中獎時彩帶粒子噴發、獎金以滾動數字呈現並掛上獎項徽章;未中獎則是溫和的搖頭動畫與「再對下一張」按鈕。輸入格為 OTP 式獨立格:自動跳格、貼上自動分配、inputMode="numeric"、Backspace 回退。
載入預覽⋯
npx shadcn@latest add "https://webberui.com/r/invoice-lottery-checker.json?t=<安裝 token>"Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<InvoiceLotteryChecker />
安裝
npx shadcn@latest add "https://webberui.com/r/invoice-lottery-checker.json?t=<安裝 token>"或在 components.json 設定 registries 後,改用 @webberui/invoice-lottery-checker 安裝。
使用
import {
InvoiceLotteryChecker,
matchInvoice,
} from "@/components/ui/invoice-lottery-checker";
// 示範獎號,非真實開獎結果——正式使用時請改由後端或財政部公開資料餵入
const prizes = {
special: "13579246",
grand: "24680135",
first: ["11223344", "55667788", "99001122"],
additionalSixth: ["357", "802"],
};
<InvoiceLotteryChecker
prizes={prizes}
period="115 年 5–6 月"
onResult={(result, number) =>
console.log(number, result.prize, result.amount)
}
note="示範獎號,非真實開獎結果"
/>
// 對獎函式可單獨使用(例如批次對整疊發票)
matchInvoice("10203788", prizes); // { prize: "sixth", amount: 200, matchedDigits: 3, partial: false }
matchInvoice("788", prizes); // { prize: "sixth", amount: 200, matchedDigits: 3, partial: true }Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
prizes | InvoicePrizes | — | 本期獎號(特別獎、特獎、頭獎三組、增開六獎) |
period | string | "本期統一發票" | 期別標題,例如「115 年 5–6 月」 |
mode | "full" | "last3" | "full" | 對獎模式:full 輸入完整 8 碼;last3 只輸入末 3 碼(僅能判定六獎/增開六獎) |
value | string | — | 受控值(僅數字);不提供時為非受控模式 |
defaultValue | string | "" | 非受控模式的初始值 |
onChange | (value: string) => void | — | 值變動時回呼,參數為清洗後的純數字字串 |
onResult | (result: InvoiceMatchResult, number: string) => void | — | 每次完成對獎時回呼(自動或手動皆會觸發) |
autoCheck | boolean | true | 輸入滿格後自動對獎;為 false 時需按「對獎」按鈕或 Enter |
showConfetti | boolean | true | 中獎時是否噴發彩帶 |
showPrizes | boolean | true | 是否在下方列出本期獎號 |
note | string | — | 底部備註文字,例如「示範獎號,非真實開獎結果」 |
className | string | — | 透傳到最外層容器 |
InvoicePrizes
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
special | string | — | 特別獎號碼(8 碼) |
grand | string | — | 特獎號碼(8 碼) |
first | string[] | — | 頭獎號碼(8 碼 × 3 組) |
additionalSixth | string[] | — | 增開六獎號碼(3 碼,可多組) |
InvoiceMatchResult
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
prize | InvoicePrizeTier | — | 中獎層級:"special"、"grand"、"first"、"second"、"third"、"fourth"、"fifth"、"sixth"、"additionalSixth";未中獎為 null |
amount | number | — | 獎金(新台幣元);未中獎為 0 |
matchedDigits | number | — | 與中獎號碼相符的末幾碼數;未中獎為 0 |
partial | boolean | — | 是否只以末 3 碼比對(號碼未滿 8 碼);為 true 時更高獎項尚未確認 |
另外具名匯出 matchInvoice(number, prizes)、sanitizeInvoiceNumber(raw, maxLength?)、INVOICE_PRIZE_LABELS(獎項中文名稱)、INVOICE_PRIZE_AMOUNTS(各獎項獎金)與 InvoicePrizeTier 型別,方便在表單層或批次對獎時重複使用同一套規則。
細節
- 給獎規則:特別獎 8 碼全中 1,000 萬;特獎 8 碼全中 200 萬;頭獎三組任一組——8 碼全中 20 萬、末 7 碼 4 萬、末 6 碼 1 萬、末 5 碼 4,000、末 4 碼 1,000、末 3 碼 200(六獎);增開六獎末 3 碼 200。多組同時符合時取最高獎項
- 只輸入 3 碼時(
mode="last3"),只能判定六獎/增開六獎,中獎面板改為提示「末三碼相符,請輸入完整號碼確認更高獎項」,onResult收到的partial為true - 結果面板只在「號碼與對獎當下一致」時顯示:使用者一按 Backspace 改動號碼,面板就自動收起;
autoCheck下同一個滿格號碼只會對一次,改動後再滿格才會重對 - 彩帶粒子以 motion 小方塊自行實作,不依賴其他元件;每片的散落位置、旋轉與大小由確定性偽隨機算出,render 期間不呼叫
Math.random,SSR 與 CSR 輸出一致 - 8 碼模式把末 3 格稍微隔開並在頭獎列表加粗末 3 碼——那是六獎的判定依據,一眼就能核對
- 元件不內建任何真實獎號:正式使用時請由後端或財政部公開資料餵入
prizes;示範與 playground 使用的全是虛構號碼並以note標明
可及性
- 實際輸入由單一原生
input承載(inputMode="numeric"、pattern="[0-9]*"、maxLength),視覺格子僅為展示並以aria-hidden隱藏,鍵盤與行動裝置數字鍵盤行為與一般輸入框一致;label以htmlFor綁定 - 對獎結果置於
role="status"加aria-live="polite"區域,中獎層級、獎金與提示都會被螢幕閱讀器朗讀;輸入框以aria-describedby指向該區域 - 「對獎」與「再對下一張」皆為
type="button",具focus-visible環;Enter 鍵可手動對獎,並已處理中文輸入法組字中的 Enter(isComposing與 Safari 的keyCode 229) - 使用者系統開啟「減少動態效果」時,停用彩帶、獎金滾動、搖頭、格子彈入與游標閃爍動畫,直接顯示最終結果與文字