123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- import React,{Component} from 'react';
- import className from 'classnames';
- import {NumberPan,Notify} from '@commonComp';
- import style from './index.less';
- import {setFontColorSize,handleMouseUp} from '@utils/tools'
- /***
- * author:zn@2018-11-19
- * 接收参数:
- * value: 默认选中的值
- * placeholder:灰显文字
- * handleSelect: 选中事件
- * show: 是否显示下拉
- * allClick:是否前后缀也可唤出数字键盘
- *
- * ***/
- class NumberDrop extends Component{
- constructor(props){
- super(props);
- this.state={
- /*editable:false, //标签是否可输入*/
- value:props.value||'',
- timer:null,
- sltTimer:null,
- blurTimer:null,
- hasSelect:false, //是否点过下拉键盘
- placeholder:props.placeholder
- };
- this.$span = React.createRef();
- this.numInpBlur = this.numInpBlur.bind(this);
- this.handleSpanInp = this.handleSpanInp.bind(this);
- this.handleNumClick = this.handleNumClick.bind(this);
- this.handleNumFocus = this.handleNumFocus.bind(this);
- this.handleKeyDowm = this.handleKeyDowm.bind(this);
- this.beyondArea = this.beyondArea.bind(this);
- this.emitBMIData = this.emitBMIData.bind(this);
- }
- select(text){ //选中键盘上数字事件
- //placeholder修改后,第一次点击键盘触发blur后onClick不触发,原因未知,改为onMouseup可触发
- let timer = null;
- clearTimeout(this.state.sltTimer);
- clearTimeout(this.state.blurTimer);
- const {handleSelect,ikey,suffix,prefix,mainSaveText,min,max,formulaCode} = 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)&&parseFloat(min)<=parseFloat(text)&&parseFloat(text)<=parseFloat(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,formulaCode});
- //BMI相关数据上传
- this.emitBMIData(text);
- }
- emitBMIData(text){
- //手动修改BMI相关值时数据上传
- const {setBMIParam,formulaCode,setBMI} = this.props;
- if(formulaCode==="BMI_RES"){
- setBMI&&setBMI(text);
- }
- if(text!==0&&(formulaCode==="BMI_SG"||formulaCode==="BMI_TZ")){
- const map={
- BMI_SG:'tall',
- BMI_TZ:'weight'
- };
- setTimeout(function(){
- setBMIParam&&setBMIParam(map[formulaCode],text);
- });
- }
- }
- beyondArea(){
- const {handleSelect,ikey,suffix,prefix,mainSaveText,formulaCode} = this.props;
- Notify.info("输入数值不符合规范,请重新输入!");
- handleSelect&&handleSelect({ikey,text:'',suffix,prefix,mainSaveText,formulaCode});
- this.emitBMIData('');
- this.setState({
- placeholder:this.props.placeholder,
- hasSelect:false
- });
- }
- 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();
- }
- handleKeyDowm(e){
- if(e.keyCode==13){
- const {reFocus,num,handleHide} = this.props;
- reFocus&&reFocus(num);
- handleHide && handleHide();
- }
- }
- handleNumClick(e){ //数字框不可编辑的状态时点击事件,点击将数字框变为可输入且下拉不再显示直到失焦后再次聚集
- e.stopPropagation();
- const {show,handleShow,ikey,id,patId,handleHide} = this.props;
- if(show) {
- handleHide && handleHide();
- return;
- }else{
- this.$span.current.focus();
- this.setState({
- hasSelect:false,
- placeholder:'' //火狐26placeholder点击不隐藏bug修改
- });
- handleShow&&handleShow({ikey,id:patId||id});
- }
- }
- 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&&parseFloat(min)<=parseFloat(arr1[0])&&parseFloat(arr1[0])<=parseFloat(max)&&parseFloat(min)<=parseFloat(arr1[1])&&parseFloat(arr1[1])<=parseFloat(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&&parseFloat(min)<=parseFloat(arr2[0])&&parseFloat(arr2[0])<=parseFloat(max)&&parseFloat(min)<=parseFloat(arr2[1])&&parseFloat(arr2[1])<=parseFloat(max)))){
- return true
- }
- return false;
- }
- return false;
- }
- numInpBlur(e){ //数字框失焦,保存值到store中
- e.stopPropagation();
- const {handleSelect,ikey,suffix,prefix,mainSaveText,min,max,show,formulaCode} = this.props;
- /*if(show){ //修改清空后第一次点击键盘不触发click事件bug--失焦placehoder消失,弃用
- return;
- }*/
- //输入超出合理范围或输入不是数字提示且清空
- const needCompare=min!=undefined&&max!=undefined;
- const txt = e.target.innerHTML.replace(/ $|^ /,'');//e.target.innerText.trim();
- const isFine = this.validSymbols(txt,min,max); //有~或/时是否合理
- const hasSymbol = /[\/|\~]/g.test(txt); //是否有~或/
- const singleFine = (!isNaN(+txt)&&!needCompare)||(!isNaN(+txt)&&needCompare&&parseFloat(min)<=parseFloat(txt)&&parseFloat(txt)<=parseFloat(max)); //无~或/时是否合理
- if(txt!=''&&(!hasSymbol&&!singleFine)||(hasSymbol&&!isFine)){
- this.beyondArea();
- return;
- }
- //输入为空时显示placeholder
- const timer = setTimeout(()=>{
- if(!e.target.innerHTML.replace(/ $|^ /,'')){
- this.setState({
- placeholder:this.props.placeholder
- });
- }
- },200);
- this.setState({
- blurTimer:timer
- });
- const val = e.target.innerHTML.replace(/ $|^ /,'');//e.target.innerText.trim();
- const {placeholder} = this.state;
- let text = val===placeholder?'':val;
- //e.target.innerText = ''; //避免出现重复输入值
- handleSelect&&handleSelect({ikey,text,suffix,prefix,mainSaveText,formulaCode});
- this.emitBMIData(text);
- }
- handleSpanInp(e){ //数字框输入事件
- e.stopPropagation();
- const txt = e.target.innerHTML.replace(/ $|^ /,'');
- this.setState({
- value:txt
- });
- const {handleHide} = this.props;
- handleHide&&handleHide();
- }
- getClasses(nospecial){ //整个标签是否有值的状态
- const {hideTag,placeholder,isImports,isExtBlue,isSelectAll,mouseSelect} = this.props;
- const val = this.state.value;
- const isSelected = val&&val!=placeholder?style['selected']:style['container'];
- const orgBorder = isImports&&!(val&&val!=placeholder)?style['orange-border']:'';
- const ext = isExtBlue?style['ext']:'';
- const noTag = hideTag?style['no-tag']:'';
- const selectedArea = mouseSelect?style['selected-area']:'';
- return className(isSelected,noTag,orgBorder,ext,setFontColorSize(val||isSelectAll?'2,6':isExtBlue?2:1),selectedArea);
- }
- getSpanClass(nospecial){ //将被替换的文字选中状态显示
- const {isSelectAll,isExtBlue,show,mouseSelect} = this.props;
- const val = this.state.value;
- const selectedArea = mouseSelect?style['selected-area']:'';
- const cls = this.props.show?style['blued']:style['nol'];
- // return cls+' '+setFontColorSize(nospecial?'':2);
- return className(show?style['blued']:(style['nol'],setFontColorSize(val?'2,6':isSelectAll?'2,6':isExtBlue?2:1)),selectedArea)
- }
- stopBubble(e){
- e.stopPropagation();
- }
- handleMouseDown(){
- const {i,setSelectArea,boxMark}= this.props;
- setSelectArea({i,boxMark,dir:'start'});
- }
- componentDidMount(){
- //设置最小宽度避免输入后宽度跳动
- const spanWidth = window.getComputedStyle(this.$span.current).width;
- this.$span.current.style.minWidth=spanWidth;
- //保存输入框dom以便聚焦
- const that = this;
- setTimeout(function(){ //多个其他史/现病史bug修改
- const {saveDoms} = that.props;
- saveDoms&&saveDoms(that.$span);
- })
- }
- componentWillReceiveProps(nextProps){
- //BMI存值
- const {formulaCode,bmi,suffix,prefix,ikey,handleSelect,mainSaveText,wrBmi} = this.props;
- if(formulaCode==="BMI_RES"&&nextProps.bmi!==bmi){
- handleSelect&&handleSelect({ikey,text:nextProps.bmi,suffix,prefix,mainSaveText,formulaCode});
- }
- //手动修改BMI时身高体重清空
- if(wrBmi!==nextProps.wrBmi&&(formulaCode==="BMI_SG"||formulaCode==="BMI_TZ")){
- handleSelect&&handleSelect({ikey,text:'',suffix,prefix,mainSaveText,formulaCode});
- }
- if((nextProps.placeholder == this.props.placeholder)&&(nextProps.value == this.props.value)){
- return
- }
- this.setState({
- placeholder:nextProps.placeholder,
- value:nextProps.value
- });
- }
- render(){
- const {prefix,suffix,show,value,handleHide,allClick,bmi,formulaCode,nospecial,isSelectAll,isExtBlue,select_start,i,boxMark} = this.props;
- const val = formulaCode==="BMI_RES"?(+bmi===Infinity||isNaN(bmi)?'':bmi):value;
- const {placeholder,hasSelect} = this.state;
- return <div className={this.getClasses(nospecial)}
- style={{position:'relative'}}
- onClick={allClick?this.handleNumClick:null}
- onMouseUp={()=>handleMouseUp({select_start,i,boxMark})}
- onMouseDown={this.handleMouseDown.bind(this)}>
- <span className={`${setFontColorSize(val?'':isSelectAll?2:isExtBlue?2:1)} prefixUnset`}>{prefix}</span>
- <span onFocus={this.handleNumFocus}
- onClick={allClick?null:this.handleNumClick}
- contentEditable={true}
- style={{minWidth:'10px',display:'inline-block',textAlign:'center'}}
- ref = {this.$span}
- onkeyup={this.handleKeyDowm}
- onBlur={this.numInpBlur}
- onInput={this.handleSpanInp}
- className={`${this.getSpanClass(nospecial)}`}
- > {val||placeholder}</span>
- <span className={`${setFontColorSize(val?'':isSelectAll?2:isExtBlue?2:1)} prefixUnset`}>{suffix}</span>
- <NumberPan handleSelect={this.select.bind(this)}
- noString={formulaCode?true:false}
- onClose={handleHide}
- value={this.state.value}
- show={show}
- toClear={!hasSelect}/>
- </div>
- }
- }
- export default NumberDrop;
|