/* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/ban-ts-comment */ import React, { KeyboardEvent } from 'react'; import { useControllableValue } from 'ahooks'; import classnames from 'classnames'; import './index.scss'; const numReg = /^\d\d*.?\d*\d$|\d/; interface NumberPropsI { value?: string; onChange: (val: string) => string; className?: string; style?: object; width: number; align: 'left' | 'right'; placeholder: string; onFocus: () => void; onBlur: () => void; onEnter: (value: any, e: KeyboardEvent) => void; min: number; max: number; format: (value: any) => any; // 当数据经过修正后的回调 onCorrect?: (currentValue: string, oldValue: string) => void; } const numberFormat = (val: string): string => { let ret = val.replace(/[^0-9.]/g, ''); if (ret.indexOf('.') !== ret.lastIndexOf('.')) { // 存在多个小数点 const splitArr = ret.split('.'); ret = splitArr.reduce( (resStr, nextStr, index) => `${resStr}${index === 1 ? '.' : ''}${nextStr}`, '', ); } return ret.replace(/^00+\./, '0.').replace(/^00+/, '0'); // 多个0合并成一个 }; /** * * @param props * @returns * 格式化顺序和优先级 * 1、通用格式化 --- 会先做简单的格式处理,过滤一些非数字信息或者写法不正确的情况 * 2、自定义格式化 --- 优先级是 format 》 min|max */ export default function Number(props: NumberPropsI) { const { className, style, width = '100%', align = 'left', placeholder = '请输入', onFocus, onBlur, onEnter, min, max, format, onCorrect, ...rest } = props; const [value, onChange] = useControllableValue(props); const customFormat = (value: string): string => { if (numReg.test(value)) { // 符合数字校验,则做自定义格式 let numValue = parseFloat(value); if (min) { numValue = Math.max(min, numValue); } if (max) { numValue = Math.min(max, numValue); } return String(numValue); } return value; }; const onMidChange = (event: object) => { // @ts-ignore const target = event.target as HTMLInputElement; const val = target.value; // 修复非数字字符串 const numberValue = numberFormat(val); // 修复最大最小值 const customerValue = customFormat(numberValue); // 格式化数字 let formattedValue = customerValue; if (format instanceof Function) { const formatValue = format(formattedValue); if (numReg.test(formatValue as string)) { formattedValue = formatValue; } } onChange(formattedValue); if (`${val}` !== customerValue) { onCorrect instanceof Function && onCorrect(customerValue, val); } }; const onKeyDown = (event: KeyboardEvent) => { if (event.keyCode === 13) { // enter 事件 onEnter instanceof Function && onEnter(value, event); } }; const finalClassName = classnames('op-number', className); const finalStyle = { ...(style || {}), width, textAlign: align, }; return ( { e.stopPropagation(); // 阻止冒泡 }} /> ); }