Переглянути джерело

单列多选添加位置计算

Luolei 6 роки тому
батько
коміт
fe321852c9

+ 0 - 1
src/components/MultSpread/index.jsx

@@ -66,7 +66,6 @@ class MultSpread extends Component{
                             hideTag={true}></RadioDrop>;
         case +it.controlType===2:
           const dataList = it.questionDetailList&&it.questionDetailList.length>0?it.questionDetailList:it.questionMapping;
-          console.log(it.name,'zhizhizhi')
           return <Multiple data={dataList}
                            ikey={inx}
                            placeholder={it.name}

+ 162 - 0
src/components/Multiple/SlideItem/index.jsx

@@ -0,0 +1,162 @@
+import react from "react";
+import style from "./index.less";
+import $ from 'jquery';
+import classNames from 'classnames';
+import {handleEnter,isIE,filterArr,deepClone,filterDataArr} from '@utils/tools.js';
+import {Notify} from '@commonComp';
+import ReactDom from "react-dom";
+import config from '@config/index.js';
+/**
+  单列多选组件(tagtype=1,controlType=2)
+  2019-2-20 By_liucf
+  参数:
+  placeholder:标签名
+  value:标签选中的值
+  show:是否展示下拉
+  data:下拉数据
+  type:标识哪一项数据(1-主诉,2-现病史,3-其他史,4-查体)
+**/
+
+class Multiple extends react.Component{
+  constructor(props){
+    super(props);
+    const {seleData,seleId} = deepClone(props.selecteds||[]);
+    this.state={
+      editable:false,
+      timer:null,
+      labelVal:"",
+      seleData:seleData||"",
+      seleId:seleId||[],
+      boxLeft:null,
+      boxTop:null
+    }
+    this.$div = React.createRef();
+    this.handleSelect = this.handleSelect.bind(this);
+    this.onChange = this.onChange.bind(this);
+    this.handleBlur = this.handleBlur.bind(this);
+    this.handleClear = this.handleClear.bind(this);
+    this.handleComfirn = this.handleComfirn.bind(this);
+  }
+
+  getListClass(){
+    let name = style['text-list'];
+    let isHide = this.props.show?'':style['hide'];
+    return classNames(style['list'],name,isHide);
+  }
+
+  getSeleStyle(id){
+    const {seleId} = this.state;
+    if(seleId.includes(id)){
+      return style['selected'];
+    }
+    return '';
+  }
+
+  handleSelect(e,item){
+    e&&e.stopPropagation();
+    let {seleData,seleId} = this.state;
+    const {name,id} = item;
+    if(seleId.includes(id)){
+      seleId.splice(seleId.indexOf(id),1);
+      seleData = seleData.replace(name,'');
+    }else{
+      seleId.push(id);
+      seleData += name;
+    }
+    this.setState({
+      seleData,
+      seleId
+    })
+  }
+
+  onChange(e){
+    const {mainSaveText,ikey,type,handleLabelChange} = this.props;
+    const {labelVal,editable} = this.state;
+    let mainText = filterDataArr(mainSaveText);//主诉字数
+    if(editable){//避免IE中点击标签也会触发
+      let val = e.target.innerText || e.target.innerHTML;
+      if(+type==1){// 主诉字数达到上限时不允许输入
+        if(mainText.length >= config.limited){
+          if(val.length > labelVal.length){
+            e.target.innerText?(e.target.innerText = labelVal):(e.target.innerHTML = labelVal);
+            Notify.info(config.limitText);
+            return
+          }else if(val.length == labelVal.length){
+            this.setState({
+              labelVal:val
+            });
+          }else{
+            handleLabelChange && handleLabelChange({ikey,changeVal:val,type});
+          }
+        }
+      }
+    }
+  }
+
+  handleBlur(e){//修改存值
+    e.stopPropagation();
+    const {ikey,type,handleLabelChange} = this.props;
+    const {editable} = this.state;
+    const ev = e || window.event;
+    if(editable){
+      // 更改标签的value值
+      let changeVal = ev.target.innerText || e.target.innerHTML;
+      if(!isIE()){
+        e.target.innerText?(e.target.innerText = ''):(e.target.innerHTML='');      //避免出现重复输入值
+      }
+      handleLabelChange && handleLabelChange({ikey,changeVal,type});
+    }
+    this.setState({
+      editable:false
+    });
+  }
+
+  handleClear(e){
+    e&&e.stopPropagation();
+    this.setState({
+      seleData:"",
+      seleId:[]
+    })
+  }
+
+  handleComfirn(e){
+    e&&e.stopPropagation();
+    const {handleConfirm,ikey,order,mainSaveText,value,handleHide,type} = this.props;
+    const params = Object.assign({},this.state,{ikey,order,mainSaveText,value,type});
+    handleConfirm&&handleConfirm(params);
+    handleHide&&handleHide();
+  }
+
+  componentDidMount(){
+    if(isIE()){
+      $(this.$div.current).onIe8Input(function(e){
+        this.onChange(e)
+      },this);
+    }
+  }
+  getStyle(){
+    const {left,top,show} = this.props;
+    return {
+      left:left?left+'px':'0',
+      top:top?top+'px':'0',
+      display:show?'table':'none'        //table onBlur阻止冒泡是为了修复multSpread中数字键盘点击触发最外层数字组件onBlur事件
+    }
+  }
+  render(){
+    const {placeholder,value,show,data} = this.props;
+    const {editable,boxTop,boxLeft} = this.state;
+    const domNode = document.getElementById('root');
+    return ReactDom.createPortal(
+      <div className={this.getListClass()} style={this.getStyle()} contentEditable="false">
+        <ul>
+          {data&&data.map((it)=>{
+          return <li onClick={(e)=>this.handleSelect(e,it)} className={this.getSeleStyle(it.id)} title={it.name.length>8?it.name:''}>{it.name&&it.name.length>8?it.name.slice(0,8)+'...':it.name}</li>
+        })}
+          <li onClick={this.handleClear} className={style['mClear']}>清空选项</li>
+          <li onClick={this.handleComfirn} className={style['mConfirm']}>确定</li>
+        </ul>
+      </div>,domNode)
+  }
+}
+
+export default Multiple;

+ 53 - 0
src/components/Multiple/SlideItem/index.less

@@ -0,0 +1,53 @@
+@import "~@less/mixin.less";
+.container{
+  display: inline-block;
+}
+.selected{
+    .select-li;
+  }
+.tag,.selected-tag{
+  cursor: pointer;
+  line-height: 20px;
+}
+
+.selected-tag{
+  padding: 0;
+  color: @text-color;
+  border-bottom: 1px @border-color solid;
+  line-height: 22px;
+}
+.hide-tag{
+  padding: 0;
+  color: @text-color;
+  line-height: 22px;
+}
+.list{
+  .pop;
+  padding: 0 0 10px;
+  color: @text-color;
+  li{
+    height: 32px;
+    line-height: 32px;
+    border:1px #fff solid;
+    padding: 0 20px;
+    white-space: nowrap;
+    cursor: pointer;
+  }
+  // li:hover,.selected{
+  li:hover{
+    border-color:#3B9ED0;
+  }
+}
+.hide{
+  display: none;
+}
+
+.mClear{
+  color:red;
+}
+.mConfirm{
+  color: #3B9ED0;
+  text-align: center;
+  border: 1px solid #3B9ED0;
+
+}

+ 30 - 38
src/components/Multiple/index.jsx

@@ -2,9 +2,9 @@ import react from "react";
 import style from "./index.less";
 import $ from 'jquery';
 import classNames from 'classnames';
-import {handleEnter,isIE,filterArr,deepClone,filterDataArr} from '@utils/tools.js';
+import {handleEnter,isIE,filterArr,deepClone,filterDataArr,getPageCoordinate} from '@utils/tools.js';
 import {Notify} from '@commonComp';
-import ReactDom from "react-dom";
+import SlideItem from "./SlideItem";
 import config from '@config/index.js';
 /**
   单列多选组件(tagtype=1,controlType=2)
@@ -28,7 +28,9 @@ class Multiple extends react.Component{
       seleData:seleData||"",
       seleId:seleId||[],
       boxLeft:null,
-      boxTop:null
+      boxTop:null,
+      tmpScroll:null,
+      tmpTop:null
     }
     this.$div = React.createRef();
     this.handleShow = this.handleShow.bind(this);
@@ -37,7 +39,6 @@ class Multiple extends react.Component{
     this.onChange = this.onChange.bind(this);
     this.handleBlur = this.handleBlur.bind(this);
     this.handleClear = this.handleClear.bind(this);
-    this.handleComfirn = this.handleComfirn.bind(this);
   }
 
   getClass(){
@@ -74,8 +75,16 @@ class Multiple extends react.Component{
     const ht = e.target.offsetHeight;   //如杂音选中文字有多行时,写死会遮挡
     let boxTop = offsetTop + ht +2 + 'px';
     this.setState({
-      boxLeft:boxLeft,
-      boxTop:boxTop
+      boxLeft:getPageCoordinate(e).boxLeft,
+      boxTop:getPageCoordinate(e).boxTop,
+      tmpScroll: $("#addScrollEvent")[0].scrollTop,
+      tmpTop:getPageCoordinate(e).boxTop
+    })
+    $("#addScrollEvent").scroll(()=>{
+      let scrollYs = $("#addScrollEvent")[0].scrollTop;
+      this.setState({
+        boxTop:this.state.tmpTop - scrollYs + this.state.tmpScroll
+      })
     })
      this.setStateInit();
     const {ikey,handleShow,placeholder,flag,id,value,tagType,type} = this.props;
@@ -182,14 +191,6 @@ class Multiple extends react.Component{
     })
   }
 
-  handleComfirn(e){
-    e&&e.stopPropagation();
-    const {handleConfirm,ikey,order,mainSaveText,value,handleHide,type} = this.props;
-    const params = Object.assign({},this.state,{ikey,order,mainSaveText,value,type});
-    handleConfirm&&handleConfirm(params);
-    handleHide&&handleHide();
-  }
-
   componentDidMount(){
     if(isIE()){
       $(this.$div.current).onIe8Input(function(e){
@@ -197,21 +198,10 @@ class Multiple extends react.Component{
       },this);
     }
   }
-  getStyle(){
-    const {left,top,show} = this.props;
-    return {
-      left:left?left+'px':'0',
-      top:top?top+'px':'0',
-      display:show?'table':'none'        //table onBlur阻止冒泡是为了修复multSpread中数字键盘点击触发最外层数字组件onBlur事件
-    }
-  }
   render(){
-    const {placeholder,value,show,data} = this.props;
-    console.log(placeholder,'name')
+    const {placeholder,value,show,data,handleConfirm,ikey,order,mainSaveText,handleHide,type} = this.props;
     const {editable,boxTop,boxLeft} = this.state;
-    const domNode = document.getElementById('root');
-    return ReactDom.createPortal(<div className={style["container"]}>
-    {/* return <div className={style["container"]}> */}
+    return <div className={style["container"]}>
       <div className={this.getClass()}
       ref={this.$div}
       onClick={this.handleShow}
@@ -220,18 +210,20 @@ class Multiple extends react.Component{
       onInput={this.onChange}
       onkeydown={handleEnter}
       contentEditable={editable}>{value||placeholder}</div>
-      <div className={this.getListClass()} style={{top:boxTop,left:boxLeft}} contentEditable="false">
-        <ul>
-          {data&&data.map((it)=>{
-          return <li onClick={(e)=>this.handleSelect(e,it)} className={this.getSeleStyle(it.id)} title={it.name.length>8?it.name:''}>{it.name&&it.name.length>8?it.name.slice(0,8)+'...':it.name}</li>
-        })}
-          <li onClick={this.handleClear} className={style['mClear']}>清空选项</li>
-          <li onClick={this.handleComfirn} className={style['mConfirm']}>确定</li>
-        </ul>
-        
+      <div className={this.getListClass()} contentEditable="false">
+        <SlideItem 
+          show={show} 
+          left={boxLeft} 
+          top={boxTop} 
+          data={data} 
+          handleConfirm={handleConfirm} 
+          ikey={ikey}
+          order={order}
+          mainSaveText={mainSaveText}
+          handleHide={handleHide}
+          type={type}></SlideItem>
       </div>
-    {/* </div> */}
-    </div>,domNode)
+    </div>
   }
 
 }

+ 35 - 27
src/components/TemplateItems/TemplateItem/index.jsx

@@ -30,6 +30,7 @@ class TemplateItem extends React.Component {
         this.titleDOM = null;
         this.isConfirmClick = false;
         this.timer = null;
+        this.handleTitleClick = this.handleTitleClick.bind(this)
     }
     genContent() {
         const {preview} = this.props;
@@ -63,28 +64,28 @@ class TemplateItem extends React.Component {
         this.props.handleContentClick(this.props.id,sex);
     }
 
-    handleTitleClick() {
-        if (this.isAnimate) {
-            return;
-        }
-        this.isAnimate = true;
-        if (this.state.isOpen) {
-            $(this.content).slideUp(() => {
-                this.isAnimate = false;
-                this.setState({
-                    isOpen: false
-                });
-            });
-            // console.log($(this.content).parent().siblings().find('.content'))
-            return;
-        }
-        $(this.content).slideDown(() => {
-            this.isAnimate = false;
-            this.setState({
-                isOpen: true
-            });
-        });
-    }
+    // handleTitleClick() {
+    //     if (this.isAnimate) {
+    //         return;
+    //     }
+    //     this.isAnimate = true;
+    //     if (this.state.isOpen) {
+    //         $(this.content).slideUp(() => {
+    //             this.isAnimate = false;
+    //             this.setState({
+    //                 isOpen: false
+    //             });
+    //         });
+    //         // console.log($(this.content).parent().siblings().find('.content'))
+    //         return;
+    //     }
+    //     $(this.content).slideDown(() => {
+    //         this.isAnimate = false;
+    //         this.setState({
+    //             isOpen: true
+    //         });
+    //     });
+    // }
     handleCheckboxClick(e,id){          //点击复选框
         e.stopPropagation();
         let tempCheck = this.state.checkBox;
@@ -157,6 +158,15 @@ class TemplateItem extends React.Component {
         this.titleDOM.innerHTML = this.props.title;
     }
 
+    handleTitleClick(e) {
+      $(e.target).next().slideToggle() 
+      let tmpDomLis = $(e.target).parent().siblings()
+      for(let i = 0;i < tmpDomLis.length;i++){
+        let tmpDiv = tmpDomLis[i]
+        $(tmpDiv).children().eq(1).slideUp()
+      }
+    }
+
     render() {
         const { allCheckShow,id,name,preview,sex } = this.props;
         let previewJson = JSON.parse(preview);
@@ -166,8 +176,8 @@ class TemplateItem extends React.Component {
                 <div className={ 
                     allCheckShow?
                     `${style["title-wrapper"]} ${style["clearfix"]} ${style[this.getCheckIcon()[1]]}`:
-                    `${style["title-wrapper"]} ${style["clearfix"]}`} 
-                    onClick={() => this.handleTitleClick()}
+                    `${style["title-wrapper"]} ${style["clearfix"]}`}
+                    onClick={this.handleTitleClick}
                 >
                     {
                         allCheckShow?<div className={style['check-wrap']} onClick={(e)=>{this.handleCheckboxClick(e,id)}}>
@@ -184,7 +194,7 @@ class TemplateItem extends React.Component {
                     </span>
                     <img className={style.arrow} src={this.getArrow()} />
                     <img title={'删除模板'} 
-                        className={style.del} 
+                        className={style.del}
                         style={{display:allCheckShow?'none':'block'}}
                         src={this.getDelIcon()} 
                         onMouseEnter={() => this.handleDelIconMouseEnter()}
@@ -204,12 +214,10 @@ class TemplateItem extends React.Component {
                     ref={(content) => this.content = content}
                     className={style.content}
                     title={this.title}
-                    style={this.getContentStyle()}
                 >
                     {
                         previewJson?<DesItem preview={previewJson}></DesItem>:<p>暂无数据</p>
                     }
-                    
                 </div>
             </div>
         )

+ 1 - 0
src/components/TemplateItems/TemplateItem/index.less

@@ -131,5 +131,6 @@
     width: 100%;
     box-sizing: border-box;
     cursor: pointer;
+    display: none;
   }
 }