index.jsx 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import React,{Component} from 'react';
  2. import className from 'classnames';
  3. import {NumberUnitPan} from '@commonComp';
  4. import style from './index.less';
  5. import config from '@config/index.js';
  6. import {filterArr,handleEnter,isIE,getPageCoordinate,filterDataArr} from '@utils/tools.js';
  7. import {Notify} from '@commonComp';
  8. import $ from 'jquery';
  9. /***
  10. * 带单位数字组件
  11. * 接收参数:
  12. * value: 默认选中的值
  13. * placeholder:灰显文字
  14. * handleSelect: 选中事件
  15. * show: 是否显示下拉
  16. *
  17. * ***/
  18. class NumberUnitDrop extends Component{
  19. constructor(props){
  20. super(props);
  21. this.state={
  22. editable:false, //标签是否可输入
  23. numEditable:true, //数字框是否可输入
  24. timer:null,
  25. hasSelect:false, //是否点过下拉键盘
  26. isClosed:false,
  27. value:props.value,
  28. // placeholderFlag:false,
  29. labelVal:'',
  30. boxLeft:0,
  31. boxTop:0,
  32. tmpTop:0,
  33. tmpScroll:0
  34. };
  35. this.$span = React.createRef();
  36. this.$pre = React.createRef();
  37. this.$suf = React.createRef();
  38. this.$cont = React.createRef();
  39. this.select = this.select.bind(this);
  40. this.numInpBlur = this.numInpBlur.bind(this);
  41. this.handleSpanInp = this.handleSpanInp.bind(this);
  42. this.handleNumClick = this.handleNumClick.bind(this);
  43. this.changeToEdit = this.changeToEdit.bind(this);
  44. }
  45. select(obj){ //选中键盘上数字事件
  46. const {handleSelect,ikey,suffix,prefix,mainSaveText,formulaCode,mainData} = this.props;
  47. this.setState({
  48. hasSelect:true
  49. });
  50. if(!obj.text){
  51. this.setState({
  52. value:''
  53. });
  54. }
  55. handleSelect&&handleSelect({ikey,text:obj.text,suffix,prefix,mainSaveText,mark:obj.mark,formulaCode,mainData});
  56. }
  57. handleNumClick(e){
  58. e.stopPropagation();
  59. const {show,handleShow,ikey,id,patId,handleHide,value} = this.props;
  60. const {hasSelect} = this.state;
  61. const that = this;
  62. //双击时不显示下拉
  63. clearTimeout(this.state.timer);
  64. const timer = setTimeout(function(){
  65. const {hasSelect,editable,isClosed} = that.state;
  66. if(editable||isClosed){
  67. return;
  68. }
  69. handleShow&&handleShow({ikey,id:patId||id});
  70. },300);
  71. this.setState({
  72. timer,
  73. boxLeft:getPageCoordinate(e).boxLeft,
  74. boxTop:getPageCoordinate(e).boxTop,
  75. tmpScroll: $("#addScrollEvent")[0].scrollTop,
  76. tmpTop:getPageCoordinate(e).boxTop
  77. });
  78. $("#addScrollEvent").scroll(()=>{
  79. let scrollYs = $("#addScrollEvent")[0].scrollTop;
  80. this.setState({
  81. boxTop:this.state.tmpTop - scrollYs + this.state.tmpScroll
  82. })
  83. })
  84. handleHide&&handleHide();
  85. }
  86. //数字框失焦,保存值到store中
  87. numInpBlur(e){
  88. e.stopPropagation();
  89. // const {handleSelect,ikey,suffix,prefix,mainSaveText,handleLabelChange,boxMark,formulaCode} = this.props;
  90. const {handleSelect,ikey,mainSaveText,handleLabelChange,boxMark,formulaCode} = this.props;
  91. const {editable} = this.state;
  92. if(editable){
  93. // const text = e.target.innerText || e.target.innerHTML;
  94. // this.$span.current.innerText=''; //修改生成文字变成输入的2倍bug
  95. let totalVal = e.target.innerText|| e.target.innerHTML;
  96. let changeVal = this.$span.current.innerText.replace(/^\s*/,'');//数字框值-修改后;去掉前空格避免多空格叠加
  97. let prefix = this.$pre.current.innerText.replace(/^\s*/,''); //前缀值-修改后
  98. let suffix = this.$suf.current.innerText.replace(/^\s*/,''); //后缀值-修改后
  99. // console.log('数字框:'+changeVal,";全部:"+totalVal,";前缀:"+prefix+";后缀:"+suffix);
  100. handleLabelChange && handleLabelChange({ikey,changeVal,type:boxMark,totalVal,prefix,suffix,formulaCode});
  101. // handleSelect&&handleSelect({ikey,text,suffix,prefix,mainSaveText});
  102. // handleLabelChange&&handleLabelChange({ikey,changeVal:text,suffix,prefix,mainSaveText,type:boxMark,formulaCode});
  103. }
  104. this.setState({
  105. isClosed:false,
  106. numEditable:true,
  107. hasSelect:false,
  108. editable:false
  109. });
  110. }
  111. handleSpanInp(e){ //数字框输入事件
  112. e.stopPropagation();
  113. // 主诉字数达到上限时不允许输入
  114. const {mainSaveText,ikey,type,handleSelect,suffix,prefix,boxMark} = this.props;
  115. const {labelVal,editable} = this.state;
  116. let mainText = filterDataArr(mainSaveText);//主诉字数
  117. if(editable){//避免IE中点击标签也会触发
  118. let val = e.target.innerText || e.target.innerHTML;
  119. if(+boxMark==1){
  120. if(mainText.length >= config.limited){
  121. if(val.length > labelVal.length){
  122. e.target.innerText?(e.target.innerText = labelVal):(e.target.innerHTML = labelVal);
  123. Notify.info(config.limitText);
  124. return
  125. }else if(val.length == labelVal.length){
  126. this.setState({
  127. labelVal:val
  128. });
  129. }else{
  130. handleSelect&&handleSelect({ikey,text:val,suffix,prefix,mainSaveText});
  131. }
  132. }
  133. }
  134. }
  135. }
  136. getClasses(){ //整个标签是否有值的状态
  137. const {value,hideTag,show,isImports} = this.props;
  138. const inpValue = this.state.value;
  139. const blueBorder = this.state.editable?style['blue-border']:'';
  140. const isSelected = value||inpValue?style['selected']:style['container'];
  141. const orgBorder = isImports&&!(value||inpValue)?style['orange-border']:'';
  142. const noTag = hideTag?style['no-tag']:'';
  143. if(show){
  144. $(this.$cont.current).addClass(style['borderd']);
  145. }else{
  146. $(this.$cont.current).removeClass(style['borderd']);
  147. }
  148. return className(isSelected,noTag,blueBorder,orgBorder);
  149. }
  150. changeToEdit(e){ //整个标签双击编辑状态
  151. e.stopPropagation();
  152. window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
  153. const {value,id,handleDbclick,patId,handleHide,show} = this.props;
  154. const text = e.target.innerText || e.target.innerHTML;
  155. clearTimeout(this.state.timer);//取消延时的单击事件
  156. e.preventDefault();
  157. if(show){
  158. handleHide&&handleHide();
  159. }
  160. if(value&&value.trim()) {//有选中值的标签才能双击编辑
  161. this.setState({
  162. editable: true,
  163. labelVal:text
  164. });
  165. //失焦关闭编辑状态
  166. setTimeout(()=>{
  167. // e.target.focus();
  168. this.$cont.current.focus();
  169. })
  170. //双击埋点记录
  171. handleDbclick && handleDbclick({id:patId||id});
  172. }
  173. }
  174. componentDidMount(){
  175. if(isIE()){
  176. // $(this.$span.current).onIe8Input(function(e){
  177. $(this.$cont.current).onIe8Input(function(e){
  178. this.handleSpanInp(e)
  179. },this);
  180. }
  181. }
  182. render(){
  183. const {placeholder,prefix,suffix,show,value,handleHide} = this.props;
  184. const {numEditable,editable,hasSelect,boxLeft,boxTop} = this.state;
  185. return <div className={this.getClasses()}
  186. ref={this.$cont}
  187. onClick={this.handleNumClick}
  188. contentEditable={editable}
  189. onBlur={this.numInpBlur}
  190. onDoubleClick={this.changeToEdit}
  191. onkeydown={handleEnter}
  192. onInput={this.handleSpanInp}>
  193. <span ref = {this.$pre}>{prefix?prefix+' ':prefix}</span>
  194. <span ref = {this.$span}
  195. onkeydown={handleEnter}
  196. style={{cursor:editable?'text':'pointer'}}>{value||placeholder}</span>
  197. <span ref = {this.$suf}>{suffix?' '+suffix:suffix}</span>
  198. <NumberUnitPan handleSelect={(obj)=>this.select(obj)}
  199. onClose={handleHide}
  200. top={boxTop}
  201. left={boxLeft}
  202. show={show} toClear={!hasSelect} value={value}/>
  203. </div>
  204. }
  205. }
  206. export default NumberUnitDrop;