import React, { useState, useMemo } from 'react'; import './BankCardInput.css'; function detectType(v) { if (/^4/.test(v)) return 'Visa'; if (/^5[1-5]/.test(v)) return 'MasterCard'; if (/^62/.test(v)) return '银联'; if (/^3[47]/.test(v)) return 'AmEx'; if (/^35/.test(v)) return 'JCB'; return ''; } function luhn(v) { let sum = 0, alt = false; for (let i = v.length - 1; i >= 0; i--) { let n = parseInt(v[i], 10); if (alt) { n *= 2; if (n > 9) n -= 9; } sum += n; alt = !alt; } return sum % 10 === 0; } export default function BankCardInput({ modelValue = '', placeholder = '请输入银行卡号', onChange }) { const [digits, setDigits] = useState(modelValue.replace(/\D/g, '')); const [focused, setFocused] = useState(false); const display = digits.replace(/(.{4})/g, '$1 ').trim(); const cardType = detectType(digits); const valid = digits.length >= 13 && luhn(digits); const invalid = digits.length >= 13 && !luhn(digits); const tipClass = valid ? 'valid' : invalid ? 'invalid' : ''; const tipText = !digits ? '支持 Visa / MasterCard / 银联等' : valid ? '卡号校验通过' : invalid ? '卡号未通过 Luhn 校验' : '继续输入卡号…'; const onInput = (e) => { const v = e.target.value.replace(/\D/g, '').slice(0, 19); e.target.value = v.replace(/(.{4})/g, '$1 ').trim(); setDigits(v); if (onChange) onChange(v); }; return (
setFocused(true)} onBlur={() => setFocused(false)} /> {cardType || '未知'}
{tipText}
); }