|
@@ -1,6 +1,6 @@
|
|
|
import React,{Component} from 'react';
|
|
|
import className from 'classnames';
|
|
|
-import {NumberPan} from '@commonComp';
|
|
|
+import {NumberPan,Notify} from '@commonComp';
|
|
|
import style from './index.less';
|
|
|
import $ from "jquery";
|
|
|
import {handleEnter,getPageCoordinate} from '@utils/tools.js';
|
|
@@ -11,6 +11,7 @@ import {handleEnter,getPageCoordinate} from '@utils/tools.js';
|
|
|
* placeholder:灰显文字
|
|
|
* handleSelect: 选中事件
|
|
|
* show: 是否显示下拉
|
|
|
+ * allClick:是否前后缀也可唤出数字键盘
|
|
|
*
|
|
|
* ***/
|
|
|
class NumberDrop extends Component{
|
|
@@ -19,11 +20,13 @@ class NumberDrop extends Component{
|
|
|
this.state={
|
|
|
editable:false, //标签是否可输入
|
|
|
timer:null,
|
|
|
+ sltTimer:null,
|
|
|
hasSelect:false, //是否点过下拉键盘
|
|
|
boxLeft:0,
|
|
|
boxTop:0,
|
|
|
tmpTop:0,
|
|
|
- tmpScroll:0
|
|
|
+ tmpScroll:0,
|
|
|
+ placeholder:props.placeholder
|
|
|
};
|
|
|
this.$span = React.createRef();
|
|
|
this.$pre = React.createRef();
|
|
@@ -36,18 +39,61 @@ class NumberDrop extends Component{
|
|
|
this.handleNumFocus = this.handleNumFocus.bind(this);
|
|
|
this.handleBlur = this.handleBlur.bind(this);
|
|
|
this.changeToEdit = this.changeToEdit.bind(this);
|
|
|
+ //this.handleKeyDowm = this.handleKeyDowm.bind(this);
|
|
|
+ this.beyondArea = this.beyondArea.bind(this);
|
|
|
}
|
|
|
select(text){ //选中键盘上数字事件
|
|
|
+ let timer = null;
|
|
|
+ clearTimeout(this.state.sltTimer);
|
|
|
+ const {handleSelect,ikey,suffix,prefix,mainSaveText,min,max} = this.props;
|
|
|
+ const needCompare=min!=undefined&&max!=undefined;
|
|
|
+ if(!text){
|
|
|
+ this.setState({
|
|
|
+ placeholder:this.props.placeholder
|
|
|
+ });
|
|
|
+ }else{
|
|
|
+ if(needCompare){
|
|
|
+ const that = this;
|
|
|
+ const isFine = this.validSymbols(text,min,max); //有~或/时是否合理
|
|
|
+ const hasSymbol = /[\/|\~]/g.test(text); //是否有~或/
|
|
|
+ const singleFine = !isNaN(+text)&&min<text&&text<max; //无~或/时是否合理
|
|
|
+ timer = setTimeout(function(){
|
|
|
+ clearTimeout(that.state.sltTimer);
|
|
|
+ if(text!=''&&(!hasSymbol&&!singleFine)||(hasSymbol&&!isFine)){
|
|
|
+ that.beyondArea();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ },1500);
|
|
|
+ }
|
|
|
+ this.setState({
|
|
|
+ hasSelect:true,
|
|
|
+ sltTimer:timer
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ handleSelect&&handleSelect({ikey,text,suffix,prefix,mainSaveText});
|
|
|
+ }
|
|
|
+ beyondArea(){
|
|
|
const {handleSelect,ikey,suffix,prefix,mainSaveText} = this.props;
|
|
|
+ Notify.info("输入数值不符合规范,请重新输入!");
|
|
|
+ handleSelect&&handleSelect({ikey,text:'',suffix,prefix,mainSaveText});
|
|
|
this.setState({
|
|
|
- hasSelect:true
|
|
|
+ placeholder:this.props.placeholder,
|
|
|
+ hasSelect:false
|
|
|
});
|
|
|
- handleSelect&&handleSelect({ikey,text,suffix,prefix,mainSaveText});
|
|
|
}
|
|
|
handleNumFocus(e){ //数字框可编辑状态下聚集事件,处理是否显示下拉等
|
|
|
+ const {placeholder} = this.state;
|
|
|
+ const val = e.target.innerText.trim();
|
|
|
+ //console.log(33,e.target.innerText,placeholder,e.target.innerText.trim() == placeholder)
|
|
|
+ if(val!=''&&val == placeholder){
|
|
|
+ this.setState({
|
|
|
+ placeholder:''
|
|
|
+ });
|
|
|
+ }
|
|
|
e.stopPropagation();
|
|
|
}
|
|
|
- handleNumClick(e){ //数字框不可编辑的状态时点击事件,点击将数字框变为可输入且下拉不再显示直到失焦后再次聚集
|
|
|
+ handleNumClick(e){ //数字框不可编辑的状态时点击事件,点击将数字框变为可输入且下拉不再显示直到失焦后再次聚集
|
|
|
const {show,handleShow,ikey,id,patId,handleHide,value} = this.props;
|
|
|
if(show) {
|
|
|
handleHide && handleHide();
|
|
@@ -61,6 +107,11 @@ class NumberDrop extends Component{
|
|
|
//双击时不显示下拉
|
|
|
clearTimeout(that.state.timer);
|
|
|
const timer = setTimeout(function(){
|
|
|
+ //只有弹窗关闭则点击数字键盘会清空当前数据
|
|
|
+ that.$span.current.focus();
|
|
|
+ that.setState({
|
|
|
+ hasSelect:false
|
|
|
+ });
|
|
|
handleShow&&handleShow({ikey,id:patId||id});
|
|
|
},300);
|
|
|
this.setState({
|
|
@@ -79,18 +130,60 @@ class NumberDrop extends Component{
|
|
|
}
|
|
|
e.stopPropagation();
|
|
|
}
|
|
|
+ validSymbols(txt,min,max){
|
|
|
+ //输入只有一个~或/时判断两边是否为合理数字,有多个为不合理
|
|
|
+ const index1 = txt.indexOf('~');
|
|
|
+ const index2 = txt.indexOf('/');
|
|
|
+ const needCompare = min!=undefined&&max!=undefined;
|
|
|
+ let arr1=[],arr2=[];
|
|
|
+ if(index1!=-1&&index1==txt.lastIndexOf('~')&&index1!=txt.length-1){ //有且只有一个~,且不在最后
|
|
|
+ arr1 = txt.split('~');
|
|
|
+ //~的范围在合理范围内为合理值
|
|
|
+ if(!isNaN(+arr1[0])&&!isNaN(+arr1[1])&&((!needCompare)||(needCompare&&min<arr1[0]&&arr1[0]<max&&min<arr1[1]&&arr1[1]<max))){
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(index2!=-1&&index2==txt.lastIndexOf('/')&&index2!=txt.length-1){ //有且只有一个~,且不在最后
|
|
|
+ arr2 = txt.split('/');
|
|
|
+ // /两边的数字分别在合理范围内为合理值
|
|
|
+ if(!isNaN(+arr2[0])&&!isNaN(+arr2[1])&&((!needCompare)||(needCompare&&min<arr2[0]&&arr2[0]<max&&min<arr2[1]&&arr2[1]<max))){
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
numInpBlur(e){ //数字框失焦,保存值到store中
|
|
|
e.stopPropagation();
|
|
|
- if(this.props.show){ //修改清空后第一次点击键盘不触发click事件bug
|
|
|
+ const {handleSelect,ikey,suffix,prefix,mainSaveText,min,max,show} = this.props;
|
|
|
+ if(show){ //修改清空后第一次点击键盘不触发click事件bug
|
|
|
return;
|
|
|
}
|
|
|
- this.setState({
|
|
|
- hasSelect:false
|
|
|
- });
|
|
|
- const val = e.target.innerText.replace(/^\s*/,'');
|
|
|
- const {handleSelect,ikey,suffix,prefix,mainSaveText,placeholder} = this.props;
|
|
|
- const text = val===placeholder?'':val;
|
|
|
- e.target.innerText = ''; //避免出现重复输入值
|
|
|
+ //输入超出合理范围或输入不是数字提示且清空
|
|
|
+ const needCompare=min!=undefined&&max!=undefined;
|
|
|
+ //if(needCompare){
|
|
|
+ const txt = e.target.innerText.trim();
|
|
|
+ const isFine = this.validSymbols(txt,min,max); //有~或/时是否合理
|
|
|
+ const hasSymbol = /[\/|\~]/g.test(txt); //是否有~或/
|
|
|
+ const singleFine = (!isNaN(+txt)&&!needCompare)||(!isNaN(+txt)&&needCompare&&min<txt&&txt<max); //无~或/时是否合理
|
|
|
+ if(txt!=''&&(!hasSymbol&&!singleFine)||(hasSymbol&&!isFine)){
|
|
|
+ this.beyondArea();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //}
|
|
|
+
|
|
|
+ //输入为空时显示placeholder
|
|
|
+ if(!e.target.innerText.trim()){
|
|
|
+ this.setState({
|
|
|
+ placeholder:this.props.placeholder
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ const val = e.target.innerText.trim();
|
|
|
+ const {placeholder} = this.state;
|
|
|
+ let text = val===placeholder?'':val;
|
|
|
+ //e.target.innerText = ''; //避免出现重复输入值
|
|
|
handleSelect&&handleSelect({ikey,text,suffix,prefix,mainSaveText});
|
|
|
}
|
|
|
handleSpanInp(e){ //数字框输入事件
|
|
@@ -98,10 +191,23 @@ class NumberDrop extends Component{
|
|
|
const {handleHide} = this.props;
|
|
|
handleHide&&handleHide();
|
|
|
}
|
|
|
+ /*handleKeyDowm(e){
|
|
|
+ handleEnter();
|
|
|
+ //只能输入数字
|
|
|
+ const key = e.key;
|
|
|
+ const ctrlOn = e.ctrlKey;
|
|
|
+ const isCopyPaste = ctrlOn&&(key=='v'||key=='c');
|
|
|
+ if((!/[0-9|.|~|\/]/.test(key)&&key.length==1&&!isCopyPaste)){
|
|
|
+ e.preventDefault();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }*/
|
|
|
getClasses(){ //整个标签是否有值的状态
|
|
|
- const {value,hideTag,placeholder} = this.props;
|
|
|
+ const {hideTag,placeholder,value} = this.props;
|
|
|
+ const $span = this.$span.current;
|
|
|
+ const val = value;//$span&&$span.innerText.trim()||value;
|
|
|
const blueBorder = this.state.editable?style['blue-border']:'';
|
|
|
- const isSelected = value&&value!=placeholder?style['selected']:style['container'];
|
|
|
+ const isSelected = val&&val!=placeholder?style['selected']:style['container'];
|
|
|
const noTag = hideTag?style['no-tag']:'';
|
|
|
return className(isSelected,noTag,blueBorder);
|
|
|
}
|
|
@@ -129,10 +235,10 @@ class NumberDrop extends Component{
|
|
|
this.setState({
|
|
|
editable: false
|
|
|
});
|
|
|
- let totalVal = e.target.innerText;
|
|
|
- let changeVal = this.$span.current.innerText.replace(/^\s*/,'');//数字框值-修改后;去掉前空格避免多空格叠加
|
|
|
- let prefix = this.$pre.current.innerText.replace(/^\s*/,''); //前缀值-修改后
|
|
|
- let suffix = this.$suf.current.innerText.replace(/^\s*/,''); //后缀值-修改后
|
|
|
+ let totalVal = e.target.innerText.trim();
|
|
|
+ let changeVal = this.$span.current.innerText.trim();//数字框值-修改后;去掉前空格避免多空格叠加
|
|
|
+ let prefix = this.$pre.current.innerText.trim(); //前缀值-修改后
|
|
|
+ let suffix = this.$suf.current.innerText.trim(); //后缀值-修改后
|
|
|
//console.log('数字框:'+changeVal,";全部:"+totalVal,";前缀:"+prefix+";后缀:"+suffix);
|
|
|
handleLabelChange && handleLabelChange({ikey,changeVal,type:boxMark,totalVal,prefix,suffix});
|
|
|
}
|
|
@@ -141,25 +247,31 @@ class NumberDrop extends Component{
|
|
|
const cls = this.props.show?style['blued']:'';
|
|
|
return cls;
|
|
|
}
|
|
|
+ componentDidMount(){
|
|
|
+ //设置最小宽度避免输入后宽度跳动
|
|
|
+ const spanWidth = window.getComputedStyle(this.$span.current).width;
|
|
|
+ this.$span.current.style.minWidth=spanWidth;
|
|
|
+ }
|
|
|
render(){
|
|
|
- const {placeholder,prefix,suffix,show,value,handleHide} = this.props;
|
|
|
- const {numEditable,editable,hasSelect,boxTop,boxLeft} = this.state;
|
|
|
+ const {prefix,suffix,show,value,handleHide,allClick} = this.props;
|
|
|
+ const {numEditable,placeholder,editable,hasSelect,boxTop,boxLeft} = this.state;
|
|
|
return <div className={this.getClasses()}
|
|
|
ref={this.$cont}
|
|
|
onDoubleClick={this.changeToEdit}
|
|
|
+ onClick={allClick?this.handleNumClick:null}
|
|
|
contentEditable={editable}
|
|
|
onBlur={this.handleBlur}
|
|
|
onkeydown={handleEnter}>
|
|
|
<span ref = {this.$pre}> {prefix}</span>
|
|
|
<span onFocus={this.handleNumFocus}
|
|
|
- onClick={this.handleNumClick}
|
|
|
+ onClick={allClick?null:this.handleNumClick}
|
|
|
contentEditable={true}
|
|
|
- style={{minWidth:'10px',display:'inline-block'}}
|
|
|
+ style={{minWidth:'10px',display:'inline-block',textAlign:'center'}}
|
|
|
ref = {this.$span}
|
|
|
onBlur={this.numInpBlur}
|
|
|
onInput={this.handleSpanInp}
|
|
|
className={this.getSpanClass()}
|
|
|
- onkeydown={handleEnter}> {value||placeholder}</span>
|
|
|
+ > {value||placeholder}</span>
|
|
|
<span ref = {this.$suf}> {suffix}</span>
|
|
|
<NumberPan handleSelect={(text)=>this.select(text)}
|
|
|
onClose={handleHide}
|