Kaynağa Gözat

Merge remote-tracking branch 'origin/master' into referMaster

zhouna 5 yıl önce
ebeveyn
işleme
895988a141

+ 2 - 2
build/webpack.dev.conf.js

@@ -32,9 +32,9 @@ const devWebpackConfig = merge(baseWebpackConfig, {
     // openPage:'?hospitalCode=A001&hospitalDeptCode=D01&doctorCode=YS001&patientCode=1600&recordId=44',//携带参数
     contentBase: false, // since we use CopyWebpackPlugin.
     compress: true,
-    // host: HOST || config.dev.host,
+    host: HOST || config.dev.host,
     // host: '192.168.3.6',
-    host: '192.168.3.106',
+    // host: '192.168.0.105',
     port: PORT || config.dev.port,
     open: config.dev.autoOpenBrowser,
     overlay: config.dev.errorOverlay

+ 4 - 2
config/index.js

@@ -3,9 +3,11 @@
 // see http://vuejs-templates.github.io/webpack for documentation.
 
 const path = require('path')
-// const proxy_path = 'http://192.168.2.236:80';
+//const proxy_path = 'http://192.168.2.121:5050';
 // const proxy_path = 'http://192.168.2.236:5050';
 const proxy_path = 'http://192.168.2.241:5050';
+// const proxy_path = 'http://223.93.170.82:23650';
+// const proxy_path = 'http://223.93.170.82:24182';
 
 module.exports = {
   dev: {
@@ -21,7 +23,7 @@ module.exports = {
     },
 
     // Various Dev Server settings
-    port: 8082, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+    port: 8083, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
     autoOpenBrowser: true,
     errorOverlay: true,
     notifyOnErrors: true,

+ 2 - 0
src/App.vue

@@ -4,6 +4,8 @@
         <portal-target name="notification-outlet"></portal-target>
         <portal-target name="notification-detail"></portal-target>
         <portal-target name="notification-search"></portal-target>
+        <portal-target name="notification-usual"></portal-target>
+        <portal-target name="notification-head"></portal-target>
     </div>
 </template>
 <script>

+ 33 - 52
src/common/ComTextArea.vue

@@ -1,11 +1,13 @@
 <template>
-  <div class="comArea" :style="getStyle(detail,slide)">
-    <textarea @input="changeVal" 
-            :style="{width:width,height:height}" 
-            v-model="txt" 
+  <div class="comArea" @touchmove.prevent>
+    <textarea
+            :style="{width:width,height:height}"
+            v-model="txt"
             placeholder="请输入"
-            @focus="focus"
-            @blur="blur"></textarea>
+            @input="changeVal"></textarea>
+    <div :class="txt?'realSure sure':'sure'" @click="makeSuer">
+      确定
+    </div>
   </div>
 </template>
 
@@ -15,6 +17,9 @@ import $ from 'jquery'
 export default {
   name:'ComTextArea',
   props: {
+    num:{
+      default:0
+    },
     width: {
       default: '100%',
       type: String
@@ -24,73 +29,49 @@ export default {
       type: String
     },
     item:{
-      type:Object,
-      require: true
-    },
-    slide:{
-      default:false,
-      type:Boolean
-    },
-    detail:{
-      default:2,
-      type:Number||String
+      default:{}
     }
   },
   data() {
     return {
-      txt:this.item.value || '' //回读用
-      // txt:'' 
+      txt: this.item.content||'', //回读用
+      sure:false,
+      // txt:''
     }
   },
   methods:{
-    getStyle(detail,slide){
-      if(detail == 1){
-        if(slide){
-          return {'display':'block','background-color': '#F9F9F9'}
-        }else{
-          return {'display':'none'}
-        }
+    changeVal(e){
+      this.txt = e.target.value;
+      const notNull=this.txt.match(/\S/g);
+      if(notNull){
+        this.sure=true;
       }else{
-        return {'display':'block'}
+        this.sure=false;
       }
     },
-    changeVal(){
-      this.$emit('changeAreaVal',this.txt)
-      const newData = Object.assign({},this.item,{value:this.txt,valueP:this.txt});
-      this.$emit("updata",newData);
-    },
-    blur(){
-      setTimeout(()=>{
-        $(".foot").css({'display':'block'})
-      },150)
-    },
-    focus(){
-      if(isIos()){
-        setTimeout(() => {
-          $(".foot").css({'display':'none'})
-        }, 150);
-      }
+    makeSuer(){
+      if(!this.txt){return}
+      let n = this.num;
+      this.$emit("updata",'',{val:this.txt||'无',valp:this.txt||'无'},++n);
     }
   },
-  watch:{
-    item:{//清空时更新数据
-      handler(newVal,oldVal){
-        this.txt = newVal.value;
-      },
-      deep:true
-    }
-  }
 }
 </script>
 <style lang="less" scoped>
 @import '../less/base.less';
   .comArea {
-    .bgques;
+    width: 100%;
+    position:fixed;
+    bottom:0;
+    background:#fff;
+    padding:0.28rem 0 0;
+    box-shadow: 0 0 30px -10px rgba(104, 124, 189, 0.25);
+    text-align: center;
     textarea {
       color: #4F50FF;
       resize: none;
       box-shadow: none;
-      font-size: 0.3rem;
+      font-size: #font[select];
       box-sizing: border-box;
       border: 1px solid #DFE0E4;
       border-radius: .08rem /* 8/100 */;

+ 89 - 0
src/common/ConfirmBox.vue

@@ -0,0 +1,89 @@
+<template>
+    <!--<van-overlay :show="show" @click="">-->
+      <div class="wrapper" :show="show" @click.stop>
+          <div class="title">
+              温馨提示
+          </div>
+          <div class="message">
+              本次问诊正在进行,确定退出?
+          </div>
+          <div class="buttonBox">
+              <span class="button okBtn" @click="confirm">确定</span>
+              <span class="button cancelBtn" @click="cancel">取消</span>
+          </div>
+      </div>
+    <!--</van-overlay>-->
+</template>
+<script>
+export default {
+    name:"ConfirmBox",
+    props:["show"],
+    methods: {
+        confirm(){
+            this.$emit("confirmDialog")
+        },
+        cancel(){
+            this.$emit("cancelDialog")
+        }
+    }
+}
+</script>
+<style lang="less" scoped>
+.wrapper{
+    position: fixed;
+  top: 45%;
+  left: 50%;
+  width: 6.4rem;
+  height: 3.36rem;
+  overflow: hidden;
+  font-size: 16px;
+  background-color: #fff;
+  border-radius: 16px;
+  -webkit-transform: translate3d(-50%, -50%, 0);
+  transform: translate3d(-50%, -50%, 0);
+  -webkit-backface-visibility: hidden;
+  backface-visibility: hidden;
+  -webkit-transition: 0.3s;
+  transition: 0.3s;
+  -webkit-transition-property: opacity, -webkit-transform;
+  transition-property: opacity, -webkit-transform;
+  transition-property: transform, opacity;
+  transition-property: transform, opacity, -webkit-transform;
+}
+.title {
+    height: .44rem;
+  line-height: .44rem;
+  font-size: .32rem;
+  color: #333;
+  width: 100%;
+  text-align: center;
+  padding: .6rem 0  .4rem 0;
+}
+.message {
+    height: .42rem;
+    line-height: .42rem;
+    font-size: .30rem;
+    color: #333;
+    width: 100%;
+    text-align: center;
+    padding: 0 0  .6rem 0;
+}
+.buttonBox {
+    position: absolute;
+    bottom: 0;
+    height: .9rem;
+    line-height: .9rem;
+    width: 100%;
+}
+.button{
+    display: inline-block;
+    width: 50%;
+    text-align: center;
+    box-sizing: border-box;
+    font-size: .32rem;
+    border: 1px solid #E6E6E6;
+}
+.okBtn {
+    color: #FF6167;
+}
+</style>

+ 119 - 0
src/common/Dialog.vue

@@ -0,0 +1,119 @@
+<template>
+  <div>
+    <div class="left clearfix" v-if="item.show">
+      <img src="../images/doctor.png" class="fl" />
+      <div class="content fl">
+        <p>{{item.name}}{{item.controlType==2?'(可多选)':''}}</p>
+      </div>
+    </div>
+    <div class="right clearfix" v-if="(!hideAreaVal)&&item.content">
+      <img v-if="typeof(item.content)==='string'" src="../images/patient.png" alt class="fr" />
+      <div v-if="typeof(item.content)==='string'" class="content fr">
+        <p>{{item.content}}</p>
+      </div>
+      <div v-else class="imgs-list">
+        <p>
+          <img v-for="img in item.content" :src="img" alt=""/>
+        </p>
+      </div>
+      <span class="edit" v-if="showEdit" @click="cancelPre(item.type,item.questionDetailList)">修改</span>
+    </div>
+  </div>
+</template>
+<script>
+  import {getNSum} from '@utils/tools';
+export default {
+  props:['item','idx','cancelNum','num','extNum','isLast','cancelTab'],   //num当前
+  data() {
+    return {};
+  },
+  computed:{
+    hideAreaVal(){      //文本域修改时不要显示已填的值
+      const {item,cancelNum,idx,num,extNum}=this;
+      let realExt=getNSum(extNum);
+      const realIdx = realExt+idx;
+      return (+item.controlType===5)&&realIdx===cancelNum&&num===realIdx;
+    },
+    showEdit(){
+      const {cancelNum,idx,num,extNum}=this;
+      let realExt=getNSum(extNum);
+      const realIdx = realExt+idx;
+      //console.log("cancelNum:",cancelNum,"idx:",idx,"num:",num,"extNum:",extNum,"realIdx:",realIdx);
+      //if((realCNum<realIdx&&realIdx===realNum-1)||(num===0&&isLast&&cancelNum!==idx)){
+      if(realIdx===num-1&&cancelNum<realIdx){
+        //console.log(true)
+        return true;
+      }
+      return false;
+    }
+  },
+  methods:{
+    cancelPre(type,result){
+      this.$emit("cancel",type,result,false,this.idx);
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+  @import "../less/base.less";
+.left {
+  margin-bottom: 0.2rem;
+  padding-top: 0.12rem;
+  padding-left: 0.24rem;
+  .content {
+    max-width: 5rem;
+    background-color: #colors[bgques];
+    border-radius: 0 0.24rem 0.24rem 0.24rem;
+    margin-top: 0.3rem;
+    font-size: #font[dialog];
+    padding: 0.24rem;
+    display: inline-block;
+  }
+  img {
+    width: 0.8rem;
+    height: 0.8rem;
+    margin-right: 0.24rem;
+  }
+}
+.right {
+  padding-top: 0.2rem;
+  margin-bottom: 0.12rem;
+  padding-right: 0.24rem;
+  .imgs-list{
+    max-width: 80%;
+    text-align: right;
+    float: right;
+    margin-right: 0.8rem;
+    img{
+      width: 1.5rem;
+      height: 1.5rem;
+    }
+  }
+  .edit{
+    color: #colors[theme];
+    font-style: normal;
+    font-size: #font[dialog];
+    float: right;
+    display: inline-block;
+    margin-top: .56rem;
+    margin-right: .24rem;
+  }
+  .content {
+    max-width: 4rem;
+    background-color: #colors[theme];
+    border-radius: 0.24rem 0 0.24rem 0.24rem;
+    margin-top: 0.3rem;
+    font-size: 0.3rem;
+    padding: 0.24rem;
+    display: inline-block;
+    p {
+      color: #fff;
+    }
+  }
+  img {
+    width: 0.8rem;
+    height: 0.8rem;
+    margin-left: 0.24rem;
+  }
+}
+</style>

+ 56 - 0
src/common/Head.vue

@@ -0,0 +1,56 @@
+<template>
+  <portal to="notification-head">
+    <div class="progress-bar">
+      <div class="title">
+        <span :class="{'active':activeTab==i.type}" :style="{width:(100/allMoudles.length)+'%'}" v-for="i in allMoudles">{{i.name}}</span>
+      </div>
+      <div class="progress">
+        <p :style="{width:progress}"></p>
+      </div>
+    </div>
+  </portal>
+</template>
+<script>
+export default {
+  props:['activeTab','allMoudles','progress']
+}
+</script>
+<style lang="less" scoped>
+@import "../less/base.less";
+
+.progress-bar {
+  height: .8rem;
+  line-height: 0.44rem;
+  background: #fff;
+  color: #aaa;
+  /*margin-bottom:.4rem;*/
+  .title{
+    height: 100%;
+  }
+  span{
+    display: inline-block;
+    font-size: .26rem;
+    color: #aaa;
+    text-align: center;
+    &:not(:last-child):after{
+        content: ">";
+        float: right;
+        color: #aaa;
+     }
+  }
+  .active{
+    font-size: #font[dialog];
+    color: #colors[theme];
+    font-weight: 500;
+  }
+  .progress{
+    height:0.06rem;
+    background:#F5F5F5;
+    p{
+      width:.1px;
+      height: 100%;
+      background: #colors[theme];
+    }
+  }
+}
+</style>

+ 7 - 4
src/common/HomePage.vue

@@ -34,14 +34,17 @@ export default {
     let timer = setInterval(() => {
       this.num = --num
       if(num == -1){
-        localStorage.setItem('startPage',0)
-        this.show = false
+        localStorage.setItem('startPage',0);
+        document.title = '挂号详情';
+        this.show = false;
         clearInterval(timer)
       }
     }, 1000);
   },
   methods:{
     close(){
+      localStorage.setItem('startPage',0);
+      document.title = '挂号详情';
       this.show = false
     },
     getDisclaimerInformations(){
@@ -119,10 +122,10 @@ export default {
   color: #fff;
   font-size: 0.32rem;
   font-weight: 500;
-  width: 5.2rem;
+  width: 5.1rem;
   position: absolute;
   bottom: 15%;
   left: 50%;
   margin-left: -2.6rem;
 }
-</style>
+</style>

+ 23 - 16
src/common/Input.vue

@@ -1,11 +1,14 @@
 <template>
   <div class="inp-wrap" :style="getStyle(detail,slide)">
-    <input :type="item.controlType==6?'text':'number'" 
-          :class="{'change':borColor}" 
-          v-model="val" 
-          @input="changeVal" 
+    <input :type="item.controlType==6?'text':'number'"
+          :class="{'change':borColor}"
+          v-model="val"
+          @input="changeVal"
           @focus="focus"
           @blur="blur">
+    <div class="realSure sure" @click="makeSuer">
+    确定
+  </div>
   </div>
 </template>
 <script type="text/javascript">
@@ -17,6 +20,9 @@
       item:{
         default:''
       },
+      num:{
+        default:-1
+      },
       slide:{
         default:false,
         type:Boolean
@@ -29,7 +35,7 @@
     data(){
       return{
         msg:"输入框",
-        val: this.item.value || '',
+        val: '',
         borColor:false
       }
     },
@@ -51,8 +57,10 @@
             this.val = e.target.value=e.target.value.replace(/^\.$/,'').slice(0,10)
         }
         this.borColor = false;
-        const newData = Object.assign({},this.item,{value:this.val,valueP:this.val});
-        this.$emit("updata",newData);
+      },
+      makeSuer(){
+        let n = this.num;
+        this.$emit("updata",'',{val:this.val||'无',valp:this.val||'无'},++n);
       },
       blur(){
         setTimeout(()=>{
@@ -83,21 +91,20 @@
 <style lang="less" scoped>
 @import '../less/base.less';
   .inp-wrap{
-    .bgques;    
-    padding-bottom: 0;
+    display: block;
+    position: fixed;
+    bottom: 0;
+    width: 100%;
+    padding:0.12rem 0 0;
+    text-align:center;
     input{
-      width: 100%;
+      width: 92%;
       color: #colors[theme];
       font-size: .3rem;
-      border: 0 none;
-      border-bottom: 1px solid #DFE0E4;
-      margin-bottom: .3rem;
-      border-radius: 0;
+      border-bottom: 1px solid #e6e6e6;
       outline-color: invert;
       padding-left: 0.1rem;
       box-sizing: border-box;
-      // background: #fff;
-      background: transparent;
     }
     .change{
       border-color:  #colors[theme];

+ 6 - 6
src/common/Label.vue

@@ -4,9 +4,9 @@
       <span>{{it.description||it.name}}</span>
       <span v-if="it.select==1" @click="deletSymp($event,it,index)"><img src="../images/del.png" alt=""></span>
     </p>
-    <Toast :message="delText" 
+    <Toast :message="delText"
           :show="showToast"
-          @comfirn="comfirnDel" 
+          @comfirn="comfirnDel"
           @cancel="cancelDel"/>
   </div>
 </template>
@@ -31,7 +31,7 @@
     created(){
       this.datas = this.item;
       // 回读互斥项标识
-      const arr = this.datas.questionMapping;
+      const arr = this.datas.questionMapping;console.log(this.item,this.datas.questionMapping)
       const filArr = arr.filter(it=>it.select==1);
       if(filArr.length > 0){
         this.exclusion = filArr[0].exclusionType;
@@ -43,7 +43,7 @@
     methods:{
       handleClick(it,index,flg){
         if(flg){
-          document.activeElement.blur();      
+          document.activeElement.blur();
           document.activeElement.scrollIntoViewIfNeeded(true);
           setTimeout(()=>{
             document.activeElement.scrollIntoViewIfNeeded(true);
@@ -176,5 +176,5 @@
       // background:#E3E4E8;
     }
   }
-  
-</style>
+
+</style>

+ 203 - 0
src/common/MultSelect.vue

@@ -0,0 +1,203 @@
+<template>
+  <portal to="notification-outlet">
+  <div class="select" @touchmove.prevent>
+    <ul class="clearfix">
+      <li
+        v-for="(item,idx) in result"
+        :class="[{'liSelect':item.select,'noBorder':((item.description||item.name).indexOf('${'))!=-1}]"
+        :key="item.id"
+      >
+        <span v-if="((item.description||item.name).indexOf('${'))==-1">{{item.description||item.name}}</span>
+        <OptionInp v-else :item="item" @handleInp="inpVal" :inx="idx"/>
+      </li>
+    </ul>
+    <div :class="sure?'realSure sure':'sure'" @click="makeSuer">
+      确定 <span v-if="numPlus">({{numPlus}})</span>
+    </div>
+  </div>
+  </portal>
+</template>
+<script>
+  import OptionInp from '../common/OptionInp.vue';
+  import {concatVal,getExpStr} from '../utils/tools.js';
+export default {
+  props: ["symptomResult","num"],
+  data() {
+    return {
+      result: [], //答案结果
+      connectResult: [], //id
+      contentResult: "", //name
+      rules: [], //规则所需数据value
+      numPlus:0,     //已选答案个数
+      sure:false
+    };
+  },
+  mounted() {
+    //this.numPlus = this.num
+    console.log(this.symptomResult.questionDetailList)
+    this.result = this.symptomResult.questionDetailList;
+  },
+  watch:{
+    result: {
+      handler(newArr) {
+        let num = 0,sldNum=0;
+        for(let i = 0;i < newArr.length;i++){
+          if(!newArr[i].select){
+            ++num;
+          }else{
+            sldNum++;
+          }
+        }
+        this.numPlus =sldNum;
+      },
+      immediate: true,
+      deep:true
+    }
+  },
+  methods: {
+    inpVal(val,index){//输入框失焦处理
+      // 输入框回读
+      let detailList = this.result;
+      let currItem = detailList[index];
+      currItem.value = val;
+      const notNull=val.match(/\S/g);
+      if(notNull){
+        this.sure=true;
+      }else{
+        if(detailList.findIndex((it)=>(it.value||'').match(/\S/g))!==-1){
+          this.sure=true;
+        }else{
+          this.sure=false;
+        }
+      }
+
+    },
+    handleClick(it,index,flg,ipt){
+      if(flg){
+        document.activeElement.blur();
+        document.activeElement.scrollIntoViewIfNeeded(true);
+        setTimeout(()=>{
+          document.activeElement.scrollIntoViewIfNeeded(true);
+        },300)
+      }
+      /*let data = it.questionDetailList&&it.questionDetailList.slice(0); //数组深拷贝
+      if(ipt){//输入框单选,输入了内容才算选中,删除内容算取消
+        for(let i=0;i<data.length; i++){
+          if(i==index){
+            data[i].select=data[i].value?1:0;
+          }else{
+            data[i].select = 0
+          }
+        }
+      }else{
+      for(let i=0;i<data.length; i++){
+        if(i==index){
+          data[i].select = data[i].select==1?0:1;
+        }else{
+          data[i].select = 0
+        }
+      }*/
+      /*}
+      let temp = concatVal(data);
+      const newData = Object.assign({},this.datas,{questionDetailList:data,value:temp.value,valueP:temp.valueP});
+      this.$emit("updata",newData);*/
+    },
+    makeSuer() {
+      if(!this.sure)return;
+      let result = this.result;
+      // if(this.numPlus == 1){
+      let tmpResult=[],tmpResultp=[];
+      for (let i = 0; i < result.length; i++) {
+        const text=result[i].name;
+        const textp=result[i].description||result[i].name;
+        const msg = getExpStr(text);
+        const msgp = getExpStr(textp);
+        if(result[i].name.indexOf("${")!==-1){
+          if((result[i].value||'').match(/\S/g)){
+            tmpResult.push(msg.prefix+(result[i].value||"")+msg.suffix);
+            tmpResultp.push(msgp.prefix+(result[i].value||"")+msgp.suffix);
+          }
+        }else {
+          //tmpIds=tmpIds.concat(result[i].connectId)
+          tmpResult.push(text);
+          tmpResultp.push(textp);
+        }
+        }
+      // }else{
+
+      // }
+      let number = this.num;
+      this.$emit("updataResult", this.symptomResult,  {val:tmpResult.join('、'),valp:tmpResultp.join('、')},++number);
+
+    },
+    /*selectResult(item,idx) {
+      const { exclusion, select } = item;
+      let result = JSON.parse(JSON.stringify(this.result));
+      if (select) {//判断是否选中,选中的取消,关联id删除,未选中判断是否互斥
+        for (let i = 0; i < result.length; i++) {
+          if(i == idx){
+            result[i].select = false
+          }
+        }
+      }else{
+        if(+exclusion === 1){
+          for (let i = 0; i < result.length; i++) {
+              if(i == idx){
+                result[i].select = true
+              }else{
+                result[i].select = false
+              }
+          }
+        }else{
+          for (let i = 0; i < result.length; i++) {
+            if(result[i].select&&+result[i].exclusion === 1){
+              result[i].select=false
+            }else{
+              if(i == idx){
+                result[i].select = true
+              }
+            }
+          }
+        }
+      }
+      this.result = result
+    }*/
+  },
+  components:{
+    OptionInp
+  }
+};
+</script>
+<style lang="less" scoped>
+  @import "../less/base.less";
+.select {
+  background-color: #fff;
+  padding: 0.12rem 0 0 0;
+  position: fixed;
+  width: 100%;
+  bottom: 0;
+  box-sizing: border-box;
+  box-shadow: 0 0 30px -10px rgba(104, 124, 189, 0.25);
+  li {
+    padding: 0.14rem 0.2rem;
+    border:1px #DFE0E4 solid;
+    border-radius: 0.36rem;
+    font-size: #font[select];
+    margin: 0.15rem 0.15rem 0;
+    float: left;
+    color: #666;
+  }
+  .liSelect {
+    color: #fff;
+    background-color: #colors[btn];
+    border-color:  #colors[btn];
+  }
+  .noBorder{
+    border: none;
+    width: 100%;
+    &.liSelect{
+       background: none;
+    }
+  }
+}
+</style>

+ 103 - 80
src/common/OptionInp.vue

@@ -1,21 +1,33 @@
 <!-- 带输入框选项 -->
 <template>
-  <div :class="['inpbox',{'iptCheck':item.select},{'exclu':exclu}]">
-    <img class="iptimg" :src="item.select?url[0]:url[1]" alt="">
-    <span class="prefix" v-if="msg.prefix">{{msg.prefix}}</span>
-    <!-- <div class="inp" @click="preClick"> -->
-      <input :type="msg.type=='number'?'number':'text'" 
-              :placeholder="msg.placeholder"
-              :style="{'width':!msg.prefix&&!msg.suffix?'90%':'33%'}"
-              :disabled="exclu"
-              :class="[{'exclu':exclu},{'cancel':item.select==0}]"
-              v-model="txt"
-              @click="handleCli"
-              @blur="handleBlur"
-              @focus="focus"
-              @input="changeVal">
-    <!-- </div> -->
-    <span class="suffix" v-if="msg.suffix">{{msg.suffix}}</span>
+  <div :class="['inpbox',{'iptCheck':item.select||item.value}]">
+    <span class="prefix" v-if="msg.prefix" @click="stopPop">{{msg.prefix}}</span>
+    <p v-if="isXy" class="mult-inps">
+      <input :type="msg.type=='number'?'number':'text'"
+             :placeholder="placeholders[0]"
+             :style="{'width':'45%'}"
+             :class="[{'cancel':item.select==0}]"
+             v-model="ssyTxt"
+             @click="handleCli"
+             @input="(e)=>changeXyVal(e,'ssyTxt')"
+      >/<input :type="msg.type=='number'?'number':'text'"
+               :placeholder="placeholders[1]"
+               :style="{'width':'45%'}"
+               :class="[{'cancel':item.select==0}]"
+               v-model="szyTxt"
+               @click="handleCli"
+               @input="(e)=>changeXyVal(e,'szyTxt')"
+    >
+    </p>
+    <input v-if="!isXy" :type="msg.type=='number'?'number':'text'"
+            :placeholder="msg.placeholder"
+            :style="{'width':!msg.prefix&&!msg.suffix?'90%':'33%'}"
+            :class="[{'cancel':item.select==0}]"
+           v-model="txt"
+           @click="handleCli"
+           @input="(e)=>changeVal(e)"
+    >
+    <span class="suffix" v-if="msg.suffix" @click="stopPop">{{msg.suffix}}</span>
   </div>
 </template>
 <script type="text/javascript">
@@ -23,57 +35,78 @@ import { getExpStr,isIos} from '@utils/tools';
 import $ from 'jquery';
   export default {
     name:'OptionInp',
+    props:['item','inx'],
     data(){
       return{
         msg:{},
-        txt:this.item.value || '',
+        txt:this.item.value||'',
         select:0,
+        placeholders:[],
+        isXy:false,   //是否是血压输入框
+        ssyTxt:'',    //收缩压
+        szyTxt:'',    //舒张压
         url:[require('../images/iptselect.png'),require('../images/iptdis.png')]
       }
     },
-    props:['item','exclu'],
     mounted(){
       const text = this.item.description || this.item.name;
       this.msg = getExpStr(text);
+      const placeholder=this.msg.placeholder;
+      if(placeholder){
+        this.placeholders=this.msg.placeholder.split("/");
+        this.placeholders.length>1?this.isXy=true:'';
+      }
+      if(this.txt.indexOf("/")!==-1){
+        this.isXy=true;
+        const arr = this.txt.split("/");
+        this.ssyTxt= arr[0];
+        this.szyTxt= arr[1];
+      }
       this.select = this.item.select;
     },
     methods:{
+      stopPop(e){
+        e.stopPropagation();
+      },
+      changeXyVal(e,flag){    //血压值输入事件
+        if(this.msg.type=='number'){//数字键盘
+          this[flag] = e.target.value=e.target.value.replace(/^\.$/,'')
+        }
+        if(this.ssyTxt.match(/\S/g)&&this.szyTxt.match(/\S/g)){   //2个都填
+          this.txt = this.ssyTxt+"/"+this.szyTxt;
+
+        }else{
+          this.txt ='';
+        }
+        this.$emit('handleInp',this.txt,this.inx);
+      },
       changeVal(e){
+        /*const val = e.target.value;
+        if(!val.match(/\S/g)){      //只有空白符不算输入
+          this.txt='';
+        }*/
         if(this.msg.type=='number'){//数字键盘
-            this.txt = e.target.value=e.target.value.replace(/^\.$/,'').slice(0,10)
+          this.txt = e.target.value=e.target.value.replace(/^\.$/,'')
+        }
+        this.$emit('handleInp',this.txt,this.inx);
+        const notNull=this.txt.match(/\S/g);
+        if(notNull&&!this.item.select||(!notNull&&this.item.select)){
+          this.$emit("handleSelect")
         }
-        const newData = Object.assign({},this.part,{value:this.txt});
-        this.$emit("updata",newData);
-        this.$emit('handleInp',this.txt);
-        this.$emit('handleSelec');
       },
       handleBlur(){
-        setTimeout(()=>{
+       /* if(this.txt){
+          this.$emit('handleInp',this.txt,this.inx);
+        }*/
+        /*setTimeout(()=>{
           $(".foot").css({'display':'block'})
-        },150)
-          // 如果该项未选中,则不存值
-        // const select = this.item.select;
-        // if(!select){return}
-        // const newData = Object.assign({},this.part,{value:this.txt});
-        // this.$emit("updata",newData);
-        // this.$emit('handleInp',this.txt);
-      },
-      focus(){
-        if(isIos()){
-          setTimeout(() => {
-            $(".foot").css({'display':'none'})
-          }, 150);
-        }
-      },
-      preClick(e){
-        e.stopPropagation();
+        },150)*/
+
       },
       handleCli(e){
-        e.stopPropagation();
-        // const select = this.item.select;
-        if(!this.select&&this.txt){//聚焦时自动选中该项
-          this.$emit('handleSelec');
-        } 
+        if(this.select||!this.txt){//已选中后点击输入框不取消选中
+          e.stopPropagation();
+        }
       }
     },
     watch:{
@@ -95,51 +128,41 @@ import $ from 'jquery';
     width: 100%;
     white-space: normal;
     vertical-align: middle;
-    height: .42rem;
-    line-height: .42rem;
+    height: .68rem;
+    line-height: .68rem;
     margin-bottom:.08rem;
     .prefix,.suffix{
       display: inline-block;
       vertical-align: middle;
-    }
-    .iptimg {
-      width: .34rem;
-      height: .34rem;
-      margin-right: .1rem;
-      position: relative;
-      top: .06rem;
     }
      input{
-      height: .42rem;
-      color: #4F50FF;
-      font-size: .3rem;
-      border-bottom: 1px solid #CCCCCC !important;
+      height: 100%;
+      color: #colors[btn];
+      font-size: #font[select];
+      border-bottom: 1px solid #E6E6E6 !important;
       border-radius: 0;
       padding-left: .05rem;
       background-color: transparent;
-      height: 0.38rem;
-      line-height: 0.38rem;
       position: relative;
-      top: 1px;
+      /*top: 1px;*/
+       vertical-align: middle;
       box-sizing: border-box;
+       &.cancel{
+          color:#ccc ;
+        }
     }
-    .check{//选中
-      color: #colors[theme];
-    }
-    // .inp .exclu{ //互斥
-    .exclu{ //互斥
-      color:#colors[exclu] !important;
-    }
-    .cancel{ //取消
-      color: #bbbbbb !important;
-    }
-    input:disabled, input[disabled]{
-      background:transparent;
-      border-bottom-color: #DEDEDE !important;
-    }
-    // input:disabled,input[disabled]::-webkit-input-placeholder{
-    .exclu::-webkit-input-placeholder{
-      color:#e6e7e9 !important;
-    }
+.mult-inps{
+  width:70%;
+  display: inline-block;
+  height:100%;
+  /*input{
+    width:45%;
+  }*/
+}
+  }
+.iptCheck{
+  span{
+    color: #colors[btn];
   }
+}
 </style>

+ 181 - 134
src/common/Picker.vue

@@ -1,145 +1,192 @@
-<!-- 时间选择弹窗 -->
 <template>
-  <portal to="notification-outlet">
-      <div class="toast-wrap" v-if="show">
-        <div class="content">
-          <van-picker
-            :columns="columns"
-            :visible-item-count='5'
-            @change="handlechange"
-            :swipe-duration="time"
-          />
-          <div class="confBtn">
-            <div @click="getVal">确定</div>
+<portal to="notification-outlet">
+        <div class="pickerBox" @touchmove.prevent>
+            <div class="picker">
+                <van-picker :columns="columnsp"
+                    :visible-item-count = "5"
+                    :swipe-duration = "time"
+                    :item-height ="36"
+                    @change="changeTemp" />
+                <!-- <div class="selected">
+                </div> -->
+            </div>
+          <div class="realSure sure" @click="onConfirm">
+            确定
           </div>
         </div>
-      <div class="mask" @click="onCancel"></div>
-      </div>
-  </portal> 
+</portal>
 </template>
-<script type="text/javascript">
-  import $ from 'jquery';
-  let num = [];
-  for(let i = 1; i <=60; i++) {
-    num.push(i)
-  }
-  let unit = ['分钟', '小时', '天', '周', '月','年'];
-  export default {
-    name:'Picker',
-    data() {
-      return {
-        columns: [
-          {
-            values:num,
-            className:'column1',
-            defaultIndex: 0
-          },
-          {
-            values:unit,
-            className:'column2',
-            defaultIndex: 2
-          },
-          // {
-          //   values:unit,
-          //   className:'column3',
-          //   defaultIndex: 2
-          // },
-        ],
-        columIndx:[0,2,2],
-        time:100
+<script>
+export default {
+    name:"Picker",
+    props: {
+      symptomResult:{default:function() {
+        return {}
+        }},
+      defaultIndex:{default:0},
+      num:{default:0},
+      defaultVal:{default:""},
+      columns:{
+        default:function() {
+          return ['37.0°C', '37.1°C', '37.2°C','37.3°C', '37.4°C', '37.5°C', '37.6°C', '37.7°C', '37.8°C', '37.9°C', '38.0°C',
+            '38.1°C', '38.2°C', '38.3°C', '38.4°C', '38.5°C', '38.6C', '38.7°C', '38.8°C', '38.9°C',
+            '39.0°C', '39.1°C', '39.2°C', '39.3°C', '39.4°C', '39.5°C', '39.6°C', '39.7°C', '39.8°C',
+            '39.9°C', '40.0°C', '40.1°C', '40.2°C', '40.3°C', '40.4°C', '40.5°C', '40.6°C', '40.7°C',
+            '40.8°C', '40.9°C', '41.0°C', '41.1°C', '41.2°C', '41.3°C', '41.4°C', '41.5°C', '41.6°C',
+            '41.7°C', '41.8°C', '41.9°C', '42.0°C'];
+        }
+      },
+      columnsp:{
+        default:function() {
+          return ['37.0°C', '37.1°C', '37.2°C','37.3°C', '37.4°C', '37.5°C', '37.6°C', '37.7°C', '37.8°C', '37.9°C', '38.0°C',
+            '38.1°C', '38.2°C', '38.3°C', '38.4°C', '38.5°C', '38.6C', '38.7°C', '38.8°C', '38.9°C',
+            '39.0°C', '39.1°C', '39.2°C', '39.3°C', '39.4°C', '39.5°C', '39.6°C', '39.7°C', '39.8°C',
+            '39.9°C', '40.0°C', '40.1°C', '40.2°C', '40.3°C', '40.4°C', '40.5°C', '40.6°C', '40.7°C',
+            '40.8°C', '40.9°C', '41.0°C', '41.1°C', '41.2°C', '41.3°C', '41.4°C', '41.5°C', '41.6°C',
+            '41.7°C', '41.8°C', '41.9°C', '42.0°C'];
+        }
       }
+      },
+    data() {
+        return {
+            time: 100,
+            selectIndex: 0,
+            selectValue: '',
+            selectValuep: '',
+        }
     },
-    props:['show','picIndex'],
-    created(){//记录位置
-      this.columns[0].defaultIndex = this.columIndx[0] = this.picIndex[0] || 0;
-      this.columns[1].defaultIndex = this.columIndx[1] = this.picIndex[1] || 2;
-      // this.columns[2].defaultIndex = this.columIndx[2] = this.picIndex[2] || 2;
+    mounted(){
+      this.selectValue=this.defaultVal||this.columns[0];
+      this.selectValuep=this.defaultVal||this.columnsp[0];
     },
     methods: {
-      getVal() {
-        const val1 = $(".column1 ul .van-picker-column__item--selected")[0].innerText;
-        const val2 = $(".column2 ul .van-picker-column__item--selected")[0].innerText;
-        // const val3 = $(".column3 ul .van-picker-column__item--selected")[0].innerText;
-        // 如果选两个0,则提示
-        
-        const value = val1 + val2 ;
-        console.log(this.columIndx)
-        this.$emit("comfirn",value,this.columIndx)
-        this.columns[0].defaultIndex = this.columIndx[0] || 0;
-        this.columns[1].defaultIndex = this.columIndx[1] || 2;
-        // this.columns[2].defaultIndex = this.columIndx[2] || 2;
-      },
-      onCancel() {
-        this.$emit("cancel")
-      },
-      handlechange(picker, value, colum){//关掉提示
-        for(let i=0;i<2;i++){
-          if(i == 1){
-            let tmpVal = unit.lastIndexOf(value[i]);
-            this.columIndx[i] = tmpVal;
-          }else{
-            let tmpVal = num.lastIndexOf(value[i]);
-            this.columIndx[i] = tmpVal;
-          }
-        }
-      },
-      resetIndex(){//清除时复原默认index
-        this.columIndx=[0,2,2]
-        this.columns[0].defaultIndex = 0;
-        this.columns[1].defaultIndex = 2;
-        this.columns[2].defaultIndex = 6;
-      }
+        changeTemp(picker, value, index) {
+            this.selectIndex = index;
+            this.selectValuep = typeof(value)==="string"?value:value.join("");
+            this.selectValue = typeof(value)==="string"?this.columns[index]:value.join("");
+        },
+        onConfirm() {
+            let number = this.num;
+            const value = this.selectValue;
+            const valuep = this.selectValuep;
+            if(+this.symptomResult.flag===1){   //为时间控件
+              const orgChoose = this.$store.state.symptom.choose;
+              orgChoose[0].special = value;
+              orgChoose[0].specialP = valuep;
+              this.$store.commit('setChoose', { choose: orgChoose, type: 1 });
+            }
+            this.$emit('confirm','', {val:value,valp:valuep,flag:this.symptomResult.flag}, ++number)
+
+        },
+
     }
-  };
+}
 </script>
 <style lang="less" scoped>
-  @import '../less/base.less';
-  .toast-wrap{
-    .content{
-      padding-top: 7px;
-      width: 100%;
-      // height: 4.8rem;
-      height: 278px;
-      background: #fff;
-      position: fixed;
-      bottom:0;
-      left: 0;
-      box-sizing: border-box;
-      border-radius: .2rem .2rem 0 0;
-      z-index: 9999;
-      font-size: .3rem;
-      .confBtn{
-        height: 44px;
-        line-height: 44px;
-        text-align: center;
-        border-top: 1px solid #ebedf0;
-        margin-top: 7px;
-        position: relative;
-        .tip{
-          position: absolute;
-          top:-22px;
-          font-size: .24rem;
-          color: red;
-          line-height: 20px;
-          width:100%;
-          text-align: center;
-        }
-        div{
-          background: #colors[theme];
-          color: #fff;
-        }
-      }
-    }
-    .mask{
-      .mask;
-      z-index: 999;
-    }
-    /deep/.van-picker-column__item{
-      font-size: 14px;
-    }
-    /deep/.van-picker-column__item--selected {
-      color: #colors[theme];
-      font-size: 18px;
-    }
-  }
-</style>
+  @import "../less/base.less";
+.pickerBox{
+    position: fixed;
+    width: 100%;
+    height: 5.3rem;
+    border-radius: 10px 10px 0 0;
+    background: #fff;
+    overflow-y: hidden;
+    z-index: 99;
+    bottom: 0;
+    left: 0;
+    box-shadow: 0 0 30px -10px rgba(104, 124, 189, 0.25);
+    padding-top: 0.28rem;
+}
+.picker {
+    position: relative;
+    height: 180px;
+}
+/deep/.van-picker {
+    position: relative;
+    overflow-y: hidden;
+}
+.conBtn{
+    height: 44px;
+    line-height: 44px;
+    background: #5B99EB;
+    color: #fff;
+
+    font-size: 16px;
+    text-align: center;
+    position: absolute;
+    bottom: 0rem;
+    width: 100%;
+}
+.selected {
+    position: absolute;
+    width: 100%;
+    height: 36px;
+    background: #5B99EB;
+    top: 0;
+    opacity: .1;
+}
+.confirm{
+    color: #fff;
+}
+.sure{
+  position: absolute;
+  bottom: 0;
+}
+/deep/.van-picker-column__item {
+    text-align: center;
+    font-size: 14px;
+    /*background: #F3F4F6;*/
+}
+/deep/.van-picker-column__item--selected{
+    /*background: #F3F4F6;*/
+    font-size: .3rem;
+    color: #colors[theme];
+}
+/deep/van-picker__columns {
+    position: relative;
+    display: -webkit-box;
+    display: -webkit-flex;
+    display: flex;
+    cursor: grab;
+}
+/deep/.van-picker__mask {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 2;
+    width: 100%;
+    height: 100%;
+    background-image: -webkit-linear-gradient(top, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4)), -webkit-linear-gradient(bottom, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4));
+    background-image: linear-gradient(180deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4)), linear-gradient(0deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4));
+    background-repeat: no-repeat;
+    background-position: top, bottom;
+    -webkit-backface-visibility: hidden;
+    backface-visibility: hidden;
+    pointer-events: none;
+}
+/deep/.van-picker__frame{
+    position: absolute;
+    top: 50%;
+    left: 0;
+    z-index: 3;
+    width: 100%;
+    -webkit-transform: translateY(-50%);
+    transform: translateY(-50%);
+    pointer-events: none;
+}
+/deep/[class*='van-hairline']::after {
+    position: absolute;
+    background: #5B99EB;
+    opacity: .1;
+    box-sizing: border-box;
+    content: ' ';
+    pointer-events: none;
+    top: -50%;
+    right: -50%;
+    bottom: -50%;
+    left: -50%;
+    border: 0 solid #ebedf0;
+    -webkit-transform: scale(0.5);
+    transform: scale(0.5);
+}
+</style>

+ 326 - 0
src/common/PushSymptom.vue

@@ -0,0 +1,326 @@
+<template>
+  <portal to="notification-outlet">
+    <div class="select" @touchmove.prevent>
+      <div class="selected-tags">
+        <p class="title">已选伴随症状:</p>
+        <ul class="clearfix">
+          <li v-if="selecteds.length>0" v-for="it in selecteds">
+            <span>{{it.description||it.name}}</span>
+            <img @click="delSelected(it)" src="../images/closeimg.png" alt=""/>
+          </li>
+        </ul>
+      </div>
+      <ul class="tags clearfix">
+        <li
+          v-for="(item,idx) in symptoms"
+          :class="[{'liSelect':item.select,'big':item.explains}]"
+          :key="item.id"
+          @click="selectResult(item,idx)"
+        >
+          <span>{{item.description||item.name}}</span>
+          <img src="../images/icon_que.png" alt="解释说明" @click.stop="showExplain(item)" v-if="item.explains"/>
+        </li>
+      </ul>
+      <div :class="selecteds.length>0?'realSure sure':'sure'" @click="makeSuer">
+        确定 <span v-if="numPlus">({{numPlus}})</span>
+      </div>
+      <Tiptoast :show="showExp" :data="message" @close="closeTip"/>
+    </div>
+  </portal>
+</template>
+<script>
+  import api from '../utils/api.js';
+  import {mapState} from 'vuex';
+  import {delResymptoms} from '@utils/tools';
+  import Tiptoast from '../common/Tiptoast.vue';
+  export default {
+    props: ["num"],
+    data() {
+      return {
+        selecteds: [], //已选伴随症状
+        selectedsName:'',   //已选伴随症状名称
+        symptoms:[],      //症状
+        sure:false,
+        numPlus:0,     //已选答案个数
+        showExp:false,
+        message:{
+          title:'',
+          text:''
+        },
+      };
+    },
+    computed:{
+      ...mapState({
+        activeModule: state => state.activeModule,
+        chooseSymp: state => state.symptom.choose,//已选症状
+        checkText: state => state.symptom.text,//症状情况文字
+        config: state => state.sysConfig,
+        pathInfo: state => state.pathInfo,
+        extSyms: state => state.extPushSymptom
+      }),
+    },
+    mounted() {
+      //this.numPlus = this.num
+      //this.result = this.symptomResult.questionDetailList;
+      this.getPush(this.chooseSymp[0].name);
+    },
+    methods: {
+      getSympText() {//推送使用医生端信息
+        const text = this.$store.state.symptom.text;
+        let msg = "";
+        for (let i in text) {
+          if(text[i] && text[i].text){
+            msg += text[i].text;
+          }
+        }
+        return trimDots(msg);
+      },
+      getPush(symptoms) {//推理
+        const param = {
+          "age": this.pathInfo.patientAge,
+          "hosCode": this.pathInfo.hospitalCode,
+          "sex": this.pathInfo.sexType,
+          "symptom": symptoms //症状+选择的明细,string
+        };
+        api.getPush(param).then((res) => {
+          const result = res.data;
+          if (result.code == 0&&result.data) {
+            const syms = result.data.symptom;
+            if((!syms||syms.length===0)&&this.extSyms.length===0){
+              this.$emit('warning',"数据异常,请退出重新进入~");
+              return;
+            }
+            /*const none={
+              conceptId: 0,
+              name: "没有了",
+              tagName: "没有了",
+              libType: 1,
+              id: 0,
+              type: 1,
+              description: "",
+              exclusion:1,
+              hasExplain: 0,
+              explains: null,
+            };*/
+            //没有了与其他互斥
+            //const hasNone = symptoms.indexOf("没有了")!==-1;
+            const selecteds = this.selecteds;
+            const exts=this.getPushExts();
+            const newSyms = delResymptoms(exts,syms);
+            const newSymsCopy=JSON.parse(JSON.stringify(newSyms));
+            const newExt =selecteds.length>0?newSymsCopy.reduce((total,it)=>{
+                if(selecteds.findIndex((i)=>i.name===it.name)===-1){
+                  total.push(it);
+                }
+              return total;
+            },[]):newSyms;
+            //if(hasNone){
+              this.symptoms = [...newExt];
+            /*}else{
+              this.symptoms = [none,...newExt];
+            }*/
+            this.symptoms.length=this.symptoms.length>10?10:this.symptoms.length;
+          }else{
+            this.setErrorSymps();
+          }
+        }).catch((err)=>{
+         this.setErrorSymps();
+        });
+      },
+      setErrorSymps(){
+          const symps = this.getPushExts();
+          const selecteds = this.selecteds;
+          const newExt1 =selecteds.length>0?symps.reduce((total,it)=>{
+            if(selecteds.findIndex((i)=>i.name===it.name)===-1){
+              total.push(it);
+            }
+            return total;
+          },[]):symps;
+        this.symptoms = newExt1;
+        this.symptoms.length=this.symptoms.length>10?10:this.symptoms.length;
+      },
+      getPushExts(){
+        let syms = [];
+        const none={
+          conceptId: 0,
+          name: "没有了",
+          tagName: "没有了",
+          libType: 1,
+          id: 0,
+          type: 1,
+          description: "",
+          exclusion:1,
+          hasExplain: 0,
+          explains: null,
+        };
+        const exts=JSON.parse(JSON.stringify(this.extSyms));
+        if(exts.length===0){
+          return [none];
+        }
+        syms = [none,...exts];
+        return syms;
+      },
+      showExplain(it){
+        if(it.explains){
+          this.message.title = it.description || it.name;
+          this.message.text = it.explains;
+        }else{
+          this.message.title = "";
+          this.message.text = "暂无资料";
+        }
+        this.showExp = true
+      },
+      closeTip(){
+        this.showExp = false;
+        this.message.title = '';
+        this.message.text = '';
+      },
+      getSymptomLisCom(result){
+        let symp = (result&&result.data.symptom)||[];
+        let symped = JSON.parse(JSON.stringify(this.chooseSymp));//已选症状
+        let sympStic = JSON.parse(localStorage.getItem('staticSymp'))||[];//首次有无症状
+        let sympAll = sympStic.concat(symp);
+        var obj = {};
+        sympAll = sympAll.reduce(function(item, next) {
+          obj[next.name] ? '' : obj[next.name] = true && item.push(next);
+          return item;
+        }, []);
+        for(let i = 0;i < symped.length;i++){//去掉已选的已选症状
+          for(let j = 0;j < sympAll.length;j++){//去掉
+            if(sympAll[j].name == symped[i].name){
+              sympAll.splice(j,1)
+            }
+          }
+        }
+        this.symp = sympAll.slice(0,12);
+        this.$refs.showHide.style.height = 'auto'
+      },
+      makeSuer() {
+        if(!this.selecteds.length>0){return}
+        let number = this.num;
+        const sName=this.selectedsName.replace(/、+/g,"、").replace(/^、|、$/g,'');
+        const sNamep=this.selectedsName.replace(/、+/g,"、").replace(/^、|、$/g,'');
+        this.$emit("updataResult", '',{val:sName,valp:sNamep,idx:2},++number);
+        this.$store.commit("setChoose",{choose:[...this.chooseSymp,...this.selecteds]});
+      },
+      selectResult(item) {
+        if(this.selecteds.length>2&&item.name!=="没有了"){
+          this.$emit('warning','最多选择3个症状');
+          return;
+        }
+        const hasNone = this.selecteds.findIndex((it)=>{
+          return it.name==='没有了';
+        })!==-1;
+        if(hasNone){
+          this.selecteds.splice(0,1);
+          this.selectedsName = this.selectedsName.replace("没有了",'');
+          this.selectedsNamep = this.selectedsNamep.replace("没有了",'');
+        }else if(item.name==='没有了'){
+          this.selecteds=[];
+          this.selectedsName = '';
+          this.selectedsNamep ='';
+        }
+        const name = item.name;
+        const namep=item.description||item.name;
+        this.selectedsName = this.selectedsName?this.selectedsName+"、"+name:name;
+        this.selectedsNamep = this.selectedsNamep?this.selectedsNamep+"、"+namep:namep;
+        this.selecteds.push(item);
+        this.numPlus = this.selectedsName==="没有了"?0:this.selecteds.length;
+        this.getPush(this.chooseSymp[0].name+this.selectedsName);
+      },
+      delSelected(item){    //删除已选伴随症状
+        const selecteds = JSON.parse(JSON.stringify(this.selecteds));
+        const inx = selecteds.findIndex((it)=>{
+          return it.name === item.name;
+        });
+        if(inx!==-1){
+          this.selectedsName = this.selectedsName.replace(item.name,"");
+          this.selectedsNamep = this.selectedsNamep.replace(item.description||item.name,"");
+          selecteds.splice(inx,1);
+        }
+        this.selecteds = selecteds;
+        this.numPlus = this.selectedsName==="没有了"?0:this.selecteds.length;
+        this.getPush(this.chooseSymp[0].name+this.selectedsName);
+      }
+    },
+    components:{
+      Tiptoast,
+    }
+  };
+</script>
+<style lang="less" scoped>
+  @import "../less/base.less";
+  .select{
+    background-color: #fff;
+    padding: 0.28rem 0 0 0;
+    position: fixed;
+    width: 100%;
+    bottom: 0;
+    box-sizing: border-box;
+    box-shadow: 0 0 30px -10px rgba(104, 124, 189, 0.25);
+  }
+  .selected-tags{
+    margin-bottom: .8rem;
+    .title{
+      color: #aaa;
+      font-size: #font[dialog];
+      margin-bottom: .4rem;
+      text-indent: .28rem;
+    }
+    li{
+      position: relative;
+      display:inline-block;
+      span{
+        display: inline-block;
+        padding: 0.14rem 0.2rem;
+        background-color: #colors[btn];
+        border:1px #colors[btn] solid;
+        border-radius: 0.36rem;
+        font-size: #font[select];
+        margin: 0.15rem;
+        float: left;
+        color: #fff;
+      }
+      img{
+        width: .3rem;
+        height: .3rem;
+        position: absolute;
+        right: .05rem;
+        top: .1rem;
+      }
+    }
+  }
+  .tags {
+  li {
+    /*padding: 0.14rem 0.2rem;
+    border:1px #DFE0E4 solid;
+    border-radius: 0.36rem;*/
+    font-size: #font[select];
+    margin: 0.3rem 0 0.3rem 0.2rem;
+    float: left;
+    color: #666;
+    position: relative;
+    height: .38rem;
+    /*&.big{
+       margin: 0.15rem .65rem .15rem .15rem
+     }*/
+  span{
+    padding: 0.14rem 0.2rem;
+    border: 1px #DFE0E4 solid;
+    border-radius: 0.36rem;
+    margin-right: 0.06rem;
+  }
+  img{
+    width: .35rem;
+    vertical-align: middle;
+    /*position: absolute;
+    right: -0.55rem;*/
+  }
+  }
+  .liSelect {
+    color: #fff;
+    background-color: #colors[btn];
+    border-color:  #colors[btn];
+  }
+  }
+</style>

+ 180 - 140
src/common/Radio.vue

@@ -1,161 +1,201 @@
 <template>
-  <div v-if="item" class="radio-wrap bgques clearfix" :style="getStyle(detail,slide)">
-    <!-- <p v-for="(it,index) in datas.questionDetailList" :key="it.id" class="list" @click="handleClick(it,index,true)"> -->
-    <div v-for="(it,index) in datas.questionDetailList" :key="it.id" :class="['list',{'block':((it.description||it.name).indexOf('${'))!=-1}]">
-      <!-- <img :src="it.select==1?check:defaultPic"> -->
-      <span v-if="((it.description||it.name).indexOf('${'))==-1" :class="['radioCheck',{'check':it.select==1}]" @click="handleClick(it,index,true)">{{it.description||it.name}}</span>
-      <OptionInp v-else :item="it" @handleInp="inpVal($event,index)" @handleSelec="handleClick(it,index,false,true)"/>
+ <!-- <portal to="notification-outlet">-->
+  <div class="select" @touchmove.prevent>
+    <ul class="clearfix">
+      <li
+        v-for="(item,idx) in result"
+        :class="[{'liSelect':item.select,'noBorder':((item.description||item.name).indexOf('${'))!=-1}]"
+        :key="item.id"
+        @click="selectResult(item,idx)"
+      >
+        <span v-if="((item.description||item.name).indexOf('${'))==-1">{{item.description||item.name}}</span>
+        <OptionInp v-else :item="item" @handleInp="inpVal" :inx="idx" @handleSelect="selectResult(item,idx)"/>
+      </li>
+    </ul>
+    <div :class="sure?'realSure sure':'sure'" @click="makeSuer">
+      确定
     </div>
   </div>
+  <!--</portal>-->
 </template>
-<script type="text/javascript">
-import icon from '../images/radio-default.png';
-import checkIcon from '../images/radio-check.png';
-import {patt,concatVal} from '@utils/tools.js';
-import MultiLineInput from '../common/MultiLineInput.vue';
-import OptionInp from '../common/OptionInp.vue';
-  export default{
-    name:'Radio',
-    props:{
-      item:{
-        default:''
-      },
-      slide:{
-        default:false,
-        type:Boolean
-      },
-      detail:{
-        default:2,
-        type:Number||String
-      }
-    },
-    data(){
-      return{
-        defaultPic:icon,
-        check:checkIcon,
-        datas:{}
-      }
-    },
-    created(){
-      // this.datas = JSON.parse(JSON.stringify(this.item));
-      this.datas = this.item;
-    },
-    methods:{
-      getStyle(detail,slide){
-        if(detail == 1){
-          if(slide){
-            return {'display':'block','background-color': '#F9F9F9'}
-          }else{
-            return {'display':'none'}
+<script>
+  import OptionInp from '../common/OptionInp.vue';
+  import {concatVal,getExpStr} from '../utils/tools.js';
+  import api from '@utils/api.js';
+export default {
+  props: ["symptomResult","num"],
+  data() {
+    return {
+      result: [], //答案结果
+      connectResult: [], //id
+      contentResult: "", //name
+      rules: [], //规则所需数据value
+      sure:false,
+      numPlus:1
+    };
+  },
+  mounted() {
+    this.numPlus = this.num;
+    const list = this.symptomResult.questionDetailList;
+    this.result = list.length>0?list:this.symptomResult.questionMapping;
+  },
+  watch:{
+    result: {
+      handler(newArr) {
+        let num = 0;
+        for(let i = 0;i < newArr.length;i++){
+          if(!newArr[i].select){
+            ++num
           }
+        }
+        if(num == newArr.length){
+          this.sure = false
         }else{
-          return {'display':'block'}
+          this.sure = true
         }
       },
-      handleClick(it,index,flg,ipt){
-        if(flg){
-          document.activeElement.blur();      
+      immediate: true,
+      deep:true
+    }
+  },
+  methods: {
+    inpVal(val,index){//输入框失焦处理
+      // 输入框回读
+      let detailList = this.result;
+      let currItem = detailList[index];
+      currItem.value = val;
+    },
+    /*handleClick(it,index,flg,ipt){
+      if(flg){
+        document.activeElement.blur();
+        document.activeElement.scrollIntoViewIfNeeded(true);
+        setTimeout(()=>{
           document.activeElement.scrollIntoViewIfNeeded(true);
-          setTimeout(()=>{
-            document.activeElement.scrollIntoViewIfNeeded(true);
-          },300)
-        }
-        const list = this.datas;
-        let data = list.questionDetailList&&list.questionDetailList.slice(0); //数组深拷贝
-        if(ipt){//输入框单选,输入了内容才算选中,删除内容算取消
-          for(let i=0;i<data.length; i++){
-            if(i==index){
-              data[i].select=data[i].value?1:0;
-            }else{
-              data[i].select = 0
+        },300)
+      }
+    },*/
+    getExtQa(ids){
+      const userInfo = this.$store.state.pathInfo;
+      const param = {
+        age:userInfo.patientAge,
+        ids:ids,
+        sexType:userInfo.sexType
+      };
+      return new Promise((resolve,reject)=>{
+        api.getByIds(param).then((res)=>{
+          resolve(res);
+        });
+      })
+    },
+    async makeSuer() {
+      if(!this.sure){return}
+      let result = this.result;
+      let number = this.numPlus,tmpResult='',tmpResultp='';
+      for (let i = 0; i < result.length; i++) {
+          const textp=result[i].description||result[i].name;
+          const text=result[i].name;
+          const msg = getExpStr(text);
+          const msgp = getExpStr(textp);
+          if(result[i].select){
+            const subQ=result[i].subQuestion||'';
+            const subQs=subQ.split(",");
+            if(subQ){
+              await this.getExtQa(subQs).then((res)=>{
+                this.$emit("getExtQa",res.data.data,this.num,subQs.length);
+              });
             }
-          }
-        }else{
-          for(let i=0;i<data.length; i++){
-            if(i==index){
-              data[i].select = data[i].select==1?0:1;
+            if(result[i].name.indexOf("${")!==-1){
+              tmpResult=result[i].value?msg.prefix+(result[i].value||"")+msg.suffix:'';
+              tmpResultp=result[i].value?msgp.prefix+(result[i].value||"")+msgp.suffix:'';
             }else{
-              data[i].select = 0
+              tmpResult=text;
+              tmpResultp=textp;
             }
           }
         }
-        let temp = concatVal(data);
-        const newData = Object.assign({},this.datas,{questionDetailList:data,value:temp.value,valueP:temp.valueP})
-        this.$emit("updata",newData);
-      },
-      inpVal(val,index){//输入框失焦处理  
-        // 输入框回读
-        let detailList = this.datas.questionDetailList;
-        let currItem = detailList[index];
-        currItem.value = val; 
-        // 输入框失焦重新拼接父级的value
-        let temp = concatVal(detailList);
-        this.datas.value = temp.value;
-        this.datas.valueP = temp.valueP;
-        this.$emit("updata",this.datas);
-      },
-    },
-    watch:{
-      item:{
-        handler(newVal,oldVal){
-          this.datas = JSON.parse(JSON.stringify(newVal));
-        },
-        deep:true
+        if(+this.symptomResult.flag===1){   //为时间控件
+          const orgChoose = this.$store.state.symptom.choose;
+          orgChoose[0].special = tmpResult;
+          orgChoose[0].specialP = tmpResultp;
+          this.$store.commit('setChoose', { choose: orgChoose, type: 1 });
+        }
+        if(+this.symptomResult.flag===2){   //为诱因控件
+          const orgChoose = this.$store.state.symptom.choose;
+          orgChoose[0].reason = tmpResult;
+          orgChoose[0].reasonP = tmpResultp;
+          this.$store.commit('setChoose', { choose: orgChoose, type: 1 });
+        }
+        //this.contentResult = tmpResult;
+      if(!tmpResult){
+        this.$emit("warning","选中项输入框必填");
+        return;
       }
+      this.$emit("updataResultSingle", this.symptomResult, {val:tmpResult||"无",valp:tmpResultp||"无",flag:this.symptomResult.flag},++number);
     },
-    components:{
-      MultiLineInput,
-      OptionInp
+    selectResult(item,idx) {
+      const { select } = item;
+      let result = JSON.parse(JSON.stringify(this.result));
+      if (select) {//判断是否选中,选中的取消,关联id删除
+        for (let i = 0; i < result.length; i++) {
+          if(i == idx){
+            result[i].select = false
+          }
+        }
+      }else{
+        for (let i = 0; i < result.length; i++) {
+          if(i == idx){
+            result[i].select = true;
+          }else{
+            /*if(result[i].name.indexOf("${input")!==-1){     //被取消的输入框有内容则
+
+            }*/
+            result[i].select = false
+          }
+        }
+      }
+      this.result = result
     }
+  },
+  components:{
+    OptionInp
   }
+};
 </script>
 <style lang="less" scoped>
-@import '../less/base.less';
-  .radio-wrap{
-    .bgques;
-    img{
-      width:100%;
-    }
-    .block{
-      width:100%;
-    }
-    .list{
-      color: #colors[text];
-      margin:0 .05rem;
-      padding: .05rem;
-      display: inline-block;
-      white-space: nowrap;
-      // overflow-x: hidden;
-      float: left;
-      // -webkit-white-space: nowrap;
-      // -webkit-box-orient: vertical;
-      img{
-        width: .38rem;
-        vertical-align: middle;
-      }
-      >span{
-        white-space: normal;
-        vertical-align: middle;
-      }
-      .radioCheck {
-        display: inline-block;
-        line-height: .66rem;
-        // min-width: 2rem;
-        // text-align: center;
-        padding:0 .2rem;
-        box-sizing: border-box;
-        border-radius: .38rem;
-        border: 1px solid #dfe0e4;
-        background-color: #ffffff;
-      }
-      .check{
-        color: #fff;
-        background-color: #6678FF;
-        border: 1px solid #6678FF;
-      }
-      .iptCheck {
-        color: #colors[theme];
-      }
-    }
+  @import "../less/base.less";
+.select {
+  background-color: #fff;
+  padding: 0.28rem 0 0;
+  position: fixed;
+  width: 100%;
+  bottom: 0;
+  box-sizing: border-box;
+  box-shadow: 0 0 30px -10px rgba(104, 124, 189, 0.25);
+  li {
+    padding: 0.14rem 0.2rem;
+    border:1px #DFE0E4 solid;
+    border-radius: 0.36rem;
+    font-size: #font[select];
+    margin: 0.15rem;
+    float: left;
+    color: #colors[text];
+  }
+  .liSelect {
+    color: #fff;
+    background-color: #colors[btn];
+    border-color:  #colors[btn];
+  }
+  .noBorder{
+    border: none;
+    width: 100%;
+    padding: 0 0.2rem;
+    margin: 0 0.15rem;
+    &.liSelect{
+       background: none;
+        span{
+          color: #DFE0E4;
+        }
+     }
   }
-</style>
+}
+</style>

+ 213 - 0
src/common/Select.vue

@@ -0,0 +1,213 @@
+<template>
+  <portal to="notification-outlet">
+  <div class="select" @touchmove.prevent>
+    <ul class="clearfix">
+      <li
+        v-for="(item,idx) in result"
+        :class="[{'liSelect':item.select,'noBorder':((item.description||item.name).indexOf('${'))!=-1}]"
+        :key="item.id"
+        @click="selectResult(item,idx)"
+      >
+        <span v-if="((item.description||item.name).indexOf('${'))==-1">{{item.description||item.name}}</span>
+        <OptionInp v-else :item="item" @handleInp="inpVal" :inx="idx" @handleSelect="selectResult(item,idx)"/>
+      </li>
+    </ul>
+    <div :class="sure?'realSure sure':'sure'" @click="makeSuer">
+      确定 <span v-if="numPlus">({{numPlus}})</span>
+    </div>
+  </div>
+  </portal>
+</template>
+<script>
+  import OptionInp from '../common/OptionInp.vue';
+  import {concatVal,getExpStr} from '../utils/tools.js';
+  import api from '@utils/api.js';
+export default {
+  props: ["symptomResult","num"],
+  data() {
+    return {
+      result: [], //答案结果
+      connectResult: [], //id
+      contentResult: "", //name
+      rules: [], //规则所需数据value
+      sure:false,
+      numPlus:0     //已选答案个数
+    };
+  },
+  mounted() {
+    //this.numPlus = this.num
+    //console.log(this.symptomResult.questionDetailList)
+    this.result = this.symptomResult.questionDetailList;
+  },
+  watch:{
+    result: {
+      handler(newArr) {
+        let num = 0,sldNum=0;
+        for(let i = 0;i < newArr.length;i++){
+          if(!newArr[i].select){
+            ++num;
+          }else{
+            newArr[i].exclusion!=1&&sldNum++;
+          }
+        }
+        this.numPlus =sldNum;
+        if(num == newArr.length){
+          this.sure = false
+        }else{
+          this.sure = true
+        }
+      },
+      immediate: true,
+      deep:true
+    }
+  },
+  methods: {
+    inpVal(val,index){//输入框失焦处理
+      // 输入框回读
+      let detailList = this.result;
+      let currItem = detailList[index];
+      currItem.value = val;
+    },
+    /*handleClick(it,index,flg,ipt){
+      if(flg){
+        document.activeElement.blur();
+        document.activeElement.scrollIntoViewIfNeeded(true);
+        setTimeout(()=>{
+          document.activeElement.scrollIntoViewIfNeeded(true);
+        },300)
+      }
+    },*/
+    getExtQa(ids){
+      const userInfo = this.$store.state.pathInfo;
+      const param = {
+        age:userInfo.patientAge,
+        ids:ids,
+        sexType:userInfo.sexType
+      };
+      return new Promise((resolve,reject)=>{
+        api.getByIds(param).then((res)=>{
+          resolve(res);
+        });
+      })
+    },
+    async makeSuer() {
+      if(!this.sure){return}
+      let result = this.result;
+      // if(this.numPlus == 1){
+        let tmpResult=[],tmpResultp=[],subQas='';
+        for (let i = 0; i < result.length; i++) {
+          const text=result[i].name;
+          const textp=result[i].description||result[i].name;
+          const msg = getExpStr(text);
+          const msgp = getExpStr(textp);
+          if(result[i].select){
+            subQas = subQas+","+result[i].subQuestion;
+            if(result[i].name.indexOf("${")!==-1){
+              if(!result[i].value){
+                this.$emit("warning","选中项输入框必填");
+                return;
+              }
+              tmpResult.push(msg.prefix+(result[i].value||"")+msg.suffix);
+              tmpResultp.push(msgp.prefix+(result[i].value||"")+msgp.suffix);
+            }else {
+              //tmpIds=tmpIds.concat(result[i].connectId)
+              tmpResult.push(text);
+              tmpResultp.push(textp);
+            }
+          }
+        }
+        subQas=subQas.replace(/^,|,$/g,'').replace(/,+/g,',');
+        const subQs=subQas.split(",");
+        if(subQas){
+          await this.getExtQa(subQs).then((res)=>{
+            this.$emit("getExtQa",res.data.data,this.num,subQs.length);
+          });
+        }
+        //tmpIds=tmpIds.concat(staticArr)
+        //this.connectResult = tmpIds
+        //this.contentResult = tmpResult.join('、')
+      // }else{
+
+      // }
+      if(+this.symptomResult.flag===2){   //为诱因控件
+        const orgChoose = this.$store.state.symptom.choose;
+        orgChoose[0].reason = tmpResult;
+        orgChoose[0].reasonP = tmpResultp;
+        this.$store.commit('setChoose', { choose: orgChoose, type: 1 });
+      }
+      let number = this.num;
+      this.$emit("updataResult", this.symptomResult,  {val:tmpResult.join('、'),valp:tmpResultp.join('、')},++number);
+    },
+    selectResult(item,idx) {
+      const { exclusion, select } = item;
+      let result = JSON.parse(JSON.stringify(this.result));
+      if (select) {//判断是否选中,选中的取消,关联id删除,未选中判断是否互斥
+        for (let i = 0; i < result.length; i++) {
+          if(i == idx){
+            result[i].select = false
+          }
+        }
+      }else{
+        if(+exclusion === 1){
+          for (let i = 0; i < result.length; i++) {
+              if(i == idx){
+                result[i].select = true
+              }else{
+                result[i].select = false
+              }
+          }
+        }else{
+          for (let i = 0; i < result.length; i++) {
+            if(result[i].select&&+result[i].exclusion === 1){
+              result[i].select=false
+            }else{
+              if(i == idx){
+                result[i].select = true
+              }
+            }
+          }
+        }
+      }
+      this.result = result
+    }
+  },
+  components:{
+    OptionInp
+  }
+};
+</script>
+<style lang="less" scoped>
+  @import "../less/base.less";
+.select {
+  background-color: #fff;
+  padding: 0.28rem 0 0 0;
+  position: fixed;
+  width: 100%;
+  bottom: 0;
+  box-sizing: border-box;
+  box-shadow: 0 0 30px -10px rgba(104, 124, 189, 0.25);
+  li {
+    padding: 0.14rem 0.2rem;
+    border:1px #DFE0E4 solid;
+    border-radius: 0.36rem;
+    font-size: #font[select];
+    margin: 0.15rem;
+    float: left;
+    color: #colors[text];
+  }
+  .liSelect {
+    color: #fff;
+    background-color: #colors[btn];
+    border-color:  #colors[btn];
+  }
+  .noBorder{
+    border: none;
+    width: 100%;
+    padding: 0 0.2rem;
+    margin: 0 0.15rem;
+    &.liSelect{
+       background: none;
+    }
+  }
+}
+</style>

+ 79 - 0
src/common/TipWarning.vue

@@ -0,0 +1,79 @@
+<template>
+  <div class="tip">{{text}}</div>
+</template>
+<script>
+  export default {
+    props:['timer','text'],
+    data(){
+      return {
+        show:true
+      }
+    },
+    mounted(){
+      this.close();
+    },
+    methods:{
+      close(){
+        const that = this;
+        const timer=setTimeout(()=>{
+          //that.show=false;
+          that.$emit("close");
+          clearTimeout(timer);
+        },3900);
+      }
+    }
+  }
+</script>
+<style lang="less" scoped>
+
+  .tip {
+    max-width: 80%;
+    font-size: .28rem;
+    padding: .2rem;
+    border-radius: .1rem;
+    background-color:rgba(0,0,0,0.7);
+    position: fixed;
+    top: 40%;
+    left: 50%;
+    z-index: 9999;
+    animation:toHidden 4s ease;
+    -moz-animation: toHidden 4s ease;	/* Firefox */
+    -webkit-animation: toHidden 4s ease;	/* Safari 和 Chrome */
+    -o-animation: toHidden 4s ease;
+    transform: translateX(-50%);
+    color: #fff;
+  }
+
+  @keyframes toHidden{
+    from{
+      opacity: 1;
+    }
+    to{
+      opacity: 0;
+    }
+  }
+  @-moz-keyframes toHidden{
+    from{
+      opacity: 1;
+    }
+    to{
+      opacity: 0;
+    }
+  }
+  @-webkit-keyframes toHidden{
+    from{
+      opacity: 1;
+    }
+    to{
+      opacity: 0;
+    }
+  }
+  @-o-keyframes toHidden{
+    from{
+      opacity: 1;
+    }
+    to{
+      opacity: 0;
+    }
+  }
+</style>

+ 8 - 8
src/common/Tiptoast.vue

@@ -1,5 +1,5 @@
 <template>
-    <portal to="notification-outlet">
+    <!--<portal to="notification-outlet">-->
       <div class="toast-wrap" v-if="show">
             <div class="content">
               <p class="tit" v-show="data.title">{{data.title}}</p>
@@ -8,10 +8,10 @@
               </div>
                 <img src="../images/icon_close@2x.png"  class="close" @click="handleClose">
             </div>
-            
+
             <div class="mask" @click="handleClose"></div>
       </div>
-    </portal>
+    <!--</portal>-->
 </template>
 <script type="text/javascript">
 /**
@@ -59,21 +59,21 @@
       top:50%;
       left: 50%;
       transform: translate(-50%,-50%);
-      padding: .5rem .8rem .8rem;
+      padding: .6rem;
       box-sizing: border-box;
       border-radius: .20rem;
       z-index: 1000;
       .tit{
         font-family:PingFangSC;
         color:#333333;
-        font-size: .32rem;
+        font-size: #font[title];
         text-align: center;
         font-weight: 700;
       }
       .text{
         color:#colors[quest];
-        padding-top: .3rem;
-        font-size: .3rem;
+        padding-top: .4rem;
+        font-size: #font[select];
       }
       .close{
         width:.72rem;
@@ -88,4 +88,4 @@
       z-index: 999;
     }
   }
-</style>
+</style>

+ 4 - 4
src/common/Toast.vue

@@ -50,7 +50,7 @@ import $ from 'jquery';
       top:50%;
       left: 50%;
       transform: translate(-50%,-50%);
-      padding: 0.6rem 0.5rem 1.5rem .5rem;
+      padding: 0.6rem 0.6rem 1.5rem;
       box-sizing: border-box;
       border-radius: .2rem;
       z-index: 1000;
@@ -73,8 +73,8 @@ import $ from 'jquery';
         bottom: 0;
         left: 0;
         width: 6.3rem;
-        height: .9rem;
-        line-height: .9rem;
+        height: .88rem;
+        line-height: .88rem;
         border-top: 1px solid #colors[line];
         // font-weight: bold;
         span{
@@ -98,4 +98,4 @@ import $ from 'jquery';
       z-index: 999;
     }
   }
-</style>
+</style>

+ 102 - 21
src/common/UploadImg.vue

@@ -1,7 +1,7 @@
 <template>
-  <div class="img-wrap bgques">
+  <div class="img-wrap" @touchmove.prevent>
     <div class="box">
-      
+
       <ul class="upload-imgs">
         <li v-for='(value, key) in imgs' class="imgLis">
           <p class="imgbox">
@@ -32,12 +32,17 @@
           <p>点击上传</p>
         </li>
       </ul>
+      <div :class="imgLen>0?'realSure sure':'sure'" @click="saveAllImage">
+        确认上传
+      </div>
     </div>
   </div>
 </template>
 <script type="text/javascript">
-import {isIos,isWX,isQQ} from '@utils/tools';
+import {isIos,isWX,isQQ} from '../utils/tools';
+import api from '../utils/api.js';
 import $ from 'jquery';
+import {mapState} from 'vuex';
 export default {
   name: 'UploadImg',
   data() {
@@ -45,17 +50,23 @@ export default {
       mag: "上传图片",
       imgs: {},
       imgLen: 0,
-      flag:true //图片处理完成后才可以再次点击上传
+      flag:true, //图片处理完成后才可以再次点击上传
+      sure:false,
     }
   },
-  props: ['item', 'moduleType', 'imgList'],
+  props: ['item', 'moduleType', 'imgList','num'],
+  computed:{
+    ...mapState({
+      imgUpList: state => state.diagnose.imgFile,
+    }),
+  },
   mounted() {
     this.imgs = this.imgList; //回读
     this.imgLen = Object.keys(this.imgList).length;
     this.$previewRefresh();//预览刷新
     /*if(isIos()){
       $('.upload').removeAttr("capture")
-    }else if(!isWX()){ 
+    }else if(!isWX()){
     // 微信端添加这个属性直接调拍照
     //安卓手机且非微信端添加相机属性,否则QQ浏览器打不开相机
       $('.upload').attr("capture","camera")
@@ -67,11 +78,57 @@ export default {
     }
   },
   methods: {
-    handleUpload() {
-      const inp = this.$refs.inp;
-      if(this.flag){
-        inp.click();
-      } 
+    async saveAllImage() {
+      let n = this.num;
+      let uploadFail = false;
+      const data = await this.uploadImgs(this.$store.state.diagnose.imgFile).then((res)=>{
+        let data = res.data;
+        if (data.code == 0) {//图片提交成功再保存数据
+          this.saveImgs(data);
+        } else {//提交失败提示
+          this.$emit('warning',data.msg);
+          uploadFail=true;
+        }
+      });
+      if(uploadFail){   //上传失败,暂停
+        return;
+      }
+      if(Object.keys(this.imgs).length===0){
+        return;
+      }
+      this.$emit("updataResult",this.item,{val:this.imgs,valp:this.imgs},++n);
+    },
+    uploadImgs() {
+      const imgList = this.imgUpList;
+     return new Promise((resolve,reject)=>{
+        let formData = new FormData();
+        if (imgList.length > 0) {//有图片先上传图片
+          for (let i = 0; i < imgList.length; i++) {
+            let pageFile = imgList[i].file;
+            formData.append('upfiles', imgList[i].file);
+            formData.append('type', imgList[i].type);
+          }
+          api.uploadImageThums(formData).then((res) => {//获取图片
+              resolve(res)
+          }).catch((err)=>{
+            this.$emit('warning','上传失败,请稍后重试!');
+          });
+        }
+      });
+    },
+    saveImgs(data){
+      const imgList = this.imgUpList;
+      let reportList = [];
+      let result = data.data;
+      for(let i = 0;i < result.length;i++){
+        let obg = {}
+        obg.originalImage = result[i].url+'?width='+imgList[i].imgWidth+'&height='+imgList[i].imgHeight
+        obg.originalName = result[i].original
+        obg.orderNum = i+1
+        obg.type = result[i].type
+        reportList.push(obg)
+      }
+      this.$store.commit("setUploadImgs",reportList);
     },
     delImg(key) {
       let obj = this.imgs;
@@ -113,7 +170,7 @@ export default {
           that.imgLen++;
           // 将图片信息存到store
           that.$store.commit('setImgFile', { type: that.moduleType, pId: that.item.id, key: key, file: uploadFile,imgWidth:imgWidth, imgHeight:imgHeight})
-          that.$store.commit('setImgSrc', { key: key, src: uploadSrc, type: that.moduleType })
+          that.$store.commit('setImgSrc', { key: key, src: uploadSrc, type: that.moduleType });
           that.$previewRefresh(); //异步获取的图片需要刷新下
         }
         // that.$refs.inp.value = '';
@@ -190,12 +247,20 @@ export default {
 }
 </script>
 <style lang="less" scoped>
+  @import "../less/base.less";
 .img-wrap {
   font-size: 0.3rem;
+  position:fixed;
+  bottom:0;
+  background:#fff;
+  width:100%;
+  box-shadow: 0 0 30px -10px rgba(104, 124, 189, 0.25);
+  padding-top: .4rem;
   .upload-imgs {
-    margin-bottom: 0.2rem;
+    margin:0 1rem;
+    height: 3.5rem;
     .upload{
-      width: 1.9rem;
+      width: 1.5rem;
       height: 100%;
       position: absolute;
       left: 0;
@@ -204,6 +269,8 @@ export default {
     }
     .uploadBox {
       // border: 1px solid #dfe0e4;
+      width: 1.5rem;
+      height: 1.5rem;
       box-sizing: border-box;
       text-align: center;
       background: url('../images/addimg.png') no-repeat;
@@ -222,21 +289,21 @@ export default {
       }
     }
     li {
-      width: 1.9rem;
-      height: 1.9rem;
+      width: 1.5rem;
+      height: 1.5rem;
       display: inline-block;
       position: relative;
       vertical-align: top;
       border-radius: 0.08rem;
-      margin: 0 0 0.3rem 0.3rem;
+      margin: 0 0 0.3rem 0.4rem;
       .close {
-        width: 0.54rem;
-        height: 0.54rem;
+        width: 0.3rem;
+        height: 0.3rem;
         background: url(../images/closeimg.png) no-repeat;
         background-size: cover;
         position: absolute;
-        top: -0.27rem;
-        right: -0.27rem;
+        top: -0.17rem;
+        right: -0.17rem;
         z-index: 3;
       }
     }
@@ -262,4 +329,18 @@ export default {
     }
   }
 }
+  .sure {
+    width: 100%;
+    height: 0.88rem;
+    font-size: .28rem;
+    background-color: #colors[btn];
+    line-height: 0.88rem;
+    margin-top: 0.8rem;
+    text-align: center;
+    color: #fff;
+    opacity: 0.5;
+  &.realSure {
+     opacity: 1;
+   }
+  }
 </style>

+ 197 - 0
src/common/UsualSymptom.vue

@@ -0,0 +1,197 @@
+<template>
+  <portal to="notification-usual">
+  <div class="usual-symptom" @touchmove.prevent>
+    <p class="title-bar">
+      <!--<a href="javascript:void(0)">--><img @click="back" src="../images/back.png" alt="返回"/><!--</a>-->
+      <span>您哪里不舒服?</span>
+    </p>
+    <ul class="radio-item clearfix">
+      <li
+        v-for="(item,idx) in symptoms"
+        :class="[{'liSelect':item.select,'big':item.explains}]"
+        :key="idx"
+        @click="selectResult(item,idx)"
+      >
+        <span>{{item.description||item.name}}</span>
+        <img src="../images/icon_que.png" alt="解释说明" @click.stop="showExplain(item)" v-if="item.explains"/>
+      </li>
+    </ul>
+
+    <div class="searchWrap" @click="search(true)">
+        <img class="searchImg" src="../images/search.png" alt="">
+        <span class="placeholder">找不到?也可点击搜索症状</span>
+    </div>
+    <Search
+      v-if="this.$store.state.searchShow"
+      @search="search"
+      @showDetil="showDetil"
+    ></Search>
+
+    <Tiptoast :show="showExp" :data="message" @close="closeTip"/>
+    <!-- <ConfirmBox :show="showConfirm" @confirmDialog="confirmDialog" @cancelDialog = "cancelDialog"></ConfirmBox> -->
+  </div>
+  </portal>
+</template>
+<script>
+  import Radio from './Radio';
+  import Search from '../components/Search.vue';
+  // import ConfirmBox from '../common/ConfirmBox'
+  import Tiptoast from '../common/Tiptoast.vue';
+  export default {
+    name:'UsualSymptom',
+    props:[],
+    data(){
+      const data = this.$store.state.usualSymptom;
+      return {
+        symptoms:this.formatData(data),
+        portaled:false,   //是否将radio渲染到最外层
+        showConfirm:false,
+        len:10,     //显示常用症状个数
+        showExp:false,
+        message:{
+          title:'',
+          text:''
+        },
+      }
+    },
+    methods:{
+      back(){
+        this.$router.go(-1);
+      },
+      showExplain(it){
+        if(it.explains){
+            this.message.title = it.description || it.name;
+            this.message.text = it.explains;
+        }else{
+            this.message.title = "";
+            this.message.text = "暂无资料";
+        }
+        this.showExp = true
+      },
+      closeTip(){
+        this.showExp = false;
+        this.message.title = '';
+        this.message.text = '';
+      },
+      formatData(data){
+        data.length=data.length>10?10:data.length;
+        return data.map((i)=>{
+          return Object.assign({},i,{
+            name:i.name,
+            value:i.questionId,
+            special:'',
+            connectId:[]
+          })
+        });
+      },
+      selectResult(item,idx){
+        this.$emit('selectUsual',item,idx);
+        this.$store.commit('setSearchShow', false);
+        this.$store.commit('setText', { type: 1, text: '患者出现'+item.name,textP: '患者出现'+(item.description||item.name),flag:true,arrFlag:true, pId: item.questionId,idx:1 });
+
+        let obj = {
+              "labelName": item.tagName||item.name,//标签名称
+              "operationNum": 1,//次数
+              "operationType": 1,//1常见2搜索
+            }
+        this.$store.commit('addBuriedSome', obj);
+      },
+      confirmDialog(){
+
+      },
+      cancelDialog(){
+
+      },
+      search(flag){
+        this.$store.commit('setSearchShow', flag);
+      },
+      showDetil(item,flg) {//搜索点开的详情
+        this.$emit('selectUsual',item,flg);
+        this.$store.commit('setSearchShow', false);
+      },
+    },
+    components:{
+      Radio,
+      // ConfirmBox,
+      Search,
+      Tiptoast
+    }
+  }
+</script>
+<style lang="less" scoped>
+  @import "../less/base.less";
+  .usual-symptom{
+    position: fixed;
+    bottom: 0;
+    background: #fff;
+    padding: .2rem .1rem;
+    box-shadow: 0 0 30px -10px rgba(104, 124, 189, 0.25);
+  }
+  .title-bar{
+    font-size: #font[title];
+    overflow: hidden;
+    img{
+      width: .16rem;
+      padding: .2rem .4rem .4rem .2rem;
+      float: left;
+    }
+    span {
+      padding-top: .1rem;
+      float: left;
+    }
+  }
+  .radio-item{
+    li {
+      /*padding: 0.14rem 0.2rem;
+      border:1px #DFE0E4 solid;
+      border-radius: 0.36rem;*/
+      font-size: #font[select];
+      margin: 0.3rem 0.1rem;
+      float: left;
+      color: #colors[text];
+      position: relative;
+      height: .38rem;
+      /*&.big{
+         margin: 0.15rem .65rem .15rem .15rem;
+       }*/
+       span{
+         padding: 0.14rem 0.2rem;
+         border: 1px #DFE0E4 solid;
+         border-radius: 0.36rem;
+         margin-right: 0.06rem;
+       }
+      img{
+        width: .35rem;
+        vertical-align: middle;
+        /*position: absolute;
+        right: -0.55rem;*/
+      }
+    }
+    .liSelect {
+      color: #fff;
+      background-color: #colors[btn];
+      border-color:  #colors[btn];
+    }
+  }
+  .searchWrap {
+    margin:.8rem .2rem 0 .2rem;
+    height: .68rem;
+    line-height: .25rem;
+    box-sizing: border-box;
+    position: relative;
+    background: #F5F5F5;
+    border-radius: .32rem;
+    padding-left:.7rem;
+    color: #AAAAAA;
+    .placeholder{
+      font-size: #font[placeholder];
+    }
+    .searchImg {
+      width: 0.44rem;
+      height: 0.44rem;
+      position: absolute;
+      left: .2rem;
+      top: .1rem;
+    }
+  }
+</style>

+ 1 - 0
src/components/Department.vue

@@ -228,6 +228,7 @@
                 p {
                     position: relative;
                     color: #fff;
+                    font-size: #font[title];
                     img {
                         position: absolute;
                         right: 0;

+ 592 - 0
src/components/MainPage.vue

@@ -0,0 +1,592 @@
+<template>
+  <div class="page">
+    <Head :activeTab='activeTab' :allMoudles='allMoudles' :progress='progress'/>
+    <!-- <div class="progress-bar">
+      <div class="title">
+        <span :class="{'active':activeTab==i.type}" :style="{width:(100/allMoudles.length)+'%'}" v-for="i in allMoudles">{{i.name}}</span>
+      </div>
+      <div class="progress">
+        <p :style="{width:progress}"></p>
+      </div>
+    </div> -->
+    <div class="wrapper">
+      <div class="scrollPart" :style="{'paddingBottom':pdbm}">
+        <!--<div class="right clearfix">
+          <img src="../assets/patient.png" alt="" class="fr">
+          <div class="content fr">
+            <p>医生您好!我想咨询新型冠状病毒。(个人信息:{{userInfo.patientName}}{{userInfo.patientSex?','+userInfo.patientSex:''}}{{userInfo.patientAge?','+userInfo.patientAge+'岁':''}})</p>
+          </div>
+        </div>-->
+        <div class="left clearfix">
+          <img src="../images/doctor.png" alt="" class="fl">
+          <div class="content fl">
+            <p>欢迎来到{{userInfo.hospitalName}}!候诊期间请先填写自己的实际症状,信息会马上传送到您的预约医生,便于您实现快速就诊。</p>
+          </div>
+        </div>
+        <!--<div class="left clearfix" @click="selectToggle(2,disData.symptom.result,true)">
+          <img src="../assets/doctor.png" alt="" class="fl">
+          <div class="content fl">
+            <p>您哪里不舒服?</p>
+          </div>
+        </div>-->
+        <UsualSymptom v-if="showUsual" @selectUsual="selectUsual"></UsualSymptom>
+        <div class="right clearfix" v-if="selectedSymptom.name">
+          <img src="../images/patient.png" alt="" class="fr">
+          <div class="content fr">
+            <p>{{selectedSymptom.description||selectedSymptom.name}}</p>
+          </div>
+          <span v-if="!canceledSym&&activeNum==0&&cancelNum===-1" class="edit" @click="cancelSymptom">修改</span>
+        </div>
+        <div v-for="(item,idx) in symptomQasList" :key="'0'+idx+item.id" v-if="activeTab">
+          <Dialog :idx="idx" v-if="item.show" :item="item" @cancel="cancelSelected" :num="activeNum" :cancelNum="cancelNum" :extNum ="[]"/>
+        </div>
+        <div v-for="(item,idx) in diagnoseQasList" :key="'1'+idx+item.id" v-if="activeTab==moduleKeys[1]||activeTab==moduleKeys[2]||activeTab==moduleKeys[3]">
+          <Dialog :idx="idx" v-if="item.show" :item="item" @cancel="cancelSelected" :num="activeNum" :extNum ="[symptomQasList.length]" :cancelNum="cancelNum"/>
+        </div>
+        <div v-for="(item,idx) in othersQasList" :key="'2'+idx+item.id" v-if="activeTab==moduleKeys[2]||activeTab==moduleKeys[3]">
+          <Dialog :idx="idx" v-if="item.show" :item="item" @cancel="cancelSelected" :num="activeNum" :extNum ="[symptomQasList.length,diagnoseQasList.length]" :cancelNum="cancelNum"/>
+        </div>
+        <div v-for="(item,idx) in addContentQasList" :key="'3'+idx+item.id" v-if="activeTab==moduleKeys[3]">
+          <Dialog :idx="idx" v-if="item.show" :item="item" @cancel="cancelSelected" :num="activeNum" :extNum ="[symptomQasList.length,diagnoseQasList.length,othersQasList.length]" :cancelNum="cancelNum"/>
+        </div>
+      </div>
+    </div>
+    <MultSelect @updataResult="updataResultSingle" :num="num" :symptomResult="symptomResult" v-if="type==3"></MultSelect>
+    <Select @updataResult="updataResultSingle" :num="num" @warning="showWarn" @getExtQa="addExtQa" :symptomResult="symptomResult" v-if="type == 2"></Select>
+    <Radio @updataResultSingle="updataResultSingle" @warning="showWarn" @getExtQa="addExtQa" :num="num" :symptomResult="symptomResult" v-if="type == 1"></Radio>
+    <!--普通单列拨盘-->
+    <Picker v-if="type==10" @confirm="updataResultSingle" :columns="getColumns().arr" :columnsp="getColumns().arrp" :num="num" :defaultIndex = "defaultIndex"></Picker>
+    <!--时间拨盘,拨盘内容写死-->
+    <Picker v-if="type == 9" :symptomResult="symptomResult" :columns="timeColumns" :columnsp="timeColumns" :defaultVal="pickDVal" @confirm="updataResultSingle" :num="num" :defaultIndex = "defaultIndex"></Picker>
+    <PushSymptom v-if="type == 99" @updataResult="updataResultSingle" :num="num" @warning="showWarn"></PushSymptom>
+    <!-- 上传图片 -->
+    <UploadImg v-if="type==4"
+               :num="num"
+               :item="symptomResult"
+               :moduleType="symptomResult.type"
+               @warning="showWarn"
+               @updataResult="updataResultSingle"
+               :imgList="imgs"/>
+    <!-- 输入框 -->
+    <!--<Input v-if="type==7"
+           :num="num"
+           :item="symptomResult"
+           :key="symptomResult.id"
+           @updata="updataResultSingle"/>-->
+    <!-- 文本域 -->
+    <ComTextArea v-if="type == 5"
+                 :num="num"
+                 :item="symptomResult"
+                 width="92%"
+                 @updata="updataResultSingle"/>
+    <div class="submit" v-if="showPreview">
+      <a href="javascript:void(0)" @click="previewRes">提交并预览</a>
+    </div>
+    <!--<div v-if="wrong" class="tip">{{waring}}</div>-->
+    <TipWarning v-if="wrong" :text="waring" @close="closeTip"/>
+  </div>
+</template>
+<script>
+import BScroll from 'better-scroll';
+import Radio from '../common/Radio';
+import Select from '../common/Select';
+import Dialog from '../common/Dialog';
+import Picker from '../common/Picker';
+import Label from '../common/Label.vue';
+import ComTextArea from '../common/ComTextArea.vue';
+/*import Input from '../common/Input.vue';*/
+import PickTime from '../common/PickTime.vue';
+import UploadImg from '../common/UploadImg.vue';
+import PushSymptom from '../common/PushSymptom.vue';
+import ConfirmBox from '../common/ConfirmBox'
+import UsualSymptom from '../common/UsualSymptom';
+import MultSelect from '../common/MultSelect.vue';
+import TipWarning from '../common/TipWarning.vue';
+import Head from '../common/Head.vue';
+import api from "../utils/api.js";
+import {mapState} from 'vuex';
+import {moduleCP,moduleConfig,getValuesArr,getNSum} from '@utils/tools'
+
+export default {
+  name:'MainPage',
+  data(){
+    return {
+      noAllowed:false,    //未登录
+      num:-1,//题目计数
+      pickDVal:'1天',    //时间控件默认值
+      allMoudles:[],
+      showUsual:false,    //常用症状显示
+      timeColumns:[],   //固定2列时间滑块数据
+      activeTab:1,      //当前模块
+      activeNum:0,    //当前问题的index,整体顺序
+      scroll:null,
+      canceledSym:false,    //是否已修改过主症状
+      canceledQa:-1,    //在对应模块的排行
+      cancelNum:-1,     //整体排行
+      cancelTab:-1,
+      deledUpload:[],  //被删除的上传控件数据(记录用于修改时恢复)
+      type :-1,       //当前显示的控件类型
+      showPreview:false,//显示预览按钮
+      selectedSymptom:{},
+      symptomResult:'',//症状选择
+      connectResult:[],//关联问题的id
+      contentResult:{},//选中的结果val医生端显示,valp患者端显示
+      symptomQasList:[],//症状详情所有的问题
+      diagnoseQasList:[], //诊疗详情所有问题
+      othersQasList:[],//其他情况所有问题
+      addContentQasList:[],
+      moduleMap:{
+        1:'symptom',
+        51:'diagnose',
+        3:'others',
+        52:'addContent'
+      },
+      defaultIndex: 0, //温度默认值
+      order:0,
+      userInfo: {}, //用户信息
+      pdbm:'8.5rem',
+      waring:'',        //错误提示语
+      wrong:false,      //是否显示错误toast
+      showConfirm: false,
+      time:1000,
+    }
+  },
+  created() {
+    //const userInfo= JSON.parse(localStorage.getItem("userInfo"))
+    const userInfo = this.$store.state.pathInfo;
+    if(!userInfo.hospitalCode){    //用户数据丢失,刷新或本页面分享时,跳回登录页
+      const code = JSON.parse(localStorage.getItem("infoParam"))||JSON.parse(localStorage.getItem("loginParam"));
+      this.noAllowed=true;
+      this.$router.push({
+        path:'/?hospitalCode='+code.hospitalCode
+      });
+      return;
+    }
+    this.userInfo = userInfo;
+    let tmpModule = moduleConfig(this.config,this.tmpAllMoudles);
+    this.allMoudles = tmpModule.data;
+    this.getTimeColumns();
+    this.updata()
+  },
+  mounted(){
+    if(this.noAllowed)return;
+    this.$nextTick(()=>{
+      let bs = new BScroll('.wrapper', {
+        probeType: 3,
+        click:true
+      });
+      this.scroll = bs
+    })
+    // this.tmpSymptom = JSON.parse(JSON.stringify(data))
+    //this.symptomResult = data.symptom.result;
+  },
+  computed:{
+    ...mapState({
+      imgs: state => state.diagnose.imgSrc,
+      tmpAllMoudles: state => state.allMoudles,
+      config: state => state.sysConfig,
+    }),
+    moduleKeys(){
+      return this.allMoudles.map((it)=>{
+        return it.type;
+      });
+    },
+    progress(){
+      if(this.num===-1){
+        return '0.1px';
+      }
+      const moduleName = this.moduleMap[this.activeTab]+'QasList';
+      const precent = (this.num+1)/this[moduleName].length;
+      return precent*100+"%";
+    }
+  },
+  watch:{
+    num:function(){
+      let n=0;
+      let numArr=this.moduleKeys.map((i,index)=>{
+        if(this.activeTab!==-1&&i===this.activeTab){
+          n=index;
+        }
+        return this[this.moduleMap[i]+'QasList'].length;
+      });
+      let numArrCopy=[...numArr];
+      numArrCopy.length=this.cancelTab!==-1?this.cancelTab:0;
+      numArr.length=n;
+      this.cancelNum = getNSum(numArrCopy)+this.canceledQa;
+      this.activeNum = getNSum(numArr)+this.num;
+    }
+  },
+  methods:{
+    getColumns(){   //后台数据为空,则使用默认值
+      const obj=getValuesArr(this.symptomResult.questionDetailList);
+      const arr=obj.vals.length>0?obj.vals:undefined;
+      const arrp=obj.vals.length>0?obj.valsp:undefined;
+      return {arr,arrp};
+    },
+    previewRes(){
+      this.$router.push({
+        path:'/preview'
+      })
+    },
+    updata(){
+      this.symptomQasList = [];
+      //this.pdbm = '8.5rem';
+      this.showUsual=true;
+      this.num = 0;
+    },
+    selectToggle(type,result,flg,idx,order){
+      return
+      if(flg){
+        this.num = 1
+      }
+      this.symptomResult = result
+      this.type = type
+      this.order = order
+      this.scrollDown()
+    },
+    getTimeColumns(){
+      let num = [];
+      for(let i = 1; i <=60; i++) {
+        num.push(i)
+      }
+      let unit = ['分钟', '小时', '天', '周', '月','年'];
+      this.timeColumns= [
+        {
+          values:num,
+          className:'column1',
+          defaultIndex: 0
+        },
+        {
+          values:unit,
+          className:'column2',
+          defaultIndex: 2
+        },
+      ]
+    },
+    cancelSelected(){     //修改题目
+      let moduleName='',tmpArr=[],tmpPreItem={},tmpNowItem={};
+      moduleName = this.moduleMap[this.activeTab]+'QasList';
+      tmpArr = this[moduleName];
+      tmpNowItem = tmpArr[this.num];
+      this.type = -1;
+      if(tmpNowItem){
+        tmpNowItem.show = false;
+      }else{//最后一题时没有下一题
+        this.showPreview=false;
+      }
+
+      const keyIdx = this.moduleKeys.findIndex((i)=>i==this.activeTab);
+      if(this.activeTab!==this.moduleKeys[0]&&this.num===0){     //取消上一阶段的最后一题时
+        this.activeTab=this.moduleKeys[keyIdx-1];
+        this.cancelTab=keyIdx-1;
+        moduleName = this.moduleMap[this.activeTab]+'QasList';
+        const n = this[moduleName].length-1;
+        tmpPreItem = this[moduleName][n];
+        this.num=n;
+      }else{
+        this.cancelTab=keyIdx;
+        tmpPreItem = tmpArr[this.num-1];
+        this.num=this.num-1;
+      }
+      this.delExtQa(tmpPreItem,this.num);     //修改时已关联的问题先删除
+      +tmpPreItem.controlType===5?'':tmpPreItem.content='';
+      this.symptomResult = tmpPreItem;
+      const timer = setTimeout(()=>{
+        this.type = tmpPreItem.controlType;
+        clearTimeout(timer);
+      });
+      this.canceledQa=this.num;     //记录被修改过的题目,只可修改一次
+    },
+    formatQaArr(obj){
+      let arr = [],nobj=JSON.parse(JSON.stringify(obj));
+      for(let i in nobj){
+        arr.push(Object.assign({},nobj[i]));
+      }
+      return arr;
+    },
+    addExtQa(obj,i,selectedN){
+      const mName=this.moduleMap[this.activeTab];
+      let moduleName = mName+'QasList';
+      const dataArr = this.formatQaArr(obj);
+      this[moduleName][i].selectedNum=selectedN;    //选中项关联子问题的个数
+      this[moduleName].splice(i+1,0,...dataArr);
+      this.$store.commit("setModuleDatas",{data:this[moduleName],mName});
+    },
+    delExtQa(obj,i){//修改时已关联的问题先删除
+      const mName=this.moduleMap[this.activeTab];
+      let moduleName = mName+'QasList';
+      let n = obj.selectedNum;
+      if(n){
+        this[moduleName].splice(i+1,n);
+      }
+      this.$store.commit("setModuleDatas",{data:this[moduleName],mName});
+    },
+    updataResultSingle(result,contentResult,num){
+      this.num = num;
+      this.type = -1;
+      const mkeys =this.moduleKeys;
+      let moduleName = this.moduleMap[this.activeTab]+'QasList';
+      let tmpArr = JSON.parse(JSON.stringify(this[moduleName]));
+      tmpArr[num-1].content = contentResult.valp;
+      //选没有可上传报告,则上传控件不显示
+      const noUpload = this.symptomResult.id===999999&&contentResult.valp.indexOf("没有")!==-1;
+      if(noUpload&&this.deledUpload.length===0){    //是否可上传没有被修改过
+        this.deledUpload=tmpArr.splice(num,1);
+        this.$store.commit("cancelImgs");
+      }else if(this.symptomResult.id===999999&&!noUpload&&this.deledUpload.length>0){
+        tmpArr.splice(num,0,...this.deledUpload);
+        this.$store.commit("cancelImgs");
+      }
+
+      this[moduleName] = tmpArr;
+      //上传的图片及是否有可上传***答案不显示在预览所以不记录到state.diagnose.text中
+      if(this.symptomResult.id!==999999&&this.symptomResult.controlType!=4){
+        this.$store.commit('setText', { type: this.activeTab,
+          text: contentResult.val,
+          textP: contentResult.valp,
+          idx:contentResult.idx,
+          flag:contentResult.flag,
+          isEdit:this.num-1==this.canceledQa
+        });
+      }
+      //console.log(this.$store.state);   //最后一题答完
+      if(+num===this[moduleName].length||(noUpload&&+num===this[moduleName].length+1)){
+        if(this.activeTab===mkeys[mkeys.length-1]){   //最后一个模块时显示预览按钮
+          this.showPreview=true;
+          return;
+        }
+        const state = this.$store.state;
+        const tabIndx =  this.moduleKeys.findIndex((i)=>i==this.activeTab);
+        this.activeTab=this.moduleKeys[+tabIndx+1];   //进入下一个阶段问题
+        moduleName = this.moduleMap[this.activeTab]+'QasList';
+        const mDataName = this.moduleMap[this.activeTab];
+        this[moduleName] = JSON.parse(JSON.stringify(state[mDataName].datas));
+        let tmpArrDetail1 = JSON.parse(JSON.stringify(this[moduleName][0]));
+        this[moduleName][0] = tmpArrDetail1;
+        let timer = setTimeout(() => {
+          this.num = 0;
+          const tmpNowItem = this[moduleName][this.num];
+          this.type = tmpNowItem.controlType;
+          tmpNowItem.show = true;
+          //console.log(tmpNowItem)
+          this.symptomResult = tmpNowItem;
+        });
+        this.$nextTick(()=>{
+          this.scroll.refresh()
+          this.scroll.scrollTo(0, this.scroll.maxScrollY,500)
+        })
+        return;
+      }
+      let tmpArrDetailResult = JSON.parse(JSON.stringify(this[moduleName][num]));
+      let tmpArrDetail = JSON.parse(JSON.stringify(tmpArr[num]));
+      let timer = setTimeout(() => {
+        this.type = tmpArrDetail.controlType;
+        tmpArrDetail.show = true;
+        tmpArr[num] = tmpArrDetail;
+        this.symptomResult = tmpArrDetailResult;
+        clearTimeout(timer)
+      }, this.time);
+
+      this.$nextTick(()=>{
+        this.scroll.refresh()
+        this.scroll.scrollTo(0, this.scroll.maxScrollY,500)
+      })
+    },
+    showWarn(text){
+      this.waring=text;
+      this.wrong=true;
+    },
+    closeTip(){
+      this.wrong=false;
+    },
+    cancelSymptom(){      //修改(即删除)已选主症
+      this.symptomQasList = [];//console.log(this.$store.state)
+      this.selectedSymptom=[];
+      this.showUsual=true;
+      this.canceledSym = true;
+      this.type=-1;
+      this.$store.commit("clearDeledBuried");     //症状修改删除原埋点暂存数据
+      this.$store.commit('setChoose', { choose: [], type: moduleCP['symp'] });
+    },
+    selectUsual(sym){
+      this.getSymptomQas(sym.questionId);     //获取症状下的关联问题
+      sym.idx=1;    //标记主诉
+      this.$store.commit('setChoose', { choose: [sym], type: moduleCP['symp'] });
+      this.selectedSymptom = sym;   //设置搜索选中症状
+      this.showUsual=false; //关闭症状选择进入下一个问题
+      this.pdbm = '10.2rem'
+      setTimeout(() => {
+        this.scrollDown()
+      }, 0);
+    },
+    getSymptomQas(id){
+      const param = {
+        age:this.userInfo.patientAge,
+        id:id,
+        sexType:this.userInfo.sexType
+      };
+      api.getById(param).then((res) => {
+        const result = res.data;
+        if(result.code==='0'){
+          const data = result.data;
+          if(!data){
+            return ;
+          }
+          let qaLis = data.questionMapping;
+          if(qaLis.length===0){
+            this.wrong = true;
+            this.waring ='该症状数据未维护';
+            return ;
+          }
+          //qaLis.length=2;     //开发测试代码,要删除
+          qaLis[0].show=true;   //第一题自动显示
+          this.type = qaLis[0].controlType;
+          this.symptomResult = qaLis[0];
+          this.$store.commit('setSymptomDatas',qaLis);
+          this.symptomQasList = this.$store.state.symptom.origin;
+        }else{
+
+        }
+      });
+    },
+    scrollDown(){
+      this.scroll.scrollTo(0, this.scroll.maxScrollY)
+    },
+  },
+  components:{
+    Radio,
+    Select,
+    Dialog,
+    Picker,
+    Label,
+    ComTextArea,
+    /*Input,*/
+    PickTime,
+    UploadImg,
+    PushSymptom,
+    ConfirmBox,
+    UsualSymptom,
+    MultSelect,
+    TipWarning,
+    Head
+  }
+}
+</script>
+<style lang="less" scoped>
+  @import "../less/base.less";
+.wrapper {
+  height: 100%;
+  width: 100%;
+  position: fixed;
+  box-sizing: border-box;
+  overflow: hidden;
+  top: 0.86rem;
+}
+.scrollPart {
+  // padding-bottom: 5rem;
+  // padding-top: 1.44rem;
+  // box-sizing: border-box;
+}
+.progress-bar {
+  height: .8rem;
+  line-height: 0.44rem;
+  background: #fff;
+  color: #aaa;
+  /*margin-bottom:.4rem;*/
+  .title{
+    height: 100%;
+  }
+  span{
+    display: inline-block;
+    font-size: .26rem;
+    color: #aaa;
+    text-align: center;
+    &:not(:last-child):after{
+        content: ">";
+        float: right;
+        color: #aaa;
+     }
+  }
+  .active{
+    font-size: #font[dialog];
+    color: #colors[theme];
+    font-weight: 500;
+  }
+  .progress{
+    height:0.06rem;
+    background:#F5F5F5;
+    p{
+      width:.1px;
+      height: 100%;
+      background: #colors[theme];
+    }
+  }
+}
+.right {
+  padding-top: .2rem;
+  margin-bottom: .12rem;
+  padding-right: .24rem;
+  .content {
+    max-width: 5rem;
+    background-color: #colors[theme];
+    border-radius: .24rem 0 .24rem .24rem;
+    margin-top: .3rem;
+    font-size: #font[dialog];
+    padding: .24rem;
+    display: inline-block;
+    p {
+      color: #fff;
+    }
+  }
+  img {
+    width: 0.8rem;
+    height: 0.8rem;
+    margin-left: .24rem;
+  }
+}
+.left {
+  margin-bottom: .2rem;
+  padding-top: .12rem;
+  padding-left: .24rem;
+  .content {
+    max-width: 5rem;
+    background-color: #colors[bgques];
+    border-radius: 0 .24rem .24rem .24rem;
+    margin-top: .3rem;
+    font-size: #font[dialog];
+    padding: .24rem;
+    display: inline-block;
+  }
+  img {
+    width: 0.8rem;
+    height: 0.8rem;
+    margin-right: .24rem;
+  }
+}
+  .edit{
+    color: #colors[theme];
+    font-style: normal;
+    font-size: #font[dialog];
+    float: right;
+    display: inline-block;
+    margin-top: .56rem;
+    margin-right: .24rem;
+  }
+  .submit{
+    position: fixed;
+    bottom: 0;
+    width: 100%;
+    a{
+      display: inline-block;
+      width: 100%;
+      height: 0.88rem;
+      font-size: #font[dialog];
+      background-color: #colors[btn];
+      line-height: 0.88rem;
+      margin-top: 0.8rem;
+      text-align: center;
+      color: #fff;
+    }
+  }
+
+</style>

+ 36 - 15
src/components/PathInfo.vue

@@ -10,12 +10,12 @@
         <p class="perLine">
           <span class="msgTitle">姓名</span>
           <i>:</i>
-          <span>{{pathInfo.patientName}}</span>  
+          <span>{{pathInfo.patientName}}</span>
         </p>
         <p class="perLine">
           <span class="msgTitle">性别</span>
           <i>:</i>
-          <span>{{pathInfo.patientSex}}</span>  
+          <span>{{pathInfo.patientSex}}</span>
         </p>
         <p class="perMsg perLine">
           <span class="msgTitle">年龄</span>
@@ -31,7 +31,7 @@
         <p class="perLine" v-if="pathInfo.hospitalDeptName">
           <span class="msgTitle">{{pathInfo.hospitalDeptName?'科室':''}}</span>
           <i v-if="pathInfo.hospitalDeptName">:</i>
-          <span>{{pathInfo.hospitalDeptName}}</span>  
+          <span>{{pathInfo.hospitalDeptName}}</span>
         </p>
         <p class="perLine" v-if="pathInfo.recordId">
           <span class="msgTitle">{{pathInfo.recordId?'排队号':''}}</span>
@@ -50,7 +50,7 @@
         <p class="already" v-if="type !== 1">{{text[type]}}</p>
       </div> -->
     </div>
-    
+
     <Toast
       :message="message"
       :show="showToast"
@@ -69,7 +69,7 @@
   import api from '@utils/api.js'
   import Submit from '../common/Submit';
   import Toast from '../common/Toast.vue';
-  import {setScroll,dateParser,setTitle,moduleConfig } from '@utils/tools.js'
+  import {setScroll,dateParser,setTitle,moduleConfig,getUrlArgObject } from '@utils/tools.js'
   import StartPage from "../common/HomePage";
   import BScroll from 'better-scroll';
   import {mapState} from 'vuex';
@@ -107,6 +107,8 @@
       }),
     },
     created(){
+      const showDoctor = getUrlArgObject("showDoctor");
+      this.$store.commit("setShowDoctor",showDoctor);
       this.getPathInfo();
       this.$store.commit('initAllData');//初始化store数据
     },
@@ -151,7 +153,8 @@
           localStorage.removeItem('scan')
           this.getSysConfig(1);
           if(localStorage.getItem("startPage") == 1){
-            this.showStart = true
+            this.showStart = true;
+            document.title = '智能预问诊';
           }
         }
         api.getPathInfo(params).then((res)=>{
@@ -160,6 +163,7 @@
             this.pathInfo = result.data;
             this.$store.commit('savePathInfo',result.data);
             this.getAll(); //获取模板
+            this.getUsualSymptom();   //获取科室常用症状
           }
         })
       },
@@ -180,8 +184,10 @@
                     if(+datas[i].value==1){
                         localStorage.setItem('startPage',1)
                         //显示启动页
-                        this.showStart = true
+                        this.showStart = true;
+                        document.title = '智能预问诊';
                     }else{
+                        document.title = '挂号详情';
                         localStorage.setItem('startPage',0)
                     }
                 }
@@ -189,6 +195,21 @@
           }
         })
       },
+      getUsualSymptom(){
+        const param = {
+          "age": this.pathInfo.patientAge,
+          "deptName": this.pathInfo.selfDeptName,
+          "sexType": this.pathInfo.sexType
+        };
+        api.getSymptom(param).then((res) => {
+          const result = res.data;
+          if (result.code == 0) {
+            this.$store.commit("setUsualSymptom",result.data);
+          }else{
+            this.defaultWaring('常用症状获取失败,请稍后重试!')
+          }
+        })
+      },
       recordCheck(){
         const param = {
           'doctorId':this.pathInfo.doctorId,
@@ -196,7 +217,7 @@
           'hospitalId':this.pathInfo.hospitalId,
           'inquiryCode':this.pathInfo.recordId,
           'patientId':this.pathInfo.patientId
-        }
+        };
         api.recordCheck(param).then((res)=>{
           const result = res.data;
           if(result.code==0){
@@ -204,7 +225,7 @@
             if(type == 3||type == 6){//有预问诊信息
               this.showToast = true
             }else{
-              this.goNext()
+              this.goNext();
             }
           }
         })
@@ -250,7 +271,7 @@
           this.submit = false
           clearTimeout(timer)
         }, 2000);
-      }, 
+      },
     },
     components:{
       Submit,
@@ -300,7 +321,7 @@
     .explain {
       font-size: .24rem;
       color: #AAAAAA;
-      padding:0 .4rem; 
+      padding:0 .4rem;
       line-height: .4rem;
       position: relative;
       bottom: 1.1rem;
@@ -351,15 +372,15 @@
           margin-right: .24rem;
         }
       }
-      
+
     }
     .btmContent {
-      width: 94%;
+      width: 6.9rem;
       height: .88rem;
       line-height: .88rem;
       text-align: center;
       background-color: #colors[btn];
-      font-size: .32rem;
+      font-size: #font[title];
       color: #fff;
       margin: 0 auto;
       border-radius: .44rem;
@@ -372,4 +393,4 @@
       height: 0.22rem;
     }
   }
-</style>
+</style>

+ 89 - 98
src/components/Preview.vue

@@ -35,12 +35,13 @@
             <li>
               <h4><i></i> 现病史:</h4>
               <p>
+                  <!-- 患者于时间单位前诱因出现症状,其余题目的内容; -->
+                <span>{{mainTextP+","}}</span>
                 <template v-for="(value,index) in checkText">
                   <!-- 患者于时间单位前诱因出现症状,其余题目的内容; -->
-                  <span :key="index" v-if="index==0">{{(value.idx==1?'':'伴')+value.textP}}{{checkText.length==1?'':','}}</span>
-                  <span :key="index" v-if="index==1">{{(checkText[0].idx == 1?'伴':'')+value.textP}}{{checkText.length==2?'':'、'}}</span>
-                  <span :key="index" v-if="index>1">{{value.textP}}{{index == checkText.length-1?'':'、'}}</span>
+                  <span :key="index" v-if="index>0&&value.flag!=1&&value.flag!=2&&index<checkText.length-1">{{value.textP+","}}</span>
                 </template>
+                <span>{{banTextP}}</span>
               </p>
               <p><span>{{getDetailText(diagnose.text,false).view}}</span></p>
             </li>
@@ -52,29 +53,32 @@
             </li>
             <li v-if="tabType[moduleCP['suplement']]==1">
               <h4><i></i> 补充内容:</h4>
-              <p>{{addContent.txt}}</p>
+              <p>{{getDetailText(addContent.text,false).view}}</p>
             </li>
-            <li v-if="JSON.stringify(diagnose.imgSrc) !='{}'" class="imgLis">
-              <h4 class="imgTitle"><i></i> 最近一次治疗报告:</h4>
+            <li v-if="Object.keys(diagnose.imgSrc).length>0" class="imgLis">
+              <h4 class="imgTitle"><i></i>最近一次治疗报告:</h4>
               <div v-for="(value,key,idx) in diagnose.imgSrc" class="imgView">
                 <img :src="value" alt="">
               </div>
             </li>
           </ul>
         </div>
-        <div class="doctorData" @click="handleClick(true)">医生端数据展示</div>
+        <div v-if="showDoctor" class="doctorData" @click="handleClick(true)">医生端数据展示</div>
       </div>
     </div>
-    <div class="foot">
+    <!--<div class="foot">
         <span
           class="back"
           @click="back"
         >上一步</span>
         <span
-          class="next"
+          class="submit-btn"
           @click="saveAllImage"
-        >提 交</span>
-      </div>
+        >提交给医生</span>
+      </div>-->
+    <div class="realSure sure" @click="saveAllDate">
+    提交给医生
+  </div>
       <Submit
         v-if="submit"
         :showType="showType"
@@ -93,17 +97,18 @@
                   <span v-for="(item,idx) in symptom.choose" :key="item.name+idx" v-if="item.idx == 1">
                     {{item.special?item.name+item.special:item.name}}
                   </span>
-                </p>                
+                </p>
               </li>
               <li>
                 <h4><i></i> 现病史:</h4>
                 <p>
+                  <!-- 患者于时间单位前诱因出现症状,其余题目的内容; -->
+                  <span>{{mainText+","}}</span>
                   <template v-for="(value,index) in checkText">
                     <!-- 患者于时间单位前诱因出现症状,其余题目的内容; -->
-                    <span :key="index" v-if="index==0">{{(value.idx==1?'':'伴')+value.text}}{{checkText.length==1?'':','}}</span>
-                    <span :key="index" v-if="index==1">{{(checkText[0].idx == 1?'伴':'')+value.text}}{{checkText.length==2?'':'、'}}</span>
-                    <span :key="index" v-if="index>1">{{value.text}}{{index == checkText.length-1?'':'、'}}</span>
+                    <span :key="index" v-if="index>0&&value.flag!=1&&value.flag!=2&&index<checkText.length-1">{{value.text+","}}</span>
                   </template>
+                  <span>{{banText}}</span>
                 </p>
                 <p><span>{{getDetailText(diagnose.text,false).content}}</span></p>
               </li>
@@ -115,7 +120,7 @@
               </li>
               <li v-if="tabType[moduleCP['suplement']]==1">
                 <h4><i></i> 补充内容:</h4>
-                <p>{{addContent.txtDoc}}</p>
+                <p>{{getDetailText(addContent.text,false).content}}</p>
               </li>
               <li v-if="JSON.stringify(diagnose.imgSrc) !='{}'" class="imgLis">
                 <h4 class="imgTitle"><i></i> 最近一次治疗报告:</h4>
@@ -138,28 +143,33 @@ import {moduleCP,trimDots,setScroll,dateParser} from '@utils/tools.js'
 import { mapState } from 'vuex';
 export default {
   data() {
-    const { pathInfo, originDatas } = this.$store.state;
+    const { pathInfo, originDatas,showDoctor } = this.$store.state;
     let sysConfig = this.$store.state.sysConfig;
     let symptomDate = this.$store.state.symptom;
     let diagnoseDate = this.$store.state.diagnose;
     let othersDate = this.$store.state.others;
     let addContentDate = this.$store.state.addContent;
-    console.log(symptomDate)
     return {
       msg: '预览',
+      showDoctor:showDoctor,
       pathInfo: pathInfo,
       symptom: symptomDate,
       diagnose: diagnoseDate,
       others: othersDate,
       addContent: addContentDate,
       checkText: symptomDate.text, //症状情况文字
+      symChoose:symptomDate.choose,
+      mainText:"",      //患者于**前**出现
+      banText:"",     //伴**
+      mainTextP:"",      //患者于**前**出现
+      banTextP:"",     //伴**
+      symLast:"",     //除主诉伴随剩余的症状详情内容
       submit: false,
       showType: 'fail',
-      imgList:[],
+      //imgList:[],
       tmpNum:0,
       moduleCP:moduleCP,
       showDoc:false,
-      trimDots:trimDots,
       time:''
     }
   },
@@ -167,6 +177,8 @@ export default {
     ...mapState({
       tabType: state => state.tabType,
       config: state => state.sysConfig,
+      addBuriedSomeList:state=>state.addBuriedSomeList,
+      imgList:state=>state.uploadImgs
     })
   },
   created(){
@@ -187,9 +199,10 @@ export default {
       }
     }
   },
-  mounted() {
-    let scroll = setScroll(BScroll,true,'.previewper')
-    this.scroll = scroll
+  mounted() {console.log(this.$store.state);
+    let scroll = setScroll(BScroll,true,'.previewper');
+    this.scroll = scroll;
+    this.formatSymText();     //拼出现病史规则句型
   },
   methods: {
     getTime() {
@@ -213,63 +226,6 @@ export default {
     back() {
       this.$router.go(-1);
     },
-    saveAllImage() {
-      let formData = new FormData();
-      let imgList = this.diagnose.imgFile;
-      // let tmpNum = this.tmpNum;
-      // var dateBegin = new Date();//获取当前时间
-      if (imgList.length > 0) {//有图片先上传图片
-        this.$store.commit('handleToggleShow', true);
-        for (let i = 0; i < imgList.length; i++) {
-          let pageFile = imgList[i].file
-          formData.append('upfiles', imgList[i].file);
-          // formData.append('upfile', imgList[i].file);
-          formData.append('type', imgList[i].type);
-          // api.uploadImageThum(formData).then((res)=>{
-          //   console.log(res)
-          //   let result = res.data;
-          //   if (result.code == 0) {
-          //     this.tmpNum = ++tmpNum
-          //     if(this.tmpNum == imgList.length){
-          //       var dateEnd = new Date();//获取当前时间
-          //       var dateDiff = dateEnd.getTime() - dateBegin.getTime();//时间差的毫秒数
-          //       var dayDiff = dateDiff / 1000;//计算出秒数
-          //       alert('图片上传完成:'+dayDiff+'s')
-          //     }
-          //   }
-          // })
-        }
-        api.uploadImageThums(formData).then((res) => {//获取图片
-          let data = res.data;
-          if (data.code == 0) {//图片提交成功再保存数据
-            let reportList = [];
-            let result = data.data;
-            for(let i = 0;i < result.length;i++){
-              let obg = {}
-              obg.originalImage = result[i].url+'?width='+imgList[i].imgWidth+'&height='+imgList[i].imgHeight
-              obg.originalName = result[i].original
-              obg.orderNum = i+1
-              obg.type = result[i].type
-              reportList.push(obg)
-            }
-            this.imgList = reportList
-                // var dateEnd = new Date();//获取当前时间
-                // var dateDiff = dateEnd.getTime() - dateBegin.getTime();//时间差的毫秒数
-                // var dayDiff = dateDiff / 1000;//计算出秒数
-                // alert('图片上传完成:'+dayDiff+'s')
-            this.saveAllDate()
-          } else {//提交失败提示
-            this.defaultWaring(res)
-          }
-        }).catch((err)=>{
-          this.defaultWaring(err)
-        })
-        return;
-      } else {//没有图片直接保存数据
-        this.$store.commit('handleToggleShow', true);
-        this.saveAllDate();
-      }
-    },
     getDetailText(textArr,flg){
       let msg = "",obg={},msgP = "";
       if(flg == 1){
@@ -306,6 +262,22 @@ export default {
       obg.type=flg
       return obg;
     },
+    formatSymText(){
+      const symChoose = this.symptom.choose;
+      const symText = this.symptom.text;
+      const bans = symText[symText.length-1];
+      const call = this.pathInfo.patientAge>18?'患者':'患儿';
+      const times = symChoose[0].special||'';
+      const reason = symChoose[0].reason||'';
+      const timesp = symChoose[0].specialP||'';
+      const reasonp = symChoose[0].reasonP||'';
+      const timeText = times?"于"+times+"前"+reason+"出现":reason+"出现";
+      const timeTextp = times?"于"+timesp+"前"+reasonp+"出现":reasonp+"出现";
+      this.mainText = call+timeText+symChoose[0].name;
+      this.mainTextP = call+timeTextp+(symChoose[0].description||symChoose[0].name);
+      this.banText = bans.text==="没有了"?"":"伴"+bans.text;
+      this.banTextP = bans.text==="没有了"?"":"伴"+bans.textP;
+    },
     saveAllDate() {
       const {pathInfo,symptom,diagnose,others,addContent} = this
       let tmpSymptom = JSON.parse(JSON.stringify(symptom))
@@ -314,25 +286,25 @@ export default {
         if(i == 0){
           detailList[0]=this.getDetailText(tmpSymptom.choose,1)
         }else if(i == 1){
-          let tmpArr = []
-          let tmpStr = this.getDetailText(diagnose.text,2).content
-          for(let j = 0;j < tmpSymptom.text.length;j++){
-            if(j == 1){
-              let tmpTxt = '伴'+tmpSymptom.text[1].text
-              tmpSymptom.text[1].text = tmpTxt
+          let tmpArr = [this.mainText];
+          let tmpStr = this.banText;
+          let symText = tmpSymptom.text;
+          for(let j = 1;j < symText.length-1;j++){
+            if(+symText[j].flag!==1&&+symText[j].flag!==2&&typeof(symText[j].text)!=='object'){   //诱因和时间已拼不重复添加,上传的图片不拼单独显示
+              tmpArr.push(symText[j].text);
             }
-            tmpArr.push(tmpSymptom.text[j].text)
           }
-          tmpStr.length>0?tmpArr.push(tmpStr):null
-          detailList[1].content=tmpArr.join()
-          detailList[1].contentJson=JSON.stringify(tmpArr)
-          detailList[1].contentValue=tmpArr.join()
+          const diagObj = this.getDetailText(diagnose.text,false);
+          const diagStr=diagObj.content;
+          const diagJson=diagObj.contentJson;
+          tmpStr?tmpArr.push(tmpStr):null;
+          detailList[1].content=tmpArr.join()+","+diagStr;
+          detailList[1].contentJson=JSON.stringify(tmpArr.concat(diagJson));
+          detailList[1].contentValue=tmpArr.join();
         }else if(i == 2){
           detailList[2] = this.getDetailText(others.text,3)
         }else if(i == 3){
-          detailList[3].content=addContent.txtDoc
-          detailList[3].contentJson=addContent.txtDoc
-          detailList[3].contentValue=addContent.txtDoc
+          detailList[3]=this.getDetailText(addContent.text,4);
         }
       }
       let params = {
@@ -356,13 +328,14 @@ export default {
         // "patientPhone": pathInfo,//患者联系电话(非)
         "patientSex": pathInfo.patientSex=='男'?1:2,//患者性别:1男2女(非)
         // "regVisitedState": pathInfo,//就诊状态(0待接诊,1接诊中,2完成接诊)(非)
-        "reportList": this.imgList,
+        "reportList": this.imgList||[],
         "sonHospitalCode": pathInfo.sonHospitalCode,
         "sonHospitalId": pathInfo.sonHospitalId,
         "sonHospitalName": pathInfo.sonHospitalName,
         // "type": 0//病历分类(1:门诊,2:住院)
       }
       // console.log(params)
+      this.saveBuriedSome(pathInfo)//埋点
       api.saveInquiry(params).then((res) => {
         if (res.data.code == 0) {
           this.$store.commit('handleToggleShow', false);
@@ -372,7 +345,20 @@ export default {
           this.defaultWaring(res)
         }
       }).catch((err)=>{
-          this.defaultWaring(err)
+        this.defaultWaring(err)
+      })
+    },
+    saveBuriedSome(pathInfo){
+        let params = {
+          "doctorId": pathInfo.doctorId||'',
+          "hospitalDeptId": pathInfo.hospitalDeptId||'',
+          "hospitalId": pathInfo.hospitalDeptId||'',
+          "inquiryCode": pathInfo.hospitalDeptId||'',
+          "patientId": pathInfo.hospitalDeptId||'',
+          "taggeds": this.addBuriedSomeList||[]
+        }
+        api.saveBuriedSome(params).then((res)=>{
+          console.log('埋点')
         })
     },
     defaultWaring(res){
@@ -459,10 +445,10 @@ export default {
       padding: .1rem .3rem;
       overflow: hidden;
     }
-    li.imgLis {
+    /*li.imgLis {
       padding-right: 0;
       padding-left: 0;
-    }
+    }*/
     h4 {
       color: #colors[quest];
       font-size: .32rem;
@@ -575,4 +561,9 @@ export default {
   padding: 8px;
   z-index: 1001;
 }
+  .sure{
+    position: fixed;
+    bottom: 0;
+    z-index: 100;
+  }
 </style>

+ 45 - 28
src/components/Search.vue

@@ -5,7 +5,7 @@
           <div class="iptWrap">
             <img
               class="searchImg"
-              src="../images/searchB.png"
+              src="../images/search.png"
               alt=""
             >
             <input
@@ -18,20 +18,23 @@
           <span @click="search">取消</span>
         </div>
         <div class="searchList">
-          <p
+          <!--<p
             class="waring"
             v-if="!searchVal&&!hasMore&&searchLis.length==0"
-          >请输入搜索内容</p>
-          <p
+          >请输入搜索内容</p>-->
+          <div
             class="waring"
             v-if="hasMore&&searchVal"
-          >暂无搜索结果</p>
+          >
+            <img src="../images/empty.png" alt=""/>
+            <p>暂无搜索结果</p>
+          </div>
           <ul>
             <li
               v-for="(item,idx) in searchLis"
               :key="item.conceptId+idx"
               @click="showDetil(item)"
-              :style="{'borderBottom':(idx==searchLis.length-1)?'0':'1px solid #a8a8a8'}"
+              :style="{'borderBottom':(idx==searchLis.length-1)?'0':'1px solid #E8E8E8'}"
             ><img
                 class="searchImgLis"
                 src="../images/search.png"
@@ -57,7 +60,7 @@ export default {
   },
   computed:{
     ...mapState({
-      chooseSymp: state => state.symptom.choose,//已选症状
+      //chooseSymp: state => state.symptom.choose,//已选症状
       pathInfo: state => state.pathInfo
     }),
   },
@@ -76,17 +79,24 @@ export default {
   },
   methods: {
     showDetil(item) {
-      let flg = false;
+      /*let flg = false;
       if(JSON.stringify(this.tmpItem)==JSON.stringify(item)){//eg:重复点击胸痛bug
         flg = true
       }
       this.tmpItem = item
-      
+
       if(this.chooseSymp.length == 0){
         item.idx = 1
-      }
+      }*/
       let timer = setTimeout(() => {
-        this.$emit('showDetil',item,flg)
+        this.$emit('showDetil',item);
+        let obj = {
+          "labelName": item.tagName||item.name,//标签名称
+          "operationNum": 1,//次数
+          "operationType": 2,//1常见2搜索
+        };
+        this.$store.commit('setText', { type: 1, text: '患者出现'+item.name,textP: '患者出现'+(item.description||item.name), pId: item.questionId,idx:'' });
+        this.$store.commit('addBuriedSome', obj);
         clearTimeout(timer)
       }, 250);
       // this.$emit('search', false)
@@ -95,15 +105,15 @@ export default {
       this.$emit('search', false)
     },
     searchList() {
-      let tmpArr = [], chooseSymp = this.chooseSymp;
-      for (let i = 0; i < chooseSymp.length; i++) {
+      let tmpArr = []/*, chooseSymp = this.chooseSymp*/;
+      /*for (let i = 0; i < chooseSymp.length; i++) {
         if(chooseSymp[i].conceptId){
           tmpArr.push(chooseSymp[i].conceptId)
         }
-      }
+      }*/
       const param = {
         "age": this.pathInfo.patientAge,
-        "inputIds": tmpArr,
+        "inputIds": [],
         "inputStr": this.searchVal,
         "sexType": this.pathInfo.sexType
       }
@@ -130,13 +140,12 @@ export default {
   top: 0;
   left: 0;
   z-index: 102;
-  background-color: #ededed;
   font-size: .3rem;
+  overflow: hidden;
 }
 .searchTop {
-  padding: 0.15rem 0.4rem;
+  padding: 0.4rem 0.4rem 0.15rem;
   padding-right: 1.2rem;
-  background-color: #ededed;
   box-sizing: border-box;
   position: absolute;
   width: 100%;
@@ -145,15 +154,15 @@ export default {
   span {
     position: absolute;
     right: 0.32rem;
-    top: 0.32rem;
-    font-size: 0.3rem;
+    top: 0.54rem;
+    font-size: 0.24rem;
     color: #666666;
   }
 }
 .iptWrap {
-  height: 0.74rem;
+  height: 0.68rem;
   border-radius: 0.37rem;
-  background-color: #fff;
+  background-color: #F5F5F5;
   overflow: hidden;
   padding: 0.16rem 0.3rem 0.16rem 0.75rem;
   box-sizing: border-box;
@@ -169,8 +178,9 @@ export default {
   input {
     width: 100%;
     height: 0.42rem;
-    font-size: 0.3rem;
+    font-size: 0.24rem;
     line-height: 0.42rem;
+    background: #F5F5F5;
   }
 }
 .searchList {
@@ -182,13 +192,20 @@ export default {
   padding-top: 1.04rem;
   height: 100%;
   width: 100%;
-  background-color: #ededed;
+  background-color: #fff;
   .waring {
-    padding-left: 0.5rem;
-    margin-top: 0.2rem;
+    width: 100%;
+    text-align: center;
+    margin-top: 1.6rem;
+    p{
+      color: #aaa;
+      margin-top: .8rem;
+      font-size: .24rem;
+    }
+
   }
   ul {
-    padding: 0 0.4rem;
+    padding: 0.2rem 0.2rem 0;
     box-sizing: border-box;
     background-color: #fff;
   }
@@ -196,7 +213,7 @@ export default {
     height: 1rem;
     line-height: 1rem;
     padding: 0 0.4rem;
-    border-bottom: 1px solid #a8a8a8;
+    border-bottom: 1px solid #E8E8E8;
     box-sizing: border-box;
     .searchImgLis {
       width: 0.44rem;

BIN
src/images/back.png


BIN
src/images/doctor.png


BIN
src/images/empty.png


BIN
src/images/icon_que.png


BIN
src/images/patient.png


BIN
src/images/plus.png


BIN
src/images/wait.gif


+ 29 - 3
src/less/base.less

@@ -9,8 +9,16 @@
   exclu:#e6e7e9; //互斥文字颜色
   btn:#6678FF;//按钮颜色
   line:#E6E6E6;//按钮颜色
-  bgques:#F9F9F9;//问题背景颜色
+  bgques:#F3F4F6;//问题背景颜色
 }
+#font(){
+  banner:.36rem;    //导航文字
+  title:.32rem;   //标题文字
+  select:0.3rem;    //选项文字
+  dialog:.28rem;    //对话内容文字
+  placeholder:.24rem; //placeholder
+}
+
 .mask{
   width:100%;
   height: 100%;
@@ -19,6 +27,10 @@
   left: 0;
   background:rgba(0,0,0,.5);
 }
+input::placeholder,textarea::placeholder {
+  font-size: #font[placeholder]!important;
+  color: #ccc!important;
+}
 .footer{
   width:100%;
   text-align: center;
@@ -59,7 +71,7 @@
     line-height: .88rem;
     text-align: center;
     vertical-align: top;
-    border: 1px solid #colors[theme];  
+    border: 1px solid #colors[theme];
     box-sizing: border-box;
     border-radius: .44rem;
   }
@@ -175,4 +187,18 @@
 }
 .displayNone {
   display: none !important;
-}
+}
+.sure {
+  width: 100%;
+  height: 0.88rem;
+  font-size: .32rem;
+  background-color: #colors[btn];
+  line-height: 0.88rem;
+  margin-top: 0.8rem;
+  text-align: center;
+  color: #fff;
+  opacity: 0.5;
+  &.realSure {
+    opacity: 1;
+  }
+}

+ 10 - 4
src/less/index.less

@@ -5,9 +5,14 @@ body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, input, textarea, p, t
   font-family: Arial, sans-serif, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB";
   color: #333333;
   // -webkit-text-size-adjust:100%;
-  -webkit-text-size-adjust:auto;
+  // -webkit-text-size-adjust:auto;
   -webkit-tap-highlight-color: rgba(0,0,0,0);
   -webkit-tap-highlight-color: transparent;
+
+  -webkit-text-size-adjust : none ;
+  -moz-text-size-adjust : none ;
+  -ms-text-size-adjust : none ;
+  text-size-adjust : none
 }
 input, textarea{
   outline: none;
@@ -56,7 +61,7 @@ a {
 /* 单行文字溢出时出现省略号,需设定宽度 */
 .ellips {
     overflow: hidden;
-    white-space: nowrap;    
+    white-space: nowrap;
     text-overflow: ellipsis;
 }
 
@@ -65,6 +70,7 @@ html,body{
   height: 100%;
   position: absolute;
   overflow: hidden;
+  background: #fff;
 }
 html{
   margin: 0;
@@ -86,7 +92,7 @@ html{
     }
     .resultSym {
       overflow: hidden;
-      white-space: nowrap;    
+      white-space: nowrap;
       text-overflow: ellipsis;
       width: 110px;
     }
@@ -96,4 +102,4 @@ html{
     .main .mainBtm .Recommend .btn {
       padding: 0 10px !important;
     }
-} */ 
+} */

+ 15 - 7
src/router/index.js

@@ -1,7 +1,8 @@
 import Vue from 'vue';
 import Router from 'vue-router';
 import PathInfo from '@components/PathInfo.vue';
-import TabPage from '@components/TabPage.vue';
+/*import TabPage from '@components/TabPage.vue';*/
+import MainPage from '@components/MainPage.vue';
 import Login from '@components/Login.vue';
 import Symptom from '@components/Symptom.vue';
 import DiagTreat from '@components/DiagTreat.vue';
@@ -15,6 +16,9 @@ const router = new Router({
     {
       path:'/',
       name:'Login',
+      meta:{
+        title:'智能预问诊'
+      },
       component:Login
     },
     {
@@ -27,10 +31,14 @@ const router = new Router({
     },
     {
       path:'/tab',
-      component:TabPage,
-      children:[
+      name:'MainPage',
+      meta:{
+        title:'智能预问诊'
+      },
+      component:MainPage,
+      /*children:[
         {
-          path:'/',      
+          path:'/',
           name:'symptom',
           component:Symptom
         },{
@@ -46,7 +54,7 @@ const router = new Router({
           name:'add',
           component:AddContent
         }
-      ]
+      ]*/
     },
     {
       path:'/department',
@@ -73,7 +81,7 @@ router.beforeEach((to, from, next) => {
     document.title = to.meta.title;
     // let i = document.createElement('iframe');//解决qq内title不刷新问题
     // i.style.display = 'none';
-    // i.src = '.'; 
+    // i.src = '.';
     // i.onload = ()=>{
     //     setTimeout(()=>{
     //         i.remove()
@@ -83,4 +91,4 @@ router.beforeEach((to, from, next) => {
   }
   next();
 })
-export default router;
+export default router;

+ 169 - 59
src/store.js

@@ -9,6 +9,7 @@ const store = new Vuex.Store({
     pathInfo:{}, //患者信息-后续提交要用
     sysConfig:[], //系统配置项
     allMoudles:[], //模板
+    extPushSymptom:[],      //后台维护的伴随症状
     scroll:{
       x:0,y:0
     },
@@ -34,6 +35,7 @@ const store = new Vuex.Store({
     },
     addContent:{
       origin:[],
+      datas:[],
       txt:'',
       txtDoc:''
     },
@@ -59,8 +61,31 @@ const store = new Vuex.Store({
       "3": 0,
       "52": 0,
     },
+    addBuriedSomeList:[],//买点数据
   },
   mutations:{
+    setShowDoctor(state,flag){
+      state.showDoctor=flag;
+    },
+    clearDeledBuried(state){
+      state.addBuriedSomeList=[];
+    },
+    addBuriedSome(state,item){
+      let list = state.addBuriedSomeList,num=0
+      for(let i = 0;i < list.length;i++){
+        let number = list[i].operationNum
+        if(list[i].labelName == item.labelName&&list[i].operationType == item.operationType){//已经存在+1
+          list[i].operationNum = ++number
+        }else{
+          ++num
+        }
+      }
+      if(num == list.length){//没有新增一项
+        list.push(item)
+      }
+      // console.log(list)
+      state.addBuriedSomeList=list
+    },
     setFinish(state,param){
       let obj = state.finish
       let obj1 = state.currentTab
@@ -71,7 +96,7 @@ const store = new Vuex.Store({
         }else{
           obj1[key] = false
         }
-      } 
+      }
       state.finish = obj
     },
     setActiveModule(state,param){
@@ -100,9 +125,11 @@ const store = new Vuex.Store({
       }
       state.addContent={
         origin:[],
-        txt:'',
+        datas:[],
+        text:[],
         txtDoc:''
       }
+      state.addBuriedSomeList=[]//买点数据
     },
     setDetail(state,param){//明细
       const detail = param.detail;
@@ -125,6 +152,20 @@ const store = new Vuex.Store({
     setSearchShow(state,flg){//搜索显示与否
       state.searchShow = flg;
     },
+    setSymptomDatas(state,data){
+      const temp = formatSymptomData(data);
+      state.symptom.origin = temp.newArr;
+      state.symptom.datas = JSON.parse(JSON.stringify(temp.newArr));
+      state.extPushSymptom = temp.extSymptoms||[];
+    },
+    setUsualSymptom(state,data){
+      const arr = [...data];
+      arr.length=arr.length>10?10:arr.length;
+      state.usualSymptom = arr;
+    },
+    /*setExtPushSymptom(state,data){
+      state.extPushSymptom=data;
+    },*/
     setDataAll(state,param){
       let res = state.allMoudles
       for(let i = 0;i<res.length;i++){
@@ -153,11 +194,17 @@ const store = new Vuex.Store({
       state.allMoudles = param;
       for(let k in param){
         if(param[k].type == moduleCP['diagT']){
-          state.diagnose.origin = JSON.parse(JSON.stringify(param[k].moduleDetailDTOList))
-          state.diagnose.datas = JSON.parse(JSON.stringify(param[k].moduleDetailDTOList))
+          const arr = formatDiagUploadData(param[k].moduleDetailDTOList);
+          state.diagnose.origin = arr;
+          state.diagnose.datas = JSON.parse(JSON.stringify(arr));
         }else if(param[k].type == moduleCP['other']){
-          state.others.origin = JSON.parse(JSON.stringify(param[k].moduleDetailDTOList))
-          state.others.datas = JSON.parse(JSON.stringify(param[k].moduleDetailDTOList))
+          const org = param[k].moduleDetailDTOList;
+          state.others.origin = JSON.parse(JSON.stringify(org));
+          state.others.datas = JSON.parse(JSON.stringify(org));
+        }else if(param[k].type == moduleCP['suplement']){
+          const org = param[k].moduleDetailDTOList;
+          state.addContent.origin = JSON.parse(JSON.stringify(org));
+          state.addContent.datas = JSON.parse(JSON.stringify(org));
         }
       }
     },
@@ -195,12 +242,16 @@ const store = new Vuex.Store({
           }
           break;
         case moduleCP['suplement']:
-          
+
           break;
         default:
           break;
       }
     },
+    setModuleDatas(state,param){
+      const {data,mName} = param;
+      state[mName].datas = JSON.parse(JSON.stringify(data));
+    },
     setDatas(state,param){
       // ppId--每一道题的id;pId--每个选项的id
       const type = parseInt(param.type);
@@ -243,61 +294,34 @@ const store = new Vuex.Store({
         default:
           break;
       }
-      
+
     },
     setText(state,param){
       const type = parseInt(param.type);
       switch(type){
         case moduleCP['symp']:
           // 对象易更新但顺序无法控制
-          // state.symptom.text = Object.assign({},state.symptom.text,{[param.pId]:param.text}); 
+          // state.symptom.text = Object.assign({},state.symptom.text,{[param.pId]:param.text});
           let text = state.symptom.text;
-          if(text.length > 0){
-            for(let i in text){
-              // 点完成时才覆盖,单纯点开再关闭不覆盖flag
-              if(text[i].pId==param.pId){
-                if(param.flag){
-                  text.splice(i,1,param);
-                }
-                return
-              }
-            }
+          if(param.isEdit){   //修改后提交的答案,先删除原存的答案
+            text.pop();
           }
           text.push(param);
           break;
         case moduleCP['diagT']: //诊疗情况
-          let diaText = JSON.parse(JSON.stringify(state.diagnose.text)); 
-          // 先判断order,然后判断index
-          let item = diaText[param.order];
-          if(item){
-            // 判断是对象还是数组--数组则区分index
-            if(Array.isArray(item)){
-              if(param.flag){//详情完成-覆盖
-                item[param.index] = param;
-              }else{ //直接点label--无则覆盖
-                if(!item[param.index]){
-                  item[param.index] = param;
-                }
-              }
-            }else{
-              if(param.flag){
-                diaText[param.order] = param;
-              }
-            }
-          }else{
-            if(param.arrFlag){
-              let temp = [];
-              temp[param.index] = param;
-              diaText[param.order] = temp;
-            }else{
-              diaText[param.order] = param;
-            }
+          let dtext = state.diagnose.text;
+          if(param.isEdit){
+            dtext.pop();
           }
-          state.diagnose.text = diaText;
+          dtext.push(param);
           break;
         case moduleCP['other']: //其他情况
-          let otherText = JSON.parse(JSON.stringify(state.others.text));
-          let oitem = otherText[param.order];
+          let otherText = state.others.text;
+          if(param.isEdit){
+            otherText.pop();
+          }
+          otherText.push(param);
+          /*let oitem = otherText[param.order];
           if(oitem){
             // 判断是对象还是数组--数组则区分index
             if(Array.isArray(oitem)){
@@ -322,13 +346,14 @@ const store = new Vuex.Store({
               otherText[param.order] = param;
             }
           }
-          state.others.text = otherText;
+          state.others.text = otherText;*/
           break;
         case moduleCP['suplement']:
-          let addText = state.addContent.txt
-          state.addContent.origin = param.data
-          state.addContent.txt = getAllStr(param).allStr
-          state.addContent.txtDoc = getAllStr(param).allStrDoc
+          let addText = state.addContent.text
+          if(param.isEdit){
+            addText.pop();
+          }
+          addText.push(param);
           break;
         default:
           break;
@@ -397,7 +422,7 @@ const store = new Vuex.Store({
         default:
           break;
       }
-      
+
     },
     setImgSrc(state,param){
       const key = param.key;
@@ -419,7 +444,7 @@ const store = new Vuex.Store({
         default:
           break;
       }
-      
+
     },
     deleImg(state,param){
       const key = param.key;
@@ -445,7 +470,14 @@ const store = new Vuex.Store({
         default:
           break;
       }
-      
+
+    },
+    cancelImgs(state){
+      state.diagnose.imgFile=[];
+      state.diagnose.imgSrc = {};
+    },
+    setUploadImgs(state,list){
+      state.uploadImgs=list;
     },
     deleSrc(state,param){
       const key = param.key;
@@ -469,12 +501,90 @@ const store = new Vuex.Store({
         default:
           break;
       }
-      
+
     },
     handleToggleShow(state,flg){
       state.loadingShow = flg
     }
   }
-})
-
+});
+function formatDiagUploadData(data){
+  //上传图片类型处理,前面添加一个问题
+  const inx = data.findIndex((it)=>{
+    return it.controlType==4;
+  });
+  let newArr = JSON.parse(JSON.stringify(data));
+  if(inx!==-1){
+    newArr.splice(inx,0,{
+      id: 999999,
+      name: "有可以上传的最近一次诊疗记录吗?",
+      tagName: "有可以上传的最近一次诊疗记录吗?",
+      type: 51,
+      controlType: 1,
+      itemType: 0,
+      tagType: 1,
+      labelPrefix: "",
+      labelSuffix: "",
+      url: "",
+      description: "",
+      specFlag: 0,
+      required: 0,
+      explains: null,
+      exclusionType: null,
+      questionDetailList:[{id: 111111, name: "没有", description: "", questionId: 999999, orderNo: 2, exclusion: 0, remark: null},{id: 111110, name: "有,可以上传", description: "", questionId: 999999, orderNo: 1, exclusion: 0, remark: null}
+        ],
+      questionMapping: [],
+      flag: "",
+      remark: null,
+      prefix: "",
+      suffix: "",
+      moduleId: 2,
+      questionId: 1191,
+      relationModule: null,
+      relationModuleName: null});
+  };
+  return newArr;
+};
+function formatSymptomData(data){
+  //症状详情后添加一个大数据推送其他症状
+  let newArr = JSON.parse(JSON.stringify(data));
+    newArr.push({
+      id: 999998,
+      name: "您还有其他不舒服吗?(可多选)",
+      tagName: "您还有其他不舒服吗?",
+      type: 1,
+      controlType: 99,
+      itemType: 0,
+      tagType: 1,
+      labelPrefix: "",
+      labelSuffix: "",
+      url: "",
+      description: "",
+      specFlag: 0,
+      required: 0,
+      explains: null,
+      exclusionType: null,
+      questionDetailList:[],
+      questionMapping: [],
+      flag: "",
+      remark: null,
+      prefix: "",
+      suffix: "",
+      moduleId: 2,
+      questionId: 999998,
+      relationModule: null,
+      relationModuleName: null});
+    //多选伴随类型不展示问题,选项添加到推送症状前
+    let extSymptoms = [];
+    const n = data.findIndex((it)=>{
+      if(+it.controlType===8){
+        extSymptoms = it.questionDetailList;
+      }
+      return +it.controlType===8;
+    });
+    if(n!==-1){
+      newArr.splice(n,1);
+    }
+    return {newArr,extSymptoms};
+};
 export default store;

+ 9 - 1
src/utils/api.js

@@ -8,6 +8,7 @@ const urls = {
   getAll:'/api/prec/moduleInfo/getAll',//获取模板
   getSymptom:'/api/prec/questionUsual/getQuestionUsual',//常用症状
   getById:'/api/prec/questionInfo/getById',//常标签详情
+  getByIds:'/api/prec/questionInfo/getByIds',// 获取多个问题
   push:'/api/prec/push/pushInner',//症状推送
   saveInquiry:'/api/prec/inquiryInfo/saveInquiry',//保存问诊记录
   uploadImageThum:'/api/prec/file/uploadImageThum',//单个文件上传同时生成缩略图
@@ -16,6 +17,7 @@ const urls = {
   getTagInfos:'/api/prec/retrieval/getTagInfos',//检索
   signIn:'/api/prec/patientInfo/signIn',//登录
   getDisclaimerInformations:'/api/prec/disclaimerInformation/getDisclaimerInformations',//配置文案
+  saveBuriedSome:'/api/prec/statistical/saveBuriedSome',//埋点
   // uploadImageThums:'http://192.168.3.1:8849/file/uploadImageThums',//多个文件上传同时生成缩略图
 }
 
@@ -23,6 +25,9 @@ export default {
   getDisclaimerInformations(){
     return axios.post(urls.getDisclaimerInformations)
   },
+  saveBuriedSome(param){
+    return axios.post(urls.saveBuriedSome,param)
+  },
   getHospitalDatas(param){
     return axios.post(urls.getHospitalDatas,param)
   },
@@ -44,6 +49,9 @@ export default {
   getById(param){
     return axios.post(urls.getById,param)
   },
+  getByIds(param){
+    return axios.post(urls.getByIds,param)
+  },
   getPush(param){
     return axios.post(urls.push,param)
   },
@@ -62,4 +70,4 @@ export default {
   signIn(param){
     return axios.post(urls.signIn,param)
   },
-}
+}

+ 345 - 0
src/utils/data.js

@@ -0,0 +1,345 @@
+export const data = {
+    symptom:{
+        question:'是否有以下症状?',
+        type:'1',//单选1多选2滚动3
+        show:true,//当前问题是否需要显示
+        result:[//症状
+            {
+                'name':'发热',
+                'value':'1.1',//规则里面的数据
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':['1001','1002','1003','1004','1005']//关联问题的id
+            },{
+                'name':'咽喉痛',
+                'value':'1.2',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'咳嗽',
+                'value':'1.3',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':['1006']
+            },{
+                'name':'鼻塞',
+                'value':'1.4',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'流鼻涕',
+                'value':'1.5',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'胸闷',
+                'value':'1.6',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':['1008']
+            },{
+                'name':'气急',
+                'value':'1.7',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':['1009']
+            },{
+                'name':'呼吸困难',
+                'value':'1.8',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'全身酸痛',
+                'value':'1.9',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'乏力',
+                'value':'1.11',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'腹泻',
+                'value':'1.12',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':['1007']
+            },{
+                'name':'都没有',
+                'value':'1.13',
+                'special':'2',//1为正常选项,2为互斥项
+                'connectId':[]
+            }
+        ]
+    },
+    allquestion:[
+        {
+        question:'是否有以下症状?(可多选)',
+        type:'2',//单选1多选2滚动3
+        show:true,//当前问题是否需要显示
+        result:[//症状
+            {
+                'name':'发热',
+                'value':'1.1',//规则里面的数据
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':['1001','1002','1003','1004','1005']//关联问题的id
+            },{
+                'name':'咽喉痛',
+                'value':'1.2',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'咳嗽',
+                'value':'1.3',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':['1006']
+            },{
+                'name':'鼻塞',
+                'value':'1.4',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'流鼻涕',
+                'value':'1.5',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'胸闷',
+                'value':'1.6',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':['1008']
+            },{
+                'name':'气急',
+                'value':'1.7',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':['1009']
+            },{
+                'name':'呼吸困难',
+                'value':'1.8',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'全身酸痛',
+                'value':'1.9',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'乏力',
+                'value':'1.11',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':[]
+            },{
+                'name':'腹泻',
+                'value':'1.12',
+                'special':'1',//1为正常选项,2为互斥项
+                'connectId':['1007']
+            },{
+                'name':'都没有',
+                'value':'1.13',
+                'special':'2',//1为正常选项,2为互斥项
+                'connectId':[]
+            }
+        ]
+        },
+        {
+            id:'1001',
+            type:'1',
+            show:false,
+            question:'目前体温是多少?',
+            result:[
+                {
+                    'name':'<37.3℃',
+                },
+                {
+                    'name':'≥37.3℃',
+                }
+            ]
+        },
+        {
+            id:'1002',
+            type:'3',
+            show:false,
+            question:'最高体温是多少?',
+            result:[
+                {
+                    'name':'37.3℃',
+                },
+                {
+                    'name':'37.4℃',
+                },
+                {
+                    'name':'37.5℃',
+                },
+                {
+                    'name':'37.6℃',
+                },
+                {
+                    'name':'37.7℃',
+                },
+                {
+                    'name':'37.8℃',
+                },
+                {
+                    'name':'37.9℃',
+                },
+                {
+                    'name':'38.0℃',
+                }
+            ]
+        },
+        {
+            id:'1003',
+            type:'1',
+            show:false,
+            question:'发热时有没有以下情况?',
+            result:[
+                {
+                    'name':'发热体温持续不退',
+                },{
+                    'name':'体温一直大于38℃',
+                },{
+                    'name':'都没有'
+                }
+            ]
+        },
+        {
+            id:'1004',
+            type:'1',
+            show:false,
+            question:'发热后有没有吃退热药?',
+            result:[
+                {
+                    'name':'有吃退热药',
+                },{
+                    'name':'没有吃退热药',
+                }
+            ]
+        },
+        {
+            id:'1005',
+            type:'1',
+            show:false,
+            question:'吃退热药后的体温情况是?',
+            result:[
+                {
+                    'name':'体温下降',
+                },{
+                    'name':'体温下降又升高',
+                },{
+                    'name':'体温没有下降'
+                }
+            ]
+        },
+        {
+            id:'1006',
+            type:'1',
+            show:false,
+            question:'有没有咳痰?',
+            result:[
+                {
+                    'name':'没有咳痰(干咳)',
+                },{
+                    'name':'有咳痰'
+                },
+            ]
+        },
+        {
+            id:'1007',
+            type:'1',
+            show:false,
+            question:'有没有腹泻加重?',
+            result:[
+                {
+                    'name':'有',
+                },{
+                    'name':'没有',
+                }
+            ]
+        },
+        {
+            id:'1008',
+            type:'1',
+            show:false,
+            question:'有没有胸闷加重?',
+            result:[
+                {
+                    'name':'有',
+                },{
+                    'name':'没有',
+                }
+            ]
+        },
+        {
+            id:'1009',
+            type:'1',
+            show:false,
+            question:'有没有气急加重?',
+            result:[
+                {
+                    'name':'有',
+                },{
+                    'name':'没有',
+                }
+            ]
+        },
+        {
+            id:'2001',
+            type:'1',
+            show:false,
+            question:'本次不舒服有多久了?',
+            result:[
+                {
+                    'name':'14天以内',
+                },
+                {
+                    'name':'14天以上',
+                }
+            ]
+        },{
+            id:'2002',
+            type:'2',
+            show:false,
+            question:'近14天有没有以下情况?',
+            result:[
+                {
+                    'name':'有武汉(湖北)、温州、台州旅游史或居住史',
+                    'special':'1',//1为正常选项,2为互斥项
+                    'value':'2.1',
+                },
+                {
+                    'name':'有接触过来自武汉(湖北)、温州、台州的人员',
+                    'special':'1',//1为正常选项,2为互斥项
+                    'value':'2.2'
+                },
+                {
+                    'name':'有接触过疑似或确诊新型冠状病毒感染者',
+                    'special':'1',//1为正常选项,2为互斥项
+                    'value':'2.3'
+                },
+                {
+                    'name':'身边有多人出现发热、乏力、咳嗽、咽痛等',
+                    'special':'1',//1为正常选项,2为互斥项
+                    'value':'2.4'
+                },
+                {
+                    'name':'都没有',
+                    'special':'2',//1为正常选项,2为互斥项
+                    'value':'2.5'
+                }
+            ]
+        },
+    ],
+    resultList: [
+        {
+            result1:['1.1','1.2','1.3','1.4','1.5','1.6','1.7','1.8','1.9','1.11','1.12'],
+            result2:['2.1','2.2','2.3','2.4']
+        },
+        {
+            result1:['1.1','1.2','1.3','1.4','1.5','1.6','1.7','1.8','1.9','1.11','1.12'],
+            result2:['2.5']
+        },
+        {
+            result1:['1.13'],
+            result2:['2.1','2.2','2.3','2.4']
+        },
+        {
+            result1:['1.13'],
+            result2:['2.5']
+        },
+    ]
+}

+ 40 - 2
src/utils/tools.js

@@ -9,7 +9,7 @@ const configer = {
 }
 
 const getUrlArgObject = (parm) => {
-    let query = window.location.search;
+    let query = window.location.hash;
     let args = qs.parse(query.substr(1));
     return args[parm];//返回对象
 }
@@ -429,8 +429,43 @@ const getRouteName = (flg,active,order) => {
       }
     }
   }
+};
+function getValuesArr(arr){
+  let vals = [],valsp=[];
+  (arr||[]).map((it)=>{
+    vals.push(it.name);
+    valsp.push(it.description||it.name);
+  });
+  return {
+    vals,
+    valsp
+  };
 }
 
+//数值求和
+function getNSum(arr){
+  function getSum(total,num){
+    return total+num;
+  };
+  return arr.reduce(getSum,0);
+};
+
+//2数组去重
+function delResymptoms(arr,arr1){
+  let idx = -1;
+  if(!arr1||arr1.length===0){
+    return arr;
+  }
+  let newArr = arr1.reduce((total,it)=>{
+    idx = arr.findIndex((t)=>t.name===it.name);
+    if(idx===-1){
+      total.push(it);
+    }
+    return total
+  },arr);
+  return newArr;
+};
+
 module.exports =  {
   imageUrlPrefix,
   getUrlArgObject,
@@ -458,7 +493,10 @@ module.exports =  {
   getNum,
   configer,
   setTitle,
-  getRouteName
+  getRouteName,
+  getValuesArr,
+  getNSum,
+  delResymptoms
 }