form-rules.js 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. /**
  2. * passport 表单的纯函数式校验规则集合。
  3. *
  4. * 调用方按返回 `{ ok, errorKey, field }` 决定提示与高亮,
  5. * 文案翻译完全交给消费者,校验层不与 UI 框架/国际化耦合。
  6. */
  7. const HANDSET_DIGITS = /^\d{5,15}$/
  8. const SECRET_RANGE = { min: 6, max: 20 }
  9. function fail(errorKey, field) {
  10. return { ok: false, errorKey, field }
  11. }
  12. const OK = Object.freeze({ ok: true })
  13. export function looksLikeHandset(value) {
  14. const cleaned = String(value || '').replace(/\s+/g, '').replace(/^\+/, '')
  15. return HANDSET_DIGITS.test(cleaned)
  16. }
  17. export function trimHandset(value) {
  18. return String(value || '').replace(/\s+/g, '').replace(/^\+/, '')
  19. }
  20. export function secretInRange(value) {
  21. const v = String(value || '')
  22. return v.length >= SECRET_RANGE.min && v.length <= SECRET_RANGE.max
  23. }
  24. export function passcodeShape(value) {
  25. return /^\d{4,6}$/.test(String(value || ''))
  26. }
  27. export function auditSigninForm(form) {
  28. if (!form || typeof form !== 'object') return fail('passport.err-empty')
  29. if (!looksLikeHandset(form.handset)) return fail('passport.err-handset', 'handset')
  30. if (form.mode === 'secret') {
  31. if (!secretInRange(form.secret)) return fail('passport.err-secret', 'secret')
  32. } else {
  33. if (!passcodeShape(form.passcode)) return fail('passport.err-passcode', 'passcode')
  34. }
  35. if (!form.accepted) return fail('passport.err-policy', 'accepted')
  36. return OK
  37. }
  38. export function auditEnrollForm(form) {
  39. if (!form || typeof form !== 'object') return fail('passport.err-empty')
  40. if (!looksLikeHandset(form.handset)) return fail('passport.err-handset', 'handset')
  41. if (!secretInRange(form.secret)) return fail('passport.err-secret', 'secret')
  42. if (!passcodeShape(form.passcode)) return fail('passport.err-passcode', 'passcode')
  43. if (!form.accepted) return fail('passport.err-policy', 'accepted')
  44. return OK
  45. }
  46. export function auditHandset(handset) {
  47. if (!looksLikeHandset(handset)) return fail('passport.err-handset', 'handset')
  48. return OK
  49. }