注 :本次仅修改pallas
项目
修改分支
test_v_0_1_8_n27396
,共1个文件
1、修改文件src/pages/PersonInfo/comps/NumberItem.tsx
import React, { useState, useRef, useEffect, useImperativeHandle } from 'react';
import { FormItem } from 'components';
import {
getFormatNo,
getRawNo,
getDesensitizationNo,
isMobile,
strWithoutSpace,
platForm,
} from 'utils/SystemUtils';
import './NumberItem.scss';
import { INPUTTYPE, IDTYPE, TOASTTEXT } from '../Const';
import Clear from '../../../images/clear.png';
import OpenEye from '../../../images/open-eye.png';
import CloseEye from '../../../images/close-eye.png';
import { formatMaxIDLen, isInvalidId } from '../DataCenter';
import { setCaretPosition, getCaretPosition } from 'utils/CaretService';
export const ID_NUMBER_RE = /^[\dxX]*$/;
type ITextType = 'desensitization' | 'format' | 'normal';
type IImgType = 'clear' | 'open-eye' | 'close-eye' | null;
interface INumberItem {
title?: string;
placeholder?: string;
type?: any;
onlyNumber?: boolean;
onChange?: (e, t) => void;
onFocus?: () => void;
onBlur?: () => void;
defaultIdType?: string;
inputId?: string;
}
const NumberItem = React.forwardRef(
(
{
title,
placeholder,
type,
onChange,
onFocus,
onBlur,
onlyNumber,
defaultIdType,
inputId,
}: INumberItem,
ref,
) => {
const isPhoneNo = type == INPUTTYPE.PHONE;
const [imgType, setImgType] = useState(null as IImgType);
const [idType, setIdType] = useState(defaultIdType);
const [rawValue, setRawValue] = useState(''); // 保存原始数据
const [inputValue, setInputValue] = useState('' as any); // 保存经过处理后展示给用户的数据
const [disabled, setDisabled] = useState(false);
const [errorTip, setErrorTip] = useState('');
const shouldShowErrorTip = useRef(false);
const desensitizationRef = useRef(false);
const inputRef = useRef(undefined);
const isID = () => {
return idType == IDTYPE.ID || type == INPUTTYPE.ID;
};
const getImgSrc = () => {
return imgType == 'clear' ? Clear : imgType == 'open-eye' ? OpenEye : CloseEye;
};
const updateCaret = (val) => {
let lastPos = getCaretPosition(inputRef.current);
if ((isID() || isPhoneNo) && lastPos !== val.length) {
let pos = lastPos;
if (inputValue.length < val.length) {
// 增加
if (isID() && (lastPos == 7 || lastPos == 6 + 8 + 2)) {
pos = lastPos + 1;
}
if (isPhoneNo && (lastPos == 4 || lastPos == 3 + 4 + 2)) {
pos = lastPos + 1;
}
} else if (inputValue.length > val.length) {
// 删除
if (isID() && (lastPos == 6 + 1 || lastPos == 6 + 8 + 2)) {
pos = lastPos - 1;
}
if (isPhoneNo && (lastPos == 3 + 1 || lastPos == 3 + 4 + 2)) {
pos = lastPos - 1;
}
}
setCaretPosition(inputRef.current, pos);
}
};
const formatInputValue = (e) => {
if (isID()) return getFormatNo(e, 'ID');
if (isPhoneNo) return getFormatNo(e, 'Phone');
return e || '';
};
const desensitizationNo = (e) => {
return getDesensitizationNo(e, isPhoneNo ? 'Phone' : isID() ? 'ID' : 'Default');
};
const doShowErrorTip = () => {
if (isPhoneNo) {
setErrorTip(rawValue?.length && !isMobile(rawValue) ? '手机号码格式不正确' : '');
} else if (isInvalidId(idType, rawValue)) {
setErrorTip(!rawValue ? '证件号不能为空' : '证件号码格式不正确');
} else {
setErrorTip('');
}
};
const blur = () => {
inputRef.current?.blur();
};
const doOnFocus = () => {
onFocus && onFocus();
setImgType('clear');
};
const doOnBlur = () => {
// 解决部分低版本iOS手机事件未随视图收回的问题
setTimeout(() => {
window.scrollTo(0, 0);
}, 100);
if (imgType === 'clear') {
setTimeout(() => {
setImgType(desensitizationRef.current ? 'open-eye' : null);
}, 100);
}
doShowErrorTip();
onBlur && onBlur();
};
const doOnChange = () => {
onChange && onChange(rawValue, isID());
if (isID() && !desensitizationRef.current) {
setInputValue(formatInputValue(rawValue) || '');
}
};
const refreshType = (e) => {
setIdType(e);
const isIdType = e == IDTYPE.ID;
if (!isIdType) {
setErrorTip('');
setInputValue(rawValue?.substring(0, formatMaxIDLen(e)) || '');
}
};
const shouldShowError = () => {
if ((isID() && rawValue?.length == 18) || (isPhoneNo && rawValue?.length == 11)) {
shouldShowErrorTip.current = true;
}
if (shouldShowErrorTip.current) {
doShowErrorTip();
}
};
const refreshErrorTip = (e) => {
if (
isID() &&
!rawValue &&
(e == TOASTTEXT.ERROR_ID || e === TOASTTEXT.ERROR_CUSTODIAN_ID)
) {
setErrorTip('证件号不能为空');
} else {
setErrorTip(e);
}
};
useImperativeHandle(ref, () => ({
blur,
refreshType,
refreshErrorTip,
refreshText: (e, { d = false, t = 'format' as ITextType, idType = undefined } = {}) => {
desensitizationRef.current = t === 'desensitization';
let val =
t === 'format'
? formatInputValue(e)
: desensitizationRef.current
? desensitizationNo(e)
: e;
setInputValue(val || '');
setRawValue(e);
setDisabled(d);
setIdType(idType);
if (desensitizationRef.current) {
setImgType('close-eye');
}
},
}));
useEffect(() => {
shouldShowError();
doOnChange();
if (errorTip === '证件号不能为空' && rawValue) {
setErrorTip('');
}
}, [rawValue]);
useEffect(() => {
doShowErrorTip();
doOnChange();
}, [idType]);
useEffect(() => {
if (inputValue && !desensitizationRef.current) {
setImgType('clear');
}
}, [inputValue]);
const Input = (
<div
className="number-cls"
onTouchStart={(e) => {
e.stopPropagation();
}}
>
{disabled || imgType == 'close-eye' ? (
<div className="input disable">{inputValue}</div>
) : (
<input
placeholder={placeholder}
className="input"
id={inputId}
value={inputValue}
ref={inputRef}
type={isPhoneNo ? 'tel' : 'text'}
maxLength={formatMaxIDLen(idType, true)}
onFocus={doOnFocus}
onBlur={doOnBlur}
onTouchStart={(e) => {
const curNode = e.target as HTMLInputElement;
const activeNode = document.activeElement as HTMLInputElement;
if (platForm.iOS) {
if (
activeNode &&
activeNode.nodeName.toLowerCase() === 'input' &&
curNode.placeholder !== activeNode.placeholder
) {
(document.activeElement as HTMLInputElement).blur();
e.preventDefault();
}
}
}}
onChange={(e) => {
e.persist();
let val = e.target.value;
const isNumber = /^\d*$/.test(strWithoutSpace(val));
if (onlyNumber && !isNumber) {
// 手机号类型输入校验
return;
}
if (isID() && !ID_NUMBER_RE.test(val.replace(/\s/g, ''))) {
// 身份证类型输入校验
return;
}
setRawValue(
getRawNo(val, isID() ? 'ID' : isPhoneNo ? 'Phone' : 'default'),
);
setInputValue(formatInputValue(val));
updateCaret(formatInputValue(val));
}}
/>
)}
{imgType && inputValue && (
<>
<img src={getImgSrc()} className="clear-img" />
<div
className="img-com"
onTouchStart={(e) => {
if (imgType == 'clear') {
setInputValue('');
setRawValue('');
setErrorTip('');
setTimeout(() => {
setImgType(null);
}, 100);
} else if (imgType == 'open-eye') {
setImgType('close-eye');
setInputValue(desensitizationNo(rawValue));
} else if (imgType == 'close-eye') {
setImgType('open-eye');
setInputValue(formatInputValue(rawValue));
}
}}
/>
</>
)}
</div>
);
// 证件号码、手机号、监护人身份证号
return (
<FormItem title={title} alignItems="flex-start" errorTip={errorTip}>
{Input}
</FormItem>
);
},
);
export default NumberItem;