WebberUI

金額大寫輸入框(React)

輸入阿拉伯數字金額即時鏡射「新臺幣壹萬貳仟元整」大寫的 React 元件:千分位格式化、角分處理、一鍵複製,並具名匯出 toChineseUpper 轉換函式,支票、收據、合約、報價單都能直接用。

支票、收據、合約、報價單都要「金額大寫」。這個元件把數字輸入框(inputMode="decimal"、只收數字與一個小數點、最多兩位小數、輸入時自動千分位)和下方的大寫鏡射列綁在一起:每敲一個數字,「新臺幣壹萬貳仟元伍角整」逐字更新——只有變動的字會動,前綴與高位字保持不動;右側複製鈕一鍵複製全文,成功打勾。轉換規則寫成獨立的 toChineseUpper() 純函式,數字 零壹貳參肆伍陸柒捌玖、位 拾佰仟、節 萬億兆、小數 角分,連續零合併、節末零省略、「壹拾」保留,最大支援到兆。

載入預覽⋯
npx shadcn@latest add https://webberui.com/r/chinese-amount-input.json

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

<ChineseAmountInput />

安裝

npx shadcn@latest add https://webberui.com/r/chinese-amount-input.json

或在 components.json 設定 registries 後,改用 @webberui/chinese-amount-input 安裝。

使用

import {
  ChineseAmountInput,
  toChineseUpper,
} from "@/components/ui/chinese-amount-input";

<ChineseAmountInput
  label="報價總額(含稅)"
  prefix="新臺幣"
  onChange={(raw, { upper, formatted, amount }) => {
    console.log(raw); // "12000.5"
    console.log(formatted); // "12,000.5"
    console.log(upper); // "新臺幣壹萬貳仟元伍角整"
    console.log(amount); // 12000.5
  }}
/>

// 轉換函式可單獨使用(例如列印支票或產生 PDF 時)
toChineseUpper(120000.5); // "壹拾貳萬元伍角整"
toChineseUpper("100000001", { prefix: "人民幣" }); // "人民幣壹億零壹元整"
toChineseUpper("1,680.32"); // "壹仟陸佰捌拾元參角貳分"(千分位逗號會被清掉)

Props

Prop型別預設值說明
valuestring | number受控值:純數字字串(如 "12000.5")或 number;不提供時為非受控模式
defaultValuestring | number""非受控模式的初始值
onChange(raw: string, meta: ChineseAmountChangeDetail) => void值變動時回呼:第一個參數為清洗後的純數字字串,第二個為大寫/千分位/數值
prefixstring"新臺幣"大寫前綴幣別(如「人民幣」);傳空字串則不加
allowDecimalbooleantrue是否允許小數(角分);false 時只接受整數
maxnumber金額上限;超過時顯示錯誤提示並設定 aria-invalid(不會阻止輸入)
labelstring"金額"欄位標籤文字
placeholderstring"0"輸入框佔位提示
disabledbooleanfalse停用輸入
namestring透傳給原生 input 的表單欄位名稱
classNamestring透傳到最外層容器

ChineseAmountChangeDetail

欄位型別預設值說明
upperstring含 prefix 的完整大寫;超出「兆」時為 ""
formattedstring千分位格式化後的顯示字串
amountnumber解析後的數值;空值為 0

toChineseUpper(amount, opts?)

toChineseUpper(amount: number | string, opts?: ToChineseUpperOptions): string——接受 number 或字串(字串可含千分位逗號、全形數字)。空字串或非數字回傳 "";負數或整數超過 16 位(兆)丟出 RangeError。數字輸入四捨五入到分,字串輸入超過兩位小數則截斷(與輸入框行為一致)。

欄位型別預設值說明
prefixstring""幣別前綴,如「新臺幣」「人民幣」
allowDecimalbooleantrue是否處理角分;false 時直接捨去小數部分

另外具名匯出 sanitizeAmount(raw, allowDecimal?)(清洗為純數字字串)、formatAmount(raw)(加千分位)與常數 MAX_AMOUNT_INT_DIGITS16)。

細節

轉換規則對照(不帶 prefix):

輸入輸出
0零元整
10壹拾元整
100壹佰元整
1005壹仟零伍元整
10500壹萬零伍佰元整
120000.5壹拾貳萬元伍角整
1000000壹佰萬元整
100000001壹億零壹元整
1.05壹元零伍分
1680.32壹仟陸佰捌拾元參角貳分
  • 「壹拾」不省略為「拾」(12 → 壹拾貳):金額大寫的目的是防塗改,與口語「十二」不同
  • 有角無分寫「元X角整」,有分無角寫「元零X分」,兩者都有寫「元X角X分」
  • 整數最多 16 位(9999 兆餘),再往上輸入框會顯示「超出支援範圍」錯誤並設 aria-invalid;設定 max 時超過上限同樣提示,但不阻止輸入,讓使用者自己修
  • 輸入框接受全形數字與全形句點(中文輸入法下常誤打),會自動轉為半形;千分位逗號在貼上時會被清掉,顯示時再補回
  • 插入千分位逗號後游標維持在原本的數字位置,不會跳到行尾

可及性

  • 實際輸入為單一原生 inputinputMode="decimal"),行動裝置會叫出數字鍵盤;aria-describedby 同時指向大寫鏡射列與提示訊息
  • 大寫鏡射列是 aria-live="polite" 區域,逐字動畫一律 aria-hidden,螢幕閱讀器只會朗讀完整字串(如「新臺幣壹萬貳仟元整」)
  • 超出範圍或超過 max 時設定 aria-invalid,錯誤訊息置於 role="status" 區域
  • 複製鈕為 type="button",帶 aria-label(複製成功後改為「已複製大寫金額」),支援鍵盤操作與 focus-visible 外框
  • 使用者系統開啟「減少動態效果」時,大寫改為直接替換文字,不做逐字淡入/滑動;複製圖示切換與訊息切換也不做動畫

本頁目錄