import React, {useState, useRef, useEffect} from 'react'; import classname from 'classnames' import {message} from 'antd' import {createNode, checkSymbol, checkKeycode} from './createNode' import RuleInfo from './RuleInfo'; import style from './index.less' const attrList = [ 'properties_realtime', // 实时属性 'properties_analysis', // 计量属性 'event', // 事件 'attr', ] const EditNode = (props) => { const {onEdit, expression, attrInfo, symbolInfo, oStyle, clearSymbol, clearAttr, isEdit, addDevice, deleteDevice } = props; const inputParent = useRef() const [extra, setExtra] = useState({}) const [focusIndex, setFocusIndex] = useState() /* 自动获取节点 */ const autoFocus = (keyIndex, direction) => { // console.log('next focus') const inputDom = inputParent?.current?.querySelectorAll('input'); if (!inputDom) return; const target = direction ? keyIndex + 1 : keyIndex - 1; if (target > inputDom.length) return; if(inputDom[target]) inputDom[target].focus() } /* 添加Node */ const addNode = (keyIndex, type = 'number', value) => { // console.log('addNode') let nodeConfig = {type} if (type === 'symbol') {nodeConfig.operator = value} if (type === 'number') {nodeConfig.value = value} if (attrList.includes(type)){ nodeConfig = {...nodeConfig, ...value} } const newNode = createNode(nodeConfig) const newFuncNode = [...expression] newFuncNode.splice(keyIndex, 0, newNode); onEdit(newFuncNode) } /* 键盘输入事件 */ const inputChange = (event, keyIndex) => { const valueCode = event.target.value.charCodeAt(0); if (valueCode >= 255) return false; }; /* 失去焦点事件 */ const finishAdd = (keyIndex) => { // console.log('onBLUR', keyIndex) setExtra({}) if (extra.value) { const asyncStep = async () => { await addNode(keyIndex, 'number', extra.value) await autoFocus(keyIndex, true) } asyncStep().then() } } /* 监听回车删除事件 */ const keydownAction = (event, keyIndex) => { const keyCode = window.event ? event.keyCode : event.which || null // console.log(keyCode, 'keyCode') // console.log(event.shiftKey, String.fromCharCode(keyCode)) if (String.fromCharCode(keyCode) === 'å'){ message.error('请切换英文输入法') return; } const extraValue = extra?.value || ''; /* 删除事件 */ if (keyCode === 8) { /* 如果有输入内容则删除 */ if (extra?.keyIndex === keyIndex && extra.value) { const newExtra = {...extra} const extraValue = newExtra.value newExtra.value = extraValue.substring(0, extraValue.length -1) setExtra(newExtra) }else { /* 删除前一节点 */ if (keyIndex === 0) return; const newFuncNode = [...expression]; // console.log(newFuncNode[keyIndex -1]) const deleteNode = newFuncNode[keyIndex -1]; if (attrList.includes(deleteNode.type)){ // console.log('delete attr') deleteDevice && deleteDevice(deleteNode.deviceId) } newFuncNode.splice(keyIndex - 1, 1); onEdit(newFuncNode) autoFocus(keyIndex, false) } } /* 回车事件 */ if (keyCode === 13) { const asyncStep = async () => { await finishAdd(keyIndex); await autoFocus(keyIndex, true) } asyncStep().then() } /* 前进事件 */ if (keyCode === 39 && !extra.value && !event.keyCode) { // console.log('---->') const inputDom = inputParent.current.querySelectorAll('input'); const target = keyIndex + 1; if (target > inputDom.length) return; if(inputDom[target]) inputDom[target].focus() } /* 后退事件 */ if (keyCode === 37 && !extra.value && !event.keyCode) { // console.log('<----') const inputDom = inputParent.current.querySelectorAll('input'); const target = keyIndex - 1; if (target < 0) return; if(inputDom[target]) inputDom[target].focus() } /* 数字 */ if ((keyCode >= 48 && event.keyCode <= 57 || keyCode === 190) && !event.shiftKey){ const keyNum = String.fromCharCode(keyCode); const newExtra = { keyIndex, value: extraValue + (keyNum === '¾' ? '.' : keyNum) } setExtra(newExtra); } /* 符号 */ const hasShift = event.shiftKey; const testSymbol = checkKeycode(hasShift, keyCode) if (testSymbol.isSymbol){ const { symbolValue } = testSymbol setExtra({}) if (extraValue.trim() !== '') { const newFuncNode = [...expression] const addNumAndSym = () => { const targetNumber = { type: 'number', value: extraValue } const numberNode = createNode(targetNumber) newFuncNode.splice(keyIndex, 0, numberNode); const targetSymbol = { type: 'symbol', operator: symbolValue } const symbolNode = createNode(targetSymbol) newFuncNode.splice(keyIndex + 1, 0, symbolNode); onEdit(newFuncNode) } const asyncStep = async () => { // await finishAdd(keyIndex) await addNumAndSym(); await autoFocus(keyIndex + 1, true) } asyncStep().then() }else { const asyncStep = async () => { await addNode(keyIndex, 'symbol', symbolValue); await autoFocus(keyIndex, true) } asyncStep().then() } } } /* input onFocus 事件 */ const inputFocus = (event, keyIndex) => { setFocusIndex(keyIndex) if (keyIndex < 0) return; const inputDom =inputParent.current.querySelectorAll('input'); inputDom[keyIndex].focus() } const defaultFocus = () => { const inputDom =inputParent.current.querySelectorAll('input'); if (inputDom.length > 0) inputDom[inputDom.length - 1].focus() } useEffect(() => { if (isEdit && symbolInfo && focusIndex !== undefined && focusIndex !== null) { const asyncStep = async () => { await addNode(focusIndex === 0 ? 0 : focusIndex, 'symbol', symbolInfo); if (clearSymbol) await clearSymbol(); await autoFocus(focusIndex, true) } asyncStep().then() } else { clearSymbol() } }, [symbolInfo]) useEffect(() => { if (isEdit && attrInfo && focusIndex !== undefined && focusIndex !== null) { if(addDevice) addDevice(attrInfo) const asyncStep = async () => { await addNode(focusIndex === 0 ? 0 :focusIndex, attrInfo.type, attrInfo); await clearAttr(); await autoFocus(focusIndex, true) } asyncStep().then() } else { clearAttr() } }, [attrInfo]) return ( <div ref={inputParent} onClick={defaultFocus} className={classname(style.edit_area)} style={oStyle} > {extra?.keyIndex === 0 && extra?.value && ( <div style={{marginLeft: 13,marginRight: '-5px'}}>{extra?.value}</div> )} <input value="" onClick={event => event.stopPropagation()} onFocus={event => inputFocus(event, 0)} onBlur={() => finishAdd(0)} onKeyDown={event => keydownAction(event, 0)} onChange={(event) => inputChange(event, 0)} className={classname(style.hide_input, style.inner_input)} /> {expression?.length > 0 && expression.map((item, index) => ( <div key={index} className={style.pos_aline_no_wrap} onClick={event => event.stopPropagation()}> <RuleInfo parentRef={inputParent} {...item} targetKey={index + 1} /> {extra?.keyIndex - 1 === index && extra?.value && ( <div className="pos_center" style={{marginLeft: 13,marginRight: '-5px'}} >{extra?.value}</div> )} <input value="" onFocus={event => inputFocus(event, index + 1)} onBlur={() => finishAdd(index + 1)} onKeyDown={event => keydownAction(event, index + 1)} onChange={(event) => inputChange(event, index + 1)} className={classname(style.hide_input, style.inner_input)} /> </div> ))} </div> ); }; export default EditNode;