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
@@ -3,6 +3,8 @@
* منبع: ستون amount + JSON فیلد data (بدون ستون DB جدا).
*/
import { parseNumericValue } from '@core/utils/convert'
export type AccountingSyncDocRecord = {
amount?: number | string | null
type?: string | null
@@ -12,8 +14,7 @@ export type AccountingSyncDocRecord = {
function parseNum(value: unknown): number {
if (value == null || value === '') return NaN
const n = Number(String(value).replace(/,/g, '').replace('/', '.'))
return Number.isFinite(n) ? n : NaN
return parseNumericValue(value)
}
export function parseDocPayload(data?: string | null): Record<string, unknown> | null {
@@ -91,7 +91,7 @@
:disabled="disabled"
class="w-full"
:formatter="(v: string) => `${v}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
:parser="(v: string) => v.replace(/,/g, '')"
:parser="(v: string) => sanitizeNumericString(v, { allowDecimal: false })"
@update:value="onPriceChange"
/>
@@ -144,6 +144,7 @@ import {
switchValueFromChecked,
type SettingFieldType
} from './settingTypes'
import { parseNumericValue, sanitizeNumericString } from '@core/utils/convert'
import dayjs, { type Dayjs } from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'
@@ -234,7 +235,7 @@ function onTimeChange(val: Dayjs | string | null | undefined) {
}
const priceValue = computed(() => {
const n = parseFloat(String(props.modelValue || '').replace(/,/g, ''))
const n = parseNumericValue(props.modelValue || '')
return Number.isFinite(n) ? n : undefined
})
@@ -243,25 +244,11 @@ function onPriceChange(val: number | string | null) {
emit('update:value', '')
return
}
emit('update:value', String(val))
}
function normalizePlainNumberInput(value: string): string {
const latin = value.replace(/[۰-۹]/g, (d) => String('۰۱۲۳۴۵۶۷۸۹'.indexOf(d)))
let out = ''
let hasDot = false
for (const ch of latin.replace(/,/g, '')) {
if (ch >= '0' && ch <= '9') out += ch
else if (ch === '.' && !hasDot) {
hasDot = true
out += ch
}
}
return out
emit('update:value', sanitizeNumericString(val, { allowDecimal: false }))
}
function onPlainNumberChange(val: string) {
emit('update:value', normalizePlainNumberInput(val ?? ''))
emit('update:value', sanitizeNumericString(val ?? '', { allowDecimal: true }))
}
</script>
@@ -1,5 +1,6 @@
import type { Const } from '@/model/configuration'
import { conditionalOrderEnabledSetting, isStoreApp, priceChannelAccessSetting, priceProviderSetting, showToUsersChatSetting } from '@/utils/config'
import { sanitizeNumericString } from '@core/utils/convert'
export type SettingFieldType =
| 'text'
@@ -517,10 +518,10 @@ export function formatValueForSave(
)
}
if (type === 'price') {
return value === '' ? '0' : String(value).replace(/,/g, '')
return value === '' ? '0' : sanitizeNumericString(value, { allowDecimal: false })
}
if (type === 'number') {
return String(value ?? '').replace(/,/g, '')
return sanitizeNumericString(value ?? '', { allowDecimal: true })
}
if (type === 'time') {
return normalizeTimeValue(value)
@@ -41,8 +41,8 @@
:place-holder="amountPlaceholder"
@onchange="onAmountChange"
/>
<div v-if="isMoney && Number(normalizedAmount) > 10" class="wallet-charge-form__hint">
معادل {{ usePrice(Number(normalizedAmount) / 10, true, 'تومان') }}
<div v-if="isMoney && normalizedAmount > 10" class="wallet-charge-form__hint">
معادل {{ usePrice(normalizedAmount / 10, true, 'تومان') }}
</div>
</a-form-item>
@@ -58,6 +58,10 @@ import type { FormInstance } from 'ant-design-vue'
import type { Charge } from '@/model/wallet'
import { inputRules } from '@/utils/inputRules'
import { usePrice } from '@core/utils/usePrice'
import {
normalizeAmountRaw,
parseAmount,
} from '@/pages/menuPages/customers/base/utils/walletChargeForm'
const props = withDefaults(
defineProps<{
@@ -124,35 +128,16 @@ const notePlaceholder = computed(() =>
isDischarge.value ? 'دلیل کسر موجودی' : 'دلیل افزایش موجودی',
)
/** ارقام فارسی/عربی → لاتین؛ جداکننده هزار حذف؛ ممیز یکسان */
function normalizeAmountRaw(raw: string | number | undefined | null): string {
return String(raw ?? '')
.trim()
.replace(/[۰-۹]/g, (d) => String('۰۱۲۳۴۵۶۷۸۹'.indexOf(d)))
.replace(/[٠-٩]/g, (d) => String('٠١٢٣٤٥٦٧٨٩'.indexOf(d)))
.replace(/[٬,\s]/g, '')
.replace(/٫/g, '.')
}
function hasDecimalSeparator(raw: string): boolean {
// بعد از حذف جداکننده هزار، نقطه = اعشار
return raw.includes('.')
}
function parseAmount(raw: string | number | undefined | null): number {
const normalized = normalizeAmountRaw(raw)
if (!normalized) return 0
const num = Number(normalized)
return Number.isFinite(num) ? Math.abs(num) : NaN
}
const normalizedAmount = computed(() => parseAmount(props.modelValue.amountAbs))
function onAmountChange(raw: string | number) {
if (!requiresInteger.value) return
const text = normalizeAmountRaw(raw)
if (!hasDecimalSeparator(text)) return
// قطع اعشار — فقط بخش صحیح بماند
const whole = text.split('.')[0] ?? ''
props.modelValue.amountAbs = whole === '' ? undefined : whole
}
@@ -1,4 +1,15 @@
import type { Charge, WalletChargeDirection } from '@/model/wallet'
import { parseNumericValue, sanitizeNumericString } from '@core/utils/convert'
/** ارقام فارسی/عربی → لاتین؛ جداکننده هزار حذف؛ ممیز یکسان */
export function normalizeAmountRaw(raw: string | number | undefined | null): string {
return sanitizeNumericString(raw, { allowDecimal: true })
}
export function parseAmount(raw: string | number | undefined | null): number {
const n = parseNumericValue(raw)
return Number.isFinite(n) ? Math.abs(n) : 0
}
export function createEmptyChargeForm(customerId?: number): Charge {
return {
@@ -13,7 +24,7 @@ export function createEmptyChargeForm(customerId?: number): Charge {
}
export function buildChargePayload(form: Charge, productId?: number | null): Charge {
const amount = Math.abs(Number(form.amountAbs) || 0)
const amount = parseAmount(form.amountAbs)
const signed = form.direction === 'discharge' ? -amount : amount
const payload: Charge = {
value: signed,