本文基于上一篇文章进行优化,不需要关注业务input怎么封装,不涉及业务改动。通用自定义数组键盘输入功能如下:直接贴代码
javascript
import type { FC } from 'react';
import React, { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
import { EPanelKeyModeType, EPanelNumCommand } from '@/pages/editor1/common/enum';
import ConfigManage from '@/pages/global/ConfigManage';
import { panelCommandStore } from '@/stores';
import { updateKeyMode } from '@/utils/panel';
export type AnyObjectImple = Record<string, string | number>;
const INPUTTAGNAME = 'INPUT';
const INPUTTEXT = 'text';
const INPUTTEL = 'tel';
/**
* 通用业务数字键盘计算
* @type cueMode: 文本模式, cueMode: 数字模式两种
* @waring 计算文本之前需要将文本现有数据 set 到panelNumberStore的originalVal上
* @desc 考虑到这里业务的逻辑较复杂,将业务提取为公用业务组件
* @desc 任何地方都可以使用该组件进行数字键盘的计算、文本的计算
* @desc 追加文本框光标位置的计算
* @returns
*/
const NumberKeyboard: FC = () => {
// 指令
const panelCommand = useRecoilValue(panelCommandStore);
const IsNormalScreen = ConfigManage.getExpandCfg().IsNormalScreen;
useEffect(() => {
// 文字输入框添加onfocus, onblur监听,调起小控台数字按键
if (IsNormalScreen) return;
const isNeedBlur = (relateDM) => {
if (relateDM?.tagName !== INPUTTAGNAME) {
return true;
} else {
return relateDM?.type !== INPUTTEXT && relateDM?.type !== INPUTTEL;
}
};
const isTargetInput = (targetDMParam: HTMLInputElement) => {
return (
targetDMParam?.tagName === INPUTTAGNAME &&
(targetDMParam?.type === INPUTTEXT || targetDMParam?.type === INPUTTEL)
);
};
const onFocus = (e: FocusEvent) => {
if (isTargetInput(e.target as HTMLInputElement)) {
updateKeyMode(EPanelKeyModeType.numberKeyMode);
}
};
const onBlur = (e: FocusEvent) => {
const relateDOM = e.relatedTarget as HTMLInputElement;
if (isTargetInput(e.target as HTMLInputElement) && isNeedBlur(relateDOM)) {
updateKeyMode(EPanelKeyModeType.restoreLastMode);
}
};
document.addEventListener('focusin', onFocus);
document.addEventListener('focusout', onBlur);
return () => {
document.removeEventListener('focusin', onFocus);
document.removeEventListener('focusout', onBlur);
};
}, []);
/**
* 数字按键相关指令
* @desc 1. 处理普通输入框
* @desc 2. 处理纯数字按键模式
* @return input 结果
*/
const changeNumberCommand = (commandData) => {
// 指令
const { command } = commandData;
try {
// 获取选定对象
const selection = window.getSelection();
if (selection) {
// 如果是文本节点则先获取光标对象
const range = selection?.getRangeAt(0);
// 获取光标对象的范围界定对象,一般就是textNode对象
const textNode: any = range.startContainer;
// 获取输入框input Dom元素, 使用的是And design Input,textNode是div,div里面且套input等子元素
const inputNode = textNode?.getElementsByTagName('input')[0];
// 光标开始
const selectionStart = inputNode.selectionStart;
// 结束位置
const selectionEnd = inputNode.selectionEnd;
console.info('selectionStart', selectionStart, 'selectionEnd', selectionEnd);
// 处理指令运算: 数字
handleNumberCommand(command, inputNode);
}
} catch (e) {}
};
/**
* 数字指令处理
* @param command
* @param inputNode
*/
const handleNumberCommand = (command, inputNode) => {
// 业务指令转对应文本
let pressFpgaVal: number | string = command - EPanelNumCommand.num0;
if (command === EPanelNumCommand.point) {
pressFpgaVal = '.';
}
/**
* 1. 处理键盘指令,分数字模式和非数字模式,非数字模式直接追加内容,数字模式计算内容
* 2. 判断指令范围
* 3. 判断指令模式,处理对应模式数据
*/
if (command >= EPanelNumCommand.num0 && command <= EPanelNumCommand.enter) {
if (command <= EPanelNumCommand.point) {
// 0-9数字处理指令
doNumberCommand(inputNode, pressFpgaVal);
} else if (command === EPanelNumCommand.point) {
// 小数点操作
// equalTen();
} else if ([EPanelNumCommand.add, EPanelNumCommand.minus].includes(command)) {
// 运算指令暂时不支持
// opertBtn(command);
} else if (command === EPanelNumCommand.back) {
// 控台Back删除处理指令
doBackCommand(inputNode);
} else if (command === EPanelNumCommand.enter) {
// 控台Enter处理指令
doEnterCommand(inputNode);
}
}
};
/**
* 0-9数字处理指令
* @param command
*/
const doNumberCommand = (inputNode, pressFpgaVal) => {
// 转换成字符串
const value = inputNode.value + '';
// 光标开始、结束位置
const selectionStart = inputNode.selectionStart;
const selectionEnd = inputNode.selectionEnd;
// 计算新值
const newValue =
value.substr(0, selectionStart) + pressFpgaVal + value.substring(selectionEnd, value.length);
console.info('value', value, newValue);
// 事件发布到组件中input
const evt = new UIEvent('inputchange', {
bubbles: false,
cancelable: false,
});
const keyName = 'data';
evt[keyName] = {
value: newValue,
selectionStart: selectionStart + pressFpgaVal.toString().length,
selectionEnd: selectionStart + pressFpgaVal.toString().length,
};
// 触发onChange事件
inputNode.dispatchEvent(evt, newValue);
};
/**
* 控台Back删除处理指令
* @param command
*/
const doBackCommand = (inputNode) => {
// 转换成字符串
const value = inputNode.value + '';
// 光标开始、结束位置
const selectionStart = inputNode.selectionStart;
const selectionEnd = inputNode.selectionEnd;
// 计算新值
const newValue =
value.substr(0, selectionStart - 1) + value.substring(selectionEnd, value.length);
console.info('value', value, newValue);
// 事件发布到组件中input
const evt = new UIEvent('inputchange', {
bubbles: false,
cancelable: false,
});
const keyName = 'data';
evt[keyName] = {
value: newValue,
selectionStart: selectionStart - 1,
selectionEnd: selectionStart - 1,
};
// 触发onChange事件
inputNode.dispatchEvent(evt);
};
/**
* 控台Enter处理指令
* 触发失去焦点指令
* @param command
*/
const doEnterCommand = (inputNode) => {
// 失焦事件发布到组件中input
const evt = new UIEvent('enter', {
bubbles: false,
cancelable: false,
});
// 触发onChange事件
inputNode.dispatchEvent(evt);
};
/**
* 初始化订阅数字键盘指令
*/
useEffect(() => {
if (panelCommand) {
changeNumberCommand(panelCommand);
}
}, [panelCommand]);
return <div />;
};
export default NumberKeyboard;