荣代码备忘录20220413

注 :本次仅修改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;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值