fix persian number in input

This commit is contained in:
2026-08-14 21:05:11 +03:30
parent 82dc6b82d8
commit 2b27b16296
10 changed files with 160 additions and 123 deletions
+61 -19
View File
@@ -1,22 +1,64 @@
//const e2p = (s: string) => s.replace(/\d/g, (d) => '۰۱۲۳۴۵۶۷۸۹'[+d])
//const p2a = (s : string) => s.replace(/[۰-۹]/g, (d) => '٠١٢٣٤٥٦٧٨٩'['۰۱۲۳۴۵۶۷۸۹'.indexOf(d)])
//const a2p = (s : string) => s.replace(/[٠-٩]/g, (d) => '۰۱۲۳۴۵۶۷۸۹'['٠١٢٣٤٥٦٧٨٩'.indexOf(d)])
//const e2a = (s : string) => s.replace(/\d/g, (d) => '٠١٢٣٤٥٦٧٨٩'[+d])
//_sample
//e2p('asdf1234') // asdf۱۲۳۴
//e2a('asdf1234') // asdf١٢٣٤
//p2e('asdf۱۲۳۴') // asdf1234
//a2e('asdf١٢٣٤') // asdf1234
//p2a('asdf۱۲۳۴') // asdf١٢٣٤
//a2p('asdf١٢٣٤') // asdf۱۲۳۴
//٠٩١٣٥٥١۷٤٢٥
//۰۹۱۳۵۵۱۷۴۲۵
/**
* تبدیل ارقام فارسی/عربی به لاتین (انگلیسی) و پاکسازی ورودی‌های عددی/قیمتی.
*/
const a2e = (s: string) => s.replace(/[٠-٩]/g, (d) => '٠١٢٣٤٥٦٧٨٩'.indexOf(d).toString())
const p2e = (s: string) => s.replace(/[۰-۹]/g, (d) => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d).toString())
const PERSIAN_DIGITS = '۰۱۲۳۴۵۶۷۸۹'
const ARABIC_DIGITS = '٠١٢٣٤٥٦٧٨٩'
function persian2english(s: string) {
const temp = p2e(s)
return a2e(temp)
export function persian2english(s: string): string {
return String(s ?? '')
.replace(/[۰-۹]/g, (d) => String(PERSIAN_DIGITS.indexOf(d)))
.replace(/[٠-٩]/g, (d) => String(ARABIC_DIGITS.indexOf(d)))
}
export type SanitizeNumericOptions = {
/** اجازهٔ نقطه اعشار (پیش‌فرض true) */
allowDecimal?: boolean
}
/**
* ارقام فارسی/عربی → لاتین، حذف جداکننده هزار، یکسان‌سازی ممیز.
* خروجی فقط شامل ارقام لاتین و (اختیاری) یک نقطه است.
*/
export function sanitizeNumericString(
raw: unknown,
options: SanitizeNumericOptions = {},
): string {
const allowDecimal = options.allowDecimal !== false
let s = persian2english(String(raw ?? '').trim())
.replace(/[٬,\s]/g, '')
.replace(/٫/g, '.')
.replace(/\//g, '.')
if (!allowDecimal) {
return s.replace(/[^\d-]/g, '').replace(/(?!^)-/g, '')
}
let out = ''
let hasDot = false
let hasSign = false
for (const ch of s) {
if (ch >= '0' && ch <= '9') {
out += ch
continue
}
if (ch === '.' && !hasDot) {
hasDot = true
out += ch
continue
}
if (ch === '-' && !hasSign && out.length === 0) {
hasSign = true
out += ch
}
}
return out
}
/** پارس امن عدد از رشتهٔ فارسی/لاتین/با کاما */
export function parseNumericValue(raw: unknown): number {
const cleaned = sanitizeNumericString(raw)
if (!cleaned || cleaned === '-' || cleaned === '.') return NaN
const n = Number(cleaned)
return Number.isFinite(n) ? n : NaN
}
export { persian2english }
+11 -6
View File
@@ -1,15 +1,20 @@
export function usePrice(price: number, digit = true, unit = 'ریال') {
let _price = price.toString()
if (digit) {
_price = _price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
import { persian2english, parseNumericValue, sanitizeNumericString } from '@core/utils/convert'
export function usePrice(price: number | string, digit = true, unit = 'ریال') {
const n = typeof price === 'number' ? price : parseNumericValue(price)
let _price = Number.isFinite(n) ? String(n) : persian2english(String(price ?? ''))
if (digit && Number.isFinite(n)) {
_price = _price.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
return `${_price} ${unit}`
}
export function useTowDecimal(num: string | number): string | number {
const temp = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)
const cleaned = sanitizeNumericString(num, { allowDecimal: true })
const temp = cleaned.match(/^-?\d+(?:\.\d{0,2})?/)
if (temp && temp.length > 0) return temp[0]
return Math.round(+num * 100) / 100
const n = parseNumericValue(cleaned)
return Number.isFinite(n) ? Math.round(n * 100) / 100 : 0
}
export function useFormat(num: string | number, unit = '') {