Przeglądaj źródła

Merge remote-tracking branch 'origin/new' into tempMaster

# Conflicts:
#	src/utils/tools.js
zhouna 5 lat temu
rodzic
commit
8fc4334a31

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

@@ -29,7 +29,7 @@ const devWebpackConfig = merge(baseWebpackConfig, {
       ],
     },
     hot: true,
-    openPage:'?hospitalCode=A001&hospitalDeptCode=D01&doctorCode=YS001&patientCode=1600&recordId=44',//携带参数
+    // openPage:'?hospitalCode=A001&hospitalDeptCode=D01&doctorCode=YS001&patientCode=1600&recordId=44',//携带参数
     contentBase: false, // since we use CopyWebpackPlugin.
     compress: true,
     // host: HOST || config.dev.host,

+ 21 - 41
package-lock.json

@@ -281,8 +281,7 @@
     "assert-plus": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
-      "optional": true
+      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
     },
     "assign-symbols": {
       "version": "1.0.0",
@@ -2082,7 +2081,6 @@
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
       "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
-      "optional": true,
       "requires": {
         "delayed-stream": "~1.0.0"
       }
@@ -3409,8 +3407,7 @@
     "delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
-      "optional": true
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
     },
     "depd": {
       "version": "1.1.2",
@@ -4141,8 +4138,7 @@
     "extsprintf": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
-      "optional": true
+      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
     },
     "fast-deep-equal": {
       "version": "2.0.1",
@@ -4518,8 +4514,7 @@
         },
         "ansi-regex": {
           "version": "2.1.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -4537,13 +4532,11 @@
         },
         "balanced-match": {
           "version": "1.0.0",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
-          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -4556,18 +4549,15 @@
         },
         "code-point-at": {
           "version": "1.1.0",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "concat-map": {
           "version": "0.0.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "console-control-strings": {
           "version": "1.1.0",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -4670,8 +4660,7 @@
         },
         "inherits": {
           "version": "2.0.3",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "ini": {
           "version": "1.3.5",
@@ -4681,7 +4670,6 @@
         "is-fullwidth-code-point": {
           "version": "1.0.0",
           "bundled": true,
-          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -4694,20 +4682,17 @@
         "minimatch": {
           "version": "3.0.4",
           "bundled": true,
-          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
         },
         "minimist": {
           "version": "0.0.8",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "minipass": {
           "version": "2.3.5",
           "bundled": true,
-          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.2",
             "yallist": "^3.0.0"
@@ -4724,7 +4709,6 @@
         "mkdirp": {
           "version": "0.5.1",
           "bundled": true,
-          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -4797,8 +4781,7 @@
         },
         "number-is-nan": {
           "version": "1.0.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "object-assign": {
           "version": "4.1.1",
@@ -4808,7 +4791,6 @@
         "once": {
           "version": "1.4.0",
           "bundled": true,
-          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -4884,8 +4866,7 @@
         },
         "safe-buffer": {
           "version": "5.1.2",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -4915,7 +4896,6 @@
         "string-width": {
           "version": "1.0.2",
           "bundled": true,
-          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -4933,7 +4913,6 @@
         "strip-ansi": {
           "version": "3.0.1",
           "bundled": true,
-          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -4972,13 +4951,11 @@
         },
         "wrappy": {
           "version": "1.0.2",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "yallist": {
           "version": "3.0.3",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         }
       }
     },
@@ -5868,8 +5845,7 @@
     "jsbn": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
-      "optional": true
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
     },
     "json-loader": {
       "version": "0.5.7",
@@ -7216,6 +7192,11 @@
         "find-up": "^2.1.0"
       }
     },
+    "portal-vue": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npm.taobao.org/portal-vue/download/portal-vue-2.1.6.tgz",
+      "integrity": "sha1-p9R5CxSnmvf9FZpg7IjDDN3Gxjk="
+    },
     "portfinder": {
       "version": "1.0.20",
       "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz",
@@ -11021,8 +11002,7 @@
     "tweetnacl": {
       "version": "0.14.5",
       "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
-      "optional": true
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
     },
     "type": {
       "version": "1.0.1",

+ 2 - 1
package.json

@@ -12,12 +12,13 @@
   "dependencies": {
     "axios": "^0.18.0",
     "babel-polyfill": "^6.26.0",
-    "better-scroll": "^1.13.2",
+    "better-scroll": "^1.15.2",
     "fastclick": "^1.0.6",
     "jquery": "^3.4.1",
     "less": "^3.8.1",
     "less-loader": "^4.1.0",
     "lib-flexible": "^0.3.2",
+    "portal-vue": "^2.1.6",
     "vue": "^2.5.2",
     "vue-photo-preview": "^1.1.3",
     "vue-router": "^3.0.1",

+ 3 - 0
src/App.vue

@@ -1,6 +1,9 @@
 <template>
     <div id="app">
         <router-view/>
+        <portal-target name="notification-outlet"></portal-target>
+        <portal-target name="notification-detail"></portal-target>
+        <portal-target name="notification-search"></portal-target>
     </div>
 </template>
 <script>

+ 10 - 12
src/common/CheckBox.vue

@@ -1,18 +1,8 @@
 <template>
   <div class="check-wrap" v-if="item">
-    <!-- <img :src="datas.url.replace('{imageUrlPrefix}',imgUrl)" v-if="datas.url"> -->
-    <p v-for="(it,index) in datas.questionDetailList" :key="it.id" class="list" @click="handleClick(it,index)">
+    <p v-for="(it,index) in datas.questionDetailList" :key="it.id" class="list" @click="handleClick(it,index,'',true)">
       <img :src="it.select==1?check:defaultPic">
-      <!-- <span :class="{'check':it.select==1}">{{it.name}}</span> -->
       <span v-if="((it.description||it.name).indexOf('${'))==-1" :class="[{'check':it.select==1},{'exclu':exclusion !==999 && it.exclusion !== exclusion}]">{{it.description||it.name}}</span>
-      <!-- <MultiLineInput v-else 
-          @handleInp="inpVal($event,index)"
-          :msg="it.name" 
-          :part="it"
-          :border="false" 
-          :inline="true" 
-          :select="it.select==1" 
-          /> -->
       <OptionInp v-else 
           :item="it" 
           ref="inp"
@@ -47,13 +37,21 @@ import OptionInp from '../common/OptionInp.vue';
       this.resetExc();
     },
     methods:{
-      handleClick(it,index,flag){
+      handleClick(it,index,flag,flg){
+        if(flg){
+          document.activeElement.blur();      
+          document.activeElement.scrollIntoViewIfNeeded(true);
+          setTimeout(()=>{
+            document.activeElement.scrollIntoViewIfNeeded(true);
+          },300)
+        }
         const that = this;
         const list = this.datas;
         let data = list.questionDetailList&&list.questionDetailList.slice(0);
         // 处理互斥
         const excluArr = data.filter(it=>it.exclusion==1);
         const filArr = data.filter(it=>it.select==1);
+
         if(excluArr.length>0){//有互斥
           if(filArr.length>0){//有选中
             if(it.exclusion !== filArr[0].exclusion){

+ 6 - 2
src/common/ComTextArea.vue

@@ -34,10 +34,14 @@ export default {
   methods:{
     changeVal(){
       this.$emit('changeAreaVal',this.txt)
-    },
-    blur(){
       const newData = Object.assign({},this.item,{value:this.txt,valueP:this.txt});
       this.$emit("updata",newData);
+    },
+    blur(){
+      document.activeElement.scrollIntoViewIfNeeded(true);
+      setTimeout(()=>{
+        document.activeElement.scrollIntoViewIfNeeded(true);
+      },300)
     }
   },
   watch:{

+ 11 - 2
src/common/Input.vue

@@ -1,6 +1,7 @@
 <template>
   <div class="inp-wrap">
     <input :type="item.controlType==6?'text':'tel'" 
+          :maxlength="item.controlType==6?'':10"
           :class="{'change':borColor}" 
           v-model="val" 
           @input="changeVal" 
@@ -24,11 +25,19 @@
         if(this.item.controlType==7){//数字键盘
           this.val = e.target.value=e.target.value.replace(/[^\d]/g,'')
         }
-      },
-      blur(){
+        // document.activeElement.scrollIntoViewIfNeeded(true);
         this.borColor = false;
         const newData = Object.assign({},this.item,{value:this.val,valueP:this.val});
         this.$emit("updata",newData);
+      },
+      blur(){
+        document.activeElement.scrollIntoViewIfNeeded(true);
+        setTimeout(()=>{
+          document.activeElement.scrollIntoViewIfNeeded(true);
+        },300)
+        // this.borColor = false;
+        // const newData = Object.assign({},this.item,{value:this.val,valueP:this.val});
+        // this.$emit("updata",newData);
       }
     },
     watch:{

+ 22 - 22
src/common/Label.vue

@@ -1,8 +1,7 @@
 <template>
   <div class="label-wrap" v-if="item">
-    <p v-for="(it,index) in datas.questionMapping" :key="it.id" :class="['symp',{'check':it.select==1},{'exclu':exclusion !==999 && it.exclusionType !== exclusion}]" @click="handleClick(it,index)">
+    <p v-for="(it,index) in datas.questionMapping" :key="it.id" :class="['symp',{'check':it.select==1},{'exclu':exclusion !==999 && it.exclusionType !== exclusion}]" @click="handleClick(it,index,true)">
       <span>{{it.description||it.name}}</span>
-      <!-- <span v-if="it.select==1" @click="deletSymp($event,it,index)"><img src="../images/delete.png" alt=""></span> -->
       <span v-if="it.select==1" @click="deletSymp($event,it,index)"><img src="../images/del.png" alt=""></span>
     </p>
     <Toast :message="delText" 
@@ -11,10 +10,10 @@
           @cancel="cancelDel"/>
   </div>
 </template>
-<script type="text/javascript">
-import Toast from '../common/Toast.vue';
-import {moduleCP} from '@utils/tools';
-  export default{
+<script>
+  import Toast from '../common/Toast.vue';
+  import {moduleCP} from '@utils/tools';
+  export default {
     name:'Label',
     data(){
       return{
@@ -23,10 +22,11 @@ import {moduleCP} from '@utils/tools';
         showToast:false,
         delText:"是否取消当前选中内容?",
         tempItem:{},
-        exclusion:999 //互斥
+        exclusion:999, //互斥
+        delIndx:null
       }
     },
-    props:['item','moduleType','ppId'],
+    props:['item','moduleType','ppId','order'],
     created(){
       this.datas = this.item;
       // 回读互斥项标识
@@ -40,7 +40,14 @@ import {moduleCP} from '@utils/tools';
       Toast
     },
     methods:{
-      handleClick(it,index){
+      handleClick(it,index,flg){
+        if(flg){
+          document.activeElement.blur();      
+          document.activeElement.scrollIntoViewIfNeeded(true);
+          setTimeout(()=>{
+            document.activeElement.scrollIntoViewIfNeeded(true);
+          },300)
+        }
         const arr = this.datas.questionMapping;
         const excluArr = arr.filter(it=>it.exclusionType==1);
         const filArr = arr.filter(it=>it.select==1);
@@ -60,16 +67,17 @@ import {moduleCP} from '@utils/tools';
             mapping.splice(i,1,newItem)
           }
         }
-        // 存值到store
+        // 存值到store  arrFlag:true说明要区分pId
         this.$store.commit('setDatas',{type:this.moduleType,data:newItem,pId:this.datas.id,ppId:this.ppId});
-        this.$store.commit('setText',{type:this.moduleType,text:it.name,textP:(it.description||it.name),pId:it.id});
+        this.$store.commit('setText',{type:this.moduleType,text:it.name,textP:(it.description||it.name),pId:it.id,order:this.order,index:index,arrFlag:true});
         if(it.questionMapping&&it.questionMapping.length>0){//有明细
-          this.$emit("setDetail",{detail:it,ppId:this.ppId})
+          this.$store.commit('setDetail',{detail:it,ppId:this.ppId,moduleType:this.moduleType,order:this.order,index:index})
         }
       },
       deletSymp(e,it,index){
         e.stopPropagation();
         // 删除互斥项(无)不弹窗提醒 7-18
+        this.delIndx = index;
         this.tempItem = it;
         if(it.exclusionType == 1){
           this.comfirnDel();
@@ -115,12 +123,13 @@ import {moduleCP} from '@utils/tools';
         }
         //存值
         this.$store.commit('setDatas',{type:this.moduleType,data:newItem,pId:this.datas.id,ppId:this.ppId});
-        this.$store.commit('delText',{type:this.moduleType,pId:temp.id});
+        this.$store.commit('delText',{type:this.moduleType,pId:temp.id,order:this.order,index:this.delIndx});
         this.cancelDel();
       },
       cancelDel(){
         this.showToast = false;
         this.tempItem = {};
+        this.delIndx = null;
       }
     }
   }
@@ -129,7 +138,6 @@ import {moduleCP} from '@utils/tools';
   .label-wrap{
     font-size: .3rem;
      .symp{
-      // position: relative;
       display: inline-block;
       min-width:1.9rem;
       height: .72rem;
@@ -138,21 +146,16 @@ import {moduleCP} from '@utils/tools';
         vertical-align: top;
       }
       span:first-child{
-        // min-width:1.34rem;
         min-width:1.42rem;
         height: .72rem;
         line-height: .72rem;
         text-align: center;
       }
       img{
-        // width:.56rem;
         width:.48rem;
         height: .70rem;
         vertical-align: top;
         z-index: 22;
-        // position: absolute;
-        // top:0;
-        // right: 0;
       }
     }
     .symp:last-child{
@@ -160,13 +163,10 @@ import {moduleCP} from '@utils/tools';
     }
     .check{
       color: #fff;
-      // background: linear-gradient(-270deg, #4F4FFF, #4F8BFF);
       background: linear-gradient(-270deg, #3638EE, #4E72FF);
       box-shadow: 0 .08rem .16rem 0 rgba(79,129,255,0.40);
-      // padding-right: 0.57rem;
     }
     .exclu{
-      // background:#f0f1f5;
       background:#E3E4E8;
     }
   }

+ 16 - 7
src/common/MultiLineInput.vue

@@ -12,14 +12,16 @@
               v-model="item.value"
               :placeholder="item.placeholder"
               @input="changeVal($event,idx,content.type)" 
-              @blur="blur" 
+              @blur="blur"
+              :maxlength="content.type=='number'?10:''"
               @click="handleClick">
             <input v-show="content.iptLis.length==1" class="contentVal" 
               :type="content.type=='number'?'tel':'text'" 
               :placeholder="content.placeholder" 
-              v-model="item.value" 
+              v-model="item.value"
               @input="changeVal($event,idx,content.type)" 
-              @blur="blur" 
+              @blur="blur"
+              :maxlength="content.type=='number'?10:''"
               @click="handleClick">
             <span v-if="idx == 0&&content.iptLis.length>1">/</span>
           </template>
@@ -52,7 +54,7 @@ export default {
     select:{ //是否选中
       default:false,
       type:Boolean
-    },
+    }
   },
   data(){
     return {
@@ -67,6 +69,7 @@ export default {
   methods:{
     changeVal(e,num,type){
       let tmpTxt = '',arr=this.tmpArr
+      document.activeElement.scrollIntoViewIfNeeded(true);
       if(type == 'number'){
         e.currentTarget.value=e.currentTarget.value.replace(/[^\d]/g,'')
       }
@@ -75,17 +78,22 @@ export default {
       this.txt = tmpTxt
       this.content = getModelExpStr(this.msg,this.txt)
       // this.$emit('changeMultipVal',e.currentTarget.value,num)
-    },
-    blur(){
-      // 如果该项未选中,则不存值
       const select = this.part.select;
       // if(!select){return}
       const newData = Object.assign({},this.part,{value:this.txt,controlType:3,valueP:this.txt});
       this.$emit("updata",newData);
       this.$emit('handleInp',this.txt);
     },
+    blur(){
+      // 如果该项未选中,则不存值
+      document.activeElement.scrollIntoViewIfNeeded(true);
+      setTimeout(()=>{
+        document.activeElement.scrollIntoViewIfNeeded(true);
+      },300)
+    },
     handleClick(e){
       // 点击输入框时不选中该项
+      // document.activeElement.scrollIntoViewIfNeeded(true);
       e.stopPropagation();
     }
   },
@@ -93,6 +101,7 @@ export default {
       part:{//清空时更新
         handler(newVal,oldVal){
           this.txt = newVal.value;
+          this.content = getModelExpStr(this.msg,this.txt)
         },
         deep:true
       }

+ 17 - 11
src/common/OptionInp.vue

@@ -5,7 +5,8 @@
     <div class="inp" @click="preClick">
       <input :type="msg.type=='number'?'tel':'text'" 
               :placeholder="msg.placeholder"
-              
+              :disabled="exclu"
+              :maxlength="msg.type=='number'?10:''"
               :class="[{'exclu':exclu},{'cancel':item.select==0}]"
               v-model="txt"
               @click="handleCli"
@@ -16,7 +17,7 @@
   </div>
 </template>
 <script type="text/javascript">
-import { getExpStr,scrollToV,isIos} from '@utils/tools';
+import { getExpStr} from '@utils/tools';
   export default {
     name:'OptionInp',
     data(){
@@ -37,14 +38,22 @@ import { getExpStr,scrollToV,isIos} from '@utils/tools';
         if(this.msg.type=='number'){//数字键盘
           this.txt = e.target.value=e.target.value.replace(/[^\d]/g,'')
         }
+        
+        const newData = Object.assign({},this.part,{value:this.txt});
+        this.$emit("updata",newData);
+        this.$emit('handleInp',this.txt);
       },
       handleBlur(){
-        // 如果该项未选中,则不存值
-      // 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);
+        document.activeElement.scrollIntoViewIfNeeded(true);
+        setTimeout(()=>{
+          document.activeElement.scrollIntoViewIfNeeded(true);
+        },300)
+          // 如果该项未选中,则不存值
+        // 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);
       },
       preClick(e){
         e.stopPropagation();
@@ -53,9 +62,6 @@ import { getExpStr,scrollToV,isIos} from '@utils/tools';
         // const select = this.item.select;
         if(!this.select){//聚焦时自动选中该项
           this.$emit('handleSelec');
-        }
-        if(!isIos()){
-          scrollToV(e)
         } 
       }
     },

+ 9 - 16
src/common/Radio.vue

@@ -1,18 +1,8 @@
 <template>
   <div class="radio-wrap" v-if="item">
-    <!-- <img :src="datas.url.replace('{imageUrlPrefix}',imgUrl)" v-if="datas.url"> -->
-    <p v-for="(it,index) in datas.questionDetailList" :key="it.id" class="list" @click="handleClick(it,index)">
+    <p v-for="(it,index) in datas.questionDetailList" :key="it.id" class="list" @click="handleClick(it,index,true)">
       <img :src="it.select==1?check:defaultPic">
-      <!-- <span :class="{'check':it.select==1}">{{it.name}}</span> -->
       <span v-if="((it.description||it.name).indexOf('${'))==-1" :class="{'check':it.select==1}">{{it.description||it.name}}</span>
-      <!-- <MultiLineInput v-else 
-          @handleInp="inpVal($event,index)"
-          :msg="it.name" 
-          :part="it" 
-          :border="false" 
-          :inline="true" 
-          :select="it.select==1" 
-          /> -->
       <OptionInp v-else :item="it" @handleInp="inpVal($event,index)" @handleSelec="handleClick(it,index)"/>
     </p>
   </div>
@@ -39,7 +29,14 @@ import OptionInp from '../common/OptionInp.vue';
       this.datas = this.item;
     },
     methods:{
-      handleClick(it,index){
+      handleClick(it,index,flg){
+        if(flg){
+          document.activeElement.blur();      
+          document.activeElement.scrollIntoViewIfNeeded(true);
+          setTimeout(()=>{
+            document.activeElement.scrollIntoViewIfNeeded(true);
+          },300)
+        }
         const list = this.datas;
         let data = list.questionDetailList&&list.questionDetailList.slice(0); //数组深拷贝?
         for(let i=0;i<data.length; i++){
@@ -63,10 +60,6 @@ import OptionInp from '../common/OptionInp.vue';
         this.datas.valueP = temp.valueP;
         this.$emit("updata",this.datas);
       },
-      /*inpSele(index){//输入框反选
-        let detailList = this.datas.questionDetailList;console.log("单选:",index,detailList[index])
-        detailList[index].select = 1;
-      }*/
     },
     watch:{
       item:{

+ 108 - 0
src/common/RadioSelect.vue

@@ -0,0 +1,108 @@
+<template>
+  <div class="radio-wrap radioSelect" v-if="item">
+    <p v-for="(it,index) in datas.questionDetailList" :key="it.id" class="list">
+      <img @click="handleClick(it,index,true,1)" :src="it.select==1?check:defaultPic"> 有&nbsp;&nbsp;&nbsp;&nbsp;
+      <img @click="handleClick(it,index,true,2)" :src="it.select==2?check:defaultPic"> 无
+      <span v-if="((it.description||it.name).indexOf('${'))==-1" :class="{'check':it.select==1||it.select==2}">{{it.description||it.name}}</span>
+    </p>
+  </div>
+</template>
+<script type="text/javascript">
+import icon from '../images/radio-default.png'
+import checkIcon from '../images/radio-check.png'
+import {patt,imageUrlPrefix,concatVal} from '@utils/tools.js'
+import MultiLineInput from '../common/MultiLineInput.vue';
+import OptionInp from '../common/OptionInp.vue';
+  export default{
+    name:'RadioSelect',
+    data(){
+      return{
+        defaultPic:icon,
+        check:checkIcon,
+        datas:{},
+        imgUrl:imageUrlPrefix,
+      }
+    },
+    props:['item'],
+    created(){
+      // this.datas = JSON.parse(JSON.stringify(this.item));
+      this.datas = this.item;
+    },
+    methods:{
+      handleClick(it,index,flg,isHas){
+        if(flg){
+          document.activeElement.blur();      
+          document.activeElement.scrollIntoViewIfNeeded(true);
+          setTimeout(()=>{
+            document.activeElement.scrollIntoViewIfNeeded(true);
+          },300)
+        }
+        const list = this.datas;
+        let data = list.questionDetailList&&list.questionDetailList.slice(0); //数组深拷贝?
+        for(let i=0;i<data.length; i++){
+        //   data[i].select = 0
+          if(i==index){
+            data[i].select = isHas;
+            data[i].controlType = 8;
+          }
+        }
+        let temp = concatVal(data,true);
+
+        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);
+      },
+      /*inpSele(index){//输入框反选
+        let detailList = this.datas.questionDetailList;console.log("单选:",index,detailList[index])
+        detailList[index].select = 1;
+      }*/
+    },
+    watch:{
+      item:{
+        handler(newVal,oldVal){
+          this.datas = JSON.parse(JSON.stringify(newVal));
+        },
+        deep:true
+      }
+    },
+    components:{
+      MultiLineInput,
+      OptionInp
+    }
+  }
+</script>
+<style lang="less" scoped>
+  .radio-wrap{
+    img{
+      width:100%;
+    }
+    .list{
+      color: #7C828E;
+      margin:0 .1rem .1rem 0;
+      padding: .12rem .1rem;
+      white-space: nowrap;
+      -webkit-white-space: nowrap;
+      // -webkit-box-orient: vertical;
+      span {
+          margin-left:1.2rem;
+      }
+      img{
+        width: .38rem;
+        vertical-align: middle;
+      }
+      .check{
+        color: #4F50FF;
+      }
+    }
+  }
+</style>

+ 20 - 2
src/common/Submit.vue

@@ -42,8 +42,25 @@ export default {
   methods: {
     goStart() {
       // this.$store.commit('initAllData') //已在患者页进行初始化
-      // this.$router.push("/")
-      this.$router.replace({path:'/'}) //阻止ios底部的前进后退按钮
+      let scan = localStorage.getItem('scan');
+      let params = JSON.parse(localStorage.getItem('infoParam'));
+      let param = JSON.parse(localStorage.getItem('loginParam'));
+      let data = JSON.parse(localStorage.getItem('loginData'));
+      let tmpArr = localStorage.getItem('recordTime')
+      let tmpTime = tmpArr&&Array.isArray(JSON.parse(tmpArr))?JSON.parse(tmpArr):[];
+      if(!scan){
+        if(data.length>1){
+          this.$router.replace({path:'/department'});
+        }else{
+          this.$router.replace({path:'/home',query:param});
+        }
+        tmpTime.push(param.time)
+        localStorage.setItem('recordTime',JSON.stringify(tmpTime))
+      }else{        
+        this.$router.replace({path:'/home',query:Object.assign({}, params,{scan:true})});
+        tmpTime.push(params.time)
+        localStorage.setItem('recordTime',JSON.stringify(tmpTime))
+      }
     }
   }
 }
@@ -112,6 +129,7 @@ export default {
 .submitFail {
   width: 6rem;
   height: 0.88rem;
+  font-size:.3rem;
   line-height: 0.88rem;
   z-index: 999;
   position: absolute;

+ 91 - 0
src/common/Tiptoast.vue

@@ -0,0 +1,91 @@
+<template>
+    <portal to="notification-outlet">
+      <div class="toast-wrap" v-if="show">
+            <div class="content">
+              <p class="tit" v-show="data.title">{{data.title}}</p>
+              <div class="text">
+                {{data.text}}
+              </div>
+                <img src="../images/icon_close@2x.png"  class="close" @click="handleClose">
+            </div>
+            
+            <div class="mask" @click="handleClose"></div>
+      </div>
+    </portal>
+</template>
+<script type="text/javascript">
+/**
+  提示性弹窗组件
+  接收参数:
+    show-布尔值,是否显示弹窗;
+    data-对象,包含title和text;
+    @close-关闭弹窗的方法(点击关闭按钮或者遮罩都关闭弹窗)
+**/
+  export default {
+    name:'Tiptoast',
+    data(){
+      return {
+        msg:""
+      }
+    },
+    props:{
+      show:{
+        default:false,
+        type:Boolean
+      },
+      data:{
+        default:{
+          title:'',
+          text:''
+        },
+        type:Object
+      },
+    },
+    methods:{
+      handleClose(){
+        this.$emit("close")
+      },
+    },
+  }
+</script>
+<style lang="less" scoped>
+  @import '../less/base.less';
+  .toast-wrap{
+    .content{
+      width: 6rem;
+      background: #fff;
+      z-index: 999;
+      position: fixed;
+      top:50%;
+      left: 50%;
+      transform: translate(-50%,-50%);
+      padding: .5rem .8rem .8rem;
+      box-sizing: border-box;
+      border-radius: .20rem;
+      z-index: 1000;
+      .tit{
+        font-family:PingFangSC;
+        color:#333333;
+        font-size: .32rem;
+        text-align: center;
+        font-weight: 700;
+      }
+      .text{
+        color:#000;
+        padding-top: .3rem;
+        font-size: .3rem;
+      }
+      .close{
+        width:1rem;
+        position: absolute;
+        bottom: -1.5rem;
+        left: 50%;
+        margin-left: -.5rem;
+      }
+    }
+    .mask{
+      .mask;
+      z-index: 999;
+    }
+  }
+</style>

+ 40 - 40
src/common/Toast.vue

@@ -1,18 +1,21 @@
 <template>
-  <div class="toast-wrap" v-if="show">
-    <div class="content">
-      <div class="text" v-html="message||msg">
-        <!-- {{message||msg}} -->
+    <portal to="notification-outlet">
+      <div class="toast-wrap" v-if="show">
+            <div class="content">
+              <div class="text" v-html="message||msg">
+                <!-- {{message||msg}} -->
+              </div>
+              <div class="btn">
+                <span @click="comfirn" class="comf">确定</span>
+                <span @click="cancel" class="canc">取消</span>
+              </div>
+            </div>
+            <div class="mask"></div>
       </div>
-      <div class="btn">
-        <span @click="comfirn">确定</span>
-        <span @click="cancel">取消</span>
-      </div>
-    </div>
-    <div class="mask"></div>
-  </div>
+    </portal>
 </template>
 <script type="text/javascript">
+
 import $ from 'jquery';
   export default {
     name:'Toast',
@@ -22,27 +25,13 @@ import $ from 'jquery';
       }
     },
     props:['message','show','labShow'],
-    /*mounted(){
-      $('body').bind("touchmove",function(e){
-        e.preventDefault();
-      })
-    },
-    beforeDestroy(){
-      $('body').bind("touchmove",function(e){
-        e.next();
-      })
-    },*/
     methods:{
       comfirn(){
         this.$emit("comfirn")
-        // const prehandler = function(e){e.preventDefault();}
-        // document.removeEventListener("touchmove",prehandler,false);
       },
       cancel(){
         this.$emit("cancel")
-        // const prehandler = function(e){e.preventDefault();}
-        // document.removeEventListener("touchmove",prehandler,false);
-      }
+      },
     },
   }
 </script>
@@ -50,8 +39,8 @@ import $ from 'jquery';
   @import '../less/base.less';
   .toast-wrap{
     .content{
-      width: 6rem;
-      height: 3.5rem;
+      width: 6.3rem;
+      height: 3.52rem;
       background: #fff;
       z-index: 999;
       // position: absolute;
@@ -61,36 +50,47 @@ import $ from 'jquery';
       transform: translate(-50%,-50%);
       padding: .5rem;
       box-sizing: border-box;
-      border-radius: .20rem;
+      border-radius: .2rem;
+      z-index: 1000;
       .text{
         color:#000;
         text-align: center;
         height: 1.25rem;
-        overflow-y: auto;
+        // overflow-y: auto;
         padding-top: .2rem;
+        font-size: .3rem;
       }
       .btn{
-        margin-top: .20rem;
+        margin-top: .30rem;
+        padding: 0 .7rem;
         display: flex;
         justify-content: space-between;
         span{
           display: inline-block;
-          width: 2rem;
-          height: .77rem;
-          line-height: .77rem;
+          width: 1.6rem;
+          height: .70rem;
+          line-height: .70rem;
           text-align: center;
-          color: #fff;
+          // color: #fff;
           font-size: .30rem;
-          background: -webkit-gradient(linear, right top, left top, from(#4F8BFF), to(#4F4FFF));
-          background: linear-gradient(right, #4F8BFF, #4F4FFF);
-          box-shadow: 0 .12rem .24rem 0 rgba(79,129,255,0.40);
-          border-radius: .22rem;
+          // background: -webkit-gradient(linear, right top, left top, from(#4F8BFF), to(#4F4FFF));
+          // background: linear-gradient(right, #4F8BFF, #4F4FFF);
+          // box-shadow: 0 .12rem .24rem 0 rgba(79,129,255,0.40);
+          border-radius: .35rem;
+        }
+        .comf{
+          color:#F64B44;
+          border:2px solid rgba(246,75,68,1);
+        }
+        .canc{
+          color: #4F50FF;
+          border:2px solid rgba(79,80,255,1);
         }
       }
     }
     .mask{
       .mask;
-      z-index: 99;
+      z-index: 999;
     }
   }
 </style>

+ 3 - 11
src/common/UploadImg.vue

@@ -3,7 +3,7 @@
     <div class="box">
       <ul class="upload-imgs">
         <li
-          v-if="imgLen<6"
+          v-show="imgLen<6"
           class="uploadBox"
           @click="handleUpload"
         >
@@ -49,7 +49,7 @@ export default {
       flag:true //图片处理完成后才可以再次点击上传
     }
   },
-  props: ['item', 'moduleType', 'imgList'],//moduleType-哪个模块下上传的图
+  props: ['item', 'moduleType', 'imgList'],
   mounted() {
     this.imgs = this.imgList; //回读
     this.imgLen = Object.keys(this.imgList).length;
@@ -64,13 +64,6 @@ export default {
   },
   methods: {
     handleUpload() {
-      // navigator.getUserMedia({video: true,audio:true}, function onSuccess(stream) {
-      /*navigator.getUserMedia({video: true}, function onSuccess(stream) {
-        const inp = this.$refs.inp;
-        inp.click();
-      }, function onError(error) {
-        alert("请开启权限设置")
-      })*/
       const inp = this.$refs.inp;
       if(this.flag){
         inp.click();
@@ -97,12 +90,11 @@ export default {
         var uploadSrc;
         var uploadFile;
         if (fileSize > maxSize) { // 如果图片大小大于4m,进行压缩
-          // console.log(maxSize,fileSize, maxSize/fileSize );
           uploadSrc = canvas.toDataURL(file.type, maxSize / fileSize);
           uploadFile = that.dataURLtoFile(uploadSrc, file.name.split('.')[0]); // 转成file文件
           // uploadFile = that.convertBase64UrlToBlob(uploadSrc); // 转成blob
         } else {
-          uploadSrc = image.src; //canvas.toDataURL(file.type,0.5);
+          uploadSrc = image.src; 
           uploadFile = file;
         }
 

+ 78 - 58
src/components/AddContent.vue

@@ -1,49 +1,51 @@
 <template>
-  <div class="symp-wrap">
-    <div class="choose">
-      <ul class="addPart">
-        <li v-for="(item,idx) in dataTrd">
-          <p class="question">{{idx+1 + '. ' +(item.description||item.name)}}</p>
-          <img class="questionImg" :src="item.url.replace('{imageUrlPrefix}',imgUrl)" v-if="item.url">
-          <Radio v-if="item.controlType==1" 
-            :item="item"
-            :key="item.id"
-            @updata="updataData($event,idx,item)"/>
-          <CheckBox v-if="item.controlType==2" 
-            :item="item"
-            :key="item.id"
-            @updata="updataData($event,idx,item)"/>
-          <ComTextArea
-            v-if="item.controlType == 5"
-            :item="item"
-            @updata="updataData($event,idx,item)"
-            @changeAreaVal="changeAreaVal($event,idx)"
-          ></ComTextArea>
-          <Input v-if="item.controlType==6 || item.controlType==7"
-            :item="item"
-            :key="item.id"
-            @updata="updataData($event,idx,item)"/>
-          <template
-            v-if="item.controlType == 3"
-            v-for="(part,index) in item.questionDetailList"
-          >
-            <MultiLineInput
+  <div class="symp-wrap addper">
+    <div class="content">
+        <div class="choose">
+        <ul class="addPart">
+          <li v-for="(item,idx) in dataTrd">
+            <p class="question">{{idx+1 + '. ' +(item.description||item.name)}}</p>
+            <img class="questionImg" :src="item.url.replace('{imageUrlPrefix}',imgUrl)" v-if="item.url">
+            <Radio v-if="item.controlType==1" 
+              :item="item"
+              :key="item.id"
+              @updata="updataData($event,idx,item)"/>
+            <CheckBox v-if="item.controlType==2" 
+              :item="item"
+              :key="item.id"
+              @updata="updataData($event,idx,item)"/>
+            <ComTextArea
+              v-if="item.controlType == 5"
+              :item="item"
+              @updata="updataData($event,idx,item)"
+              @changeAreaVal="changeAreaVal($event,idx)"
+            ></ComTextArea>
+            <Input v-if="item.controlType==6 || item.controlType==7"
+              :item="item"
+              :key="item.id"
+              @updata="updataData($event,idx,item)"/>
+            <template
               v-if="item.controlType == 3"
-              :msg="part.description||part.name"
-              :part="part"
-              @updata="updataData($event,index,item)"
-            ></MultiLineInput>
-          </template>
-        </li>
-      </ul>
-      <div class="result" v-if="allStr">
-        <p class="title">{{allMoudles.name}}</p>
-        <p>{{allStr}}</p>
-      </div>
-      <div class="thanks">
-        <p>感谢您的回答,您的病历已经自动生成。</p>
-        <p>您可以点击预览并提交病历按钮预览病历。</p>
-        <p>如果没有需要修改的内容,请点击提交,医生便能看到您的病历。</p>
+              v-for="(part,index) in item.questionDetailList"
+            >
+              <MultiLineInput
+                v-if="item.controlType == 3"
+                :msg="part.description||part.name"
+                :part="part"
+                @updata="updataData($event,index,item)"
+              ></MultiLineInput>
+            </template>
+          </li>
+        </ul>
+        <div class="result" v-if="allStr">
+          <p class="title">{{allMoudles.name}}</p>
+          <p>{{allStr}}</p>
+        </div>
+        <div class="thanks">
+          <p>感谢您的回答,您的病历已经自动生成。</p>
+          <p>您可以点击预览并提交病历按钮预览病历。</p>
+          <p>如果没有需要修改的内容,请点击提交,医生便能看到您的病历。</p>
+        </div>
       </div>
     </div>
     <div class="foot">
@@ -58,7 +60,8 @@ import MultiLineInput from '../common/MultiLineInput.vue';
 import Input from '../common/Input.vue';
 import Radio from '../common/Radio.vue';
 import CheckBox from '../common/CheckBox.vue';
-import {imageUrlPrefix,getAllStr} from '@utils/tools.js';
+import {imageUrlPrefix,getAllStr,setScroll} from '@utils/tools.js';
+import BScroll from 'better-scroll';
 export default {
   name: 'AddContent',
   props: ['allMoudles','preName'],
@@ -67,13 +70,25 @@ export default {
       imgUrl:imageUrlPrefix,
       dataTrd: [],
       val: '',
-      allStr:''
+      allStr:'',
+      scroll:null
     }
   },
-  mounted() {
+  created(){
     this.dataTrd = this.allMoudles && this.allMoudles.moduleDetailDTOList
+    this.allStr = this.$store.state.addContent.txt
+  },
+  mounted() {
+    this.$nextTick(()=>{
+      let scroll = setScroll(BScroll,true,'.addper')
+      this.scroll = scroll
+      scroll.on('scroll', this.onScroll)
+    })
   },
   methods: {
+    onScroll() {
+      document.activeElement.scrollIntoViewIfNeeded(true);        
+    },
     back() {
       this.$emit("back");
     },
@@ -97,22 +112,23 @@ export default {
       let mapping = this.dataTrd;
       let allData = this.$store.state.allMoudles;
       let tmpTrdData = allData.filter((item) => item.type == 52);
-
-      // console.log(data,mapping,this.$store.state,999999)
       if(data.controlType == 3){//多行输入,多了一层需单独处理
         let tmpLis = item.questionDetailList;
         tmpLis.splice(idx,1,data);
         this.allStr=getAllStr({data:tmpTrdData&&tmpTrdData[0].moduleDetailDTOList,type:this.allMoudles&&this.allMoudles.type}).allStr;
-        return;
-      }
-      for(let i in mapping){
-        if(mapping[i].id==data.id){
-          mapping.splice(i,1,data)
+      }else{
+        for(let i in mapping){
+          if(mapping[i].id==data.id){
+            mapping.splice(i,1,data)
+          }
         }
+        this.allStr=getAllStr({data:tmpTrdData&&tmpTrdData[0].moduleDetailDTOList,type:this.allMoudles&&this.allMoudles.type}).allStr
+        this.$store.commit('setDataAll',{data:data,idx:idx});
       }
-      // console.log(allData.filter((item) => item.type == 52))
-      this.allStr=getAllStr({data:tmpTrdData&&tmpTrdData[0].moduleDetailDTOList,type:this.allMoudles&&this.allMoudles.type}).allStr
-      this.$store.commit('setDataAll',{data:data,idx:idx});
+      this.$store.commit('setText',{data:tmpTrdData&&tmpTrdData[0].moduleDetailDTOList,type:this.allMoudles&&this.allMoudles.type});
+      this.$nextTick(()=>{
+        this.scroll.refresh()
+      })
     },
   },
   components: {
@@ -131,7 +147,11 @@ export default {
 }
 .symp-wrap {
   font-size: 0.3rem;
-  padding-right: .3rem;
+  overflow: hidden;
+  .content {
+    // padding-right: .3rem;
+  }
+  .btscroll;  
   h3 {
     color: #000;
     margin-bottom: 0.36rem;

+ 124 - 0
src/components/Department.vue

@@ -0,0 +1,124 @@
+<template>
+    <div class="department">
+        <div class="departmentView">
+            <div class="content">
+                <div class="list" v-for="(item,index) in departmentLis" @click="goStart(index,item.recordTime)" :key="item.recordTime">
+                    <div class="top">
+                        <p>挂号科室:{{item.hospitalDeptName}} <img src="../images/right.png" alt=""></p>
+                    </div>
+                    <div class="main">
+                        <p>预约时间:{{item.recordTime}}</p>
+                        <p>病历号:{{item.recordId}}</p>
+                        <p>挂号信息:{{item.registerNum}}</p>
+                        <p v-if="item.dided">您已完成过一次预问诊,是否再次录入</p>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+  import {setScroll,compare} from '@utils/tools.js';
+  import BScroll from 'better-scroll';
+    export default {
+        name: "Department",
+        data(){
+            return {
+                scroll:null,
+                departmentLis:[]
+            }
+        },
+        created(){
+            let tmpList = JSON.parse(localStorage.getItem('loginData'))
+            let tmpTime = JSON.parse(localStorage.getItem('recordTime'))
+            let sortArr = tmpList.sort(compare("recordTime"));
+            if(tmpTime){
+                for(let j = 0;j < tmpTime.length;j++){
+                    for(let i = 0;i < sortArr.length;i++){
+                        if(tmpTime[j] == (new Date((sortArr[i].recordTime).replace(/\-/g, "/"))).getTime()){
+                            sortArr[i].dided = 1
+                        }
+                    }
+                }
+            }
+            this.departmentLis = sortArr
+        },
+        mounted(){
+            this.$nextTick(()=>{
+                let scroll = setScroll(BScroll,true,'.departmentView')
+                this.scroll = scroll
+            })
+        },
+        methods:{
+            goStart(num,time){
+                let msg = this.departmentLis[num]
+                let params = {
+                    hospitalCode:msg.hospitalCode,
+                    hospitalDeptCode:msg.hospitalDeptCode,
+                    doctorCode:msg.doctorCode,
+                    patientCode:msg.patientCode,
+                    recordId:msg.recordId,
+                    time:(new Date(time.replace(/\-/g, "/"))).getTime()
+                }
+
+                localStorage.setItem('loginParam',JSON.stringify(params))//保存登陆信息,扫码进入徐删除该参数
+
+                this.$router.push({
+                    path:'/home',
+                    query:params
+                })
+            }
+        }
+    }
+</script>
+<style lang="less" scoped>
+    .department {
+        font-size: .3rem;
+        padding: .3rem 0 1rem 0;
+        .departmentView {
+            position: absolute;
+            width: 100%;
+            height: 100%;
+            overflow: hidden;
+            padding: 0 .3rem 1rem .3rem;
+            box-sizing: border-box;
+            .content {
+                padding-bottom: 1rem;
+            }
+            .list {
+                height:3.5rem;
+                background:rgba(255,255,255,1);
+                box-shadow:0px 3px 15px 0px rgba(217,217,217,0.5);
+                border-radius:.1rem;
+                overflow: hidden;
+                margin-bottom: .3rem;
+            }
+            .top {
+                height: 1rem;
+                line-height: 1rem;
+                background: url('../images/bg-title.png') 100% 100% no-repeat;
+                padding: 0 .3rem;
+                box-sizing: border-box;
+                p {
+                    position: relative;
+                    color: #fff;
+                    img {
+                        position: absolute;
+                        right: 0;
+                        top: 50%;
+                        width: .4rem;
+                        height: .4rem;
+                        margin-top: -0.2rem;
+                    }
+                }
+            }
+            .main {
+                font-size: .28rem;
+                padding: .3rem;
+                p {
+                    line-height: .5rem;
+                }
+            }
+        }
+    }
+</style>

+ 68 - 10
src/components/Detail.vue

@@ -2,12 +2,16 @@
   <div class="detail-wrap">
     <!-- <div v-for="(item,index) in datas"> -->
     <div v-for="(item,index) in checkDatas.questionMapping">
-      <p class="quest">{{index + 1 +'.' + (item.description || item.name)}}</p>
+      <p class="quest"><span v-show="item.required==1" style="color: red;">*</span>{{index + 1 +'.' + (item.description || item.name)}}</p>
       <img class="questionImg" :src="item.url.replace('{imageUrlPrefix}',imgUrl)" v-if="item.url">
       <Radio v-if="item.controlType==1" 
             :item="item"
             :key="item.id"
             @updata="updataData"/>
+      <RadioSelect v-if="item.controlType==8" 
+            :item="item"
+            :key="item.id"
+            @updata="updataData"/>
       <CheckBox v-if="item.controlType==2" 
             :item="item"
             :key="item.id"
@@ -40,6 +44,7 @@ import Radio from '../common/Radio.vue';
 import CheckBox from '../common/CheckBox.vue';
 import Input from '../common/Input.vue';
 import ComTextArea from '../common/ComTextArea.vue';
+import RadioSelect from '../common/RadioSelect.vue';
 import MultiLineInput from '../common/MultiLineInput.vue';
 import {patt,trimDots,imageUrlPrefix} from '@utils/tools.js'
 // 将获取到的数据源转换成私有数据,处理选择事件。点击完成后统一存到store中,便于回读
@@ -48,11 +53,10 @@ import {patt,trimDots,imageUrlPrefix} from '@utils/tools.js'
     data(){
       return{
         checkDatas:{},
-        finished:false,
         imgUrl:imageUrlPrefix,
       }
     },
-    props:['datas','type','ppId'],
+    props:['datas','data'],
     created(){
       this.checkDatas = JSON.parse(JSON.stringify(this.datas));
     },
@@ -61,7 +65,8 @@ import {patt,trimDots,imageUrlPrefix} from '@utils/tools.js'
       CheckBox,
       Input,
       ComTextArea,
-      MultiLineInput
+      MultiLineInput,
+      RadioSelect
     },
     methods:{
       updataData(data,item){
@@ -106,19 +111,48 @@ import {patt,trimDots,imageUrlPrefix} from '@utils/tools.js'
             this.$emit('check',false)
           }
         }
+        // 更新完成样式
+        let checkReq = this.checkReq();
+        if(checkReq){
+          this.$emit('checkReq',true)
+        }else{
+          this.$emit('checkReq',false)
+        }
       },
       saveData(){//存值
-        this.finished = true;
         this.checkDatas = Object.assign({},this.checkDatas,{select:1});
         const datas = this.checkDatas.questionMapping;
+        const id = this.checkDatas.id;
+        let chooseSymp = this.$store.state.symptom.choose;
+        
         let text = ""; //医生
         let textP = "";//患者
+        let special = ""; //拼到主诉
+        let specialP = "";
         for(let i in datas){
+          // 校验必填项
+         /* if(datas[i].required==1 && !datas[i].value){
+            alert("请先将必填项填完");
+            return
+          }*/
+          // 拼到主诉
+          if(datas[i].specFlag==1 && datas[i].value){
+            special += datas[i].value;
+            specialP += datas[i].valueP;
+          }
           if(datas[i].value){
             text += datas[i].value+',';
             textP += datas[i].valueP+',';
           }
         }
+        if(special){//拼接到主诉的内容存到chooseSymp
+          for(let k in chooseSymp){
+            if(id == (chooseSymp[k].id ||chooseSymp[k].questionId)){
+              chooseSymp[k].special = special;
+              chooseSymp[k].specialP = specialP;
+            }
+          }
+        }
         
         let msg = this.checkDatas.name+ ',' + text;
         let msgP = (this.checkDatas.description || this.checkDatas.name)+ ',' + textP;
@@ -131,15 +165,21 @@ import {patt,trimDots,imageUrlPrefix} from '@utils/tools.js'
           newMsg = msg;
           newMsgP = msgP;
         }
-        this.$store.commit('setDatas',{data:this.checkDatas,pId:this.checkDatas.id,type:this.type,ppId:this.ppId});
+        this.$store.commit('setDatas',{data:this.checkDatas,pId:id,type:this.data.moduleType,ppId:this.data.ppId});
         // flag是区分点开已选症状 未点完成
-        this.$store.commit('setText',{text:trimDots(newMsg),textP:trimDots(newMsgP),pId:this.checkDatas.id,type:this.type,flag:true});
+        this.$store.commit('setText',{text:trimDots(newMsg),textP:trimDots(newMsgP),pId:id,type:this.data.moduleType,flag:true,order:this.data.order,arrFlag:true,index:this.data.index});
+        // 关闭详情
+        this.$store.commit('setDetail',{detail:{}})
       },
       clearData(){//清空
         const datas = this.checkDatas.questionMapping;
+        let reqFlag = false;//必填项标识
         for(let i in datas){
           datas[i].value = "";
           datas[i].valueP = "";
+          if(datas[i].required==1){
+            reqFlag = true;
+          }
           let detaiList = datas[i].questionDetailList;
           if(detaiList.length>0){
             for(let k in detaiList){
@@ -151,11 +191,20 @@ import {patt,trimDots,imageUrlPrefix} from '@utils/tools.js'
             }
           }
         }
+
         this.checkDatas = Object.assign({},this.checkDatas,{questionMapping:datas});
+        // 已有选中内容重新进来,点清空时并非真的清空
+        if(this.checkDatas.select ==1){return}
         let msg = this.checkDatas.name;
         let msgP = (this.checkDatas.description||this.checkDatas.name);
-        this.$store.commit('setDatas',{data:this.checkDatas,pId:this.checkDatas.id,type:this.type,ppId:this.ppId});
-        this.$store.commit('setText',{text:msg,textP:msgP,pId:this.checkDatas.id,type:this.type,flag:true});
+        // 没有点过完成直接选择然后清空,外层不会处于选中状态,故没有必填项时添加{select:1}
+        if(reqFlag){
+          this.$store.commit('setDatas',{data:this.checkDatas,pId:this.checkDatas.id,type:this.data.moduleType,ppId:this.data.ppId});
+        }else{
+          this.$store.commit('setDatas',{data:Object.assign({},this.checkDatas,{select:1}),pId:this.checkDatas.id,type:this.data.moduleType,ppId:this.data.ppId});
+        }
+        
+        this.$store.commit('setText',{text:msg,textP:msgP,pId:this.checkDatas.id,type:this.data.moduleType,flag:true,order:this.data.order,arrFlag:true,index:this.data.index});
       },
       check(){// 校验是否有已填项
         const datas = this.checkDatas.questionMapping;
@@ -178,6 +227,15 @@ import {patt,trimDots,imageUrlPrefix} from '@utils/tools.js'
           return true;
         }
         return false;
+      },
+      checkReq(){// 校验必填项
+        const datas = this.checkDatas.questionMapping;
+        for(let k in datas){
+          if(datas[k].required==1 && !datas[k].value){
+            return false;
+          }
+        }
+        return true;
       }
     },
   }
@@ -185,7 +243,7 @@ import {patt,trimDots,imageUrlPrefix} from '@utils/tools.js'
 <style lang="less" scoped>
   .detail-wrap{
     // padding: .3rem .5rem 1.2rem .6rem;
-    padding: .3rem .5rem 2rem .6rem;
+    padding: .3rem .5rem 1rem .6rem;
     font-size: .3rem;
     .quest{
       color:#000;

+ 139 - 71
src/components/DetailBox.vue

@@ -1,79 +1,115 @@
 <template>
-  <div class="detailBox-wrap" ref="detailBox">
-    <div class="head">
-      <span class="icon" @click="close">
-        <img src="../images/small-close.png">
-      </span>
-      <span class="name">{{(privateData.description ||privateData.name)+'详情'}}</span>
-      <span @click="handleClear" :class="{'check':checkF}">清空</span>
-      <i>{{tips}}</i>
+  <portal to="notification-detail">
+    <div class="detailBoxMask"></div>
+    <div class="detailBox-wrap viewPrew">
+      <div class="content detailBoxMain" ref="detailBox">
+        <div class="tmpDom"></div>
+        <div class="main">
+          <Detail :datas="privateData" 
+                  ref="detail"
+                  :data="data"
+                  @check="changeCheck($event)"
+                  @checkReq="changeFins($event)"/>
+        </div>
+        <!-- <div class="foot" @click="complete">完成</div> -->
+      </div>
+      <div class="head">
+        <span class="icon" @click="close">
+          <img src="../images/small-close.png">
+        </span>
+        <span class="name">{{(privateData.description ||privateData.name)+'详情'}}</span>
+        <span @click="handleClear" :class="{'check':checkF}">清空</span>
+        <i>{{tips}}</i>
+      </div>
     </div>
-    <div class="main">
-      <Detail :datas="privateData" 
-              ref="detail"
-              :type="moduleType" 
-              :ppId="ppId"
-              @check="changeCheck($event)"/>
-    </div>
-    <!-- <div class="foot" @click="complete">完成</div> -->
-    <div :class="['foot',{'noCheck':!checkF}]" @click="complete">完成</div>
+    <!-- <div :class="['foot',{'noCheck':!checkF}]" @click="complete">完成</div> -->
+    <div :class="['foot',{'noCheck':!reqFinish}]" @click="complete">完成</div>
     <Toast :message="clearTxt" 
           :show="showToast"
           @comfirn="comfirnDel" 
           @cancel="cancelDel"/>
-  </div>
+  </portal>
 </template>
 <script type="text/javascript">
   import Detail from './Detail.vue';
   import Toast from '../common/Toast.vue';
-  import {fixedKeyboard} from '@utils/tools.js';
+  import {fixedKeyboard,setScroll,moduleCP} from '@utils/tools.js';
+  import BScroll from 'better-scroll';
   import $ from 'jquery';
   export default {
     name:'DetailBox', //点开详情的盒子
     data(){
+      const {detailInfo,detailShow} = this.$store.state;
       return{
         msg:"胸痛详情",
-        privateData:{},
+        data:detailInfo,
+        privateData:detailInfo.detail||{},
         compFlag:false,
         clearTxt:"是否清空当前已选内容?",
         showToast:false,
         tips:"(请完成病情预问诊可让医生提前了解病情)",
-        checkF:false //详情页有无已选项标识
+        checkF:false, //详情页有无已选项标识
+        show:detailShow,
+        reqFinish:false
       }
     },
-    created(){
-      this.privateData = this.data;
-    },
     mounted(){
-      const box = this.$refs.detailBox;
-      const height = document.documentElement.clientHeight;
-      box.style.height = height - 45 + 'px'; 
-      $('body').css({'height':height+'px','overflow-y':'hidden'})
-      // 校验是否有已填项,有--弹窗;无--return
-      let hasCheck = this.$refs.detail.check();
-      if(hasCheck){
-        this.checkF = true;
-      }
-      fixedKeyboard();//给Window绑定事件
-    },
-    beforeDestroy(){//给Window解绑事件
-      $(window).off("resize");
-      $(window).off("click");
-      $('body').css({'height':'100%','overflow-y':'auto'})
+      this.$nextTick(()=>{
+        // 校验是否有已填项,有--弹窗;无--return
+        let hasCheck = this.$refs.detail.check();
+        let checkReq = this.$refs.detail.checkReq();
+        if(hasCheck){
+          this.checkF = true;
+        }
+        if(checkReq && hasCheck){
+          this.reqFinish = true;
+        }
+        setTimeout(() => {
+          let scroll = setScroll(BScroll,true,'.viewPrew')
+          this.scroll = scroll
+          scroll.on('scroll', this.onScroll)
+        }, 400);
+      })
     },
     methods:{
+      onScroll() {
+        document.activeElement.scrollIntoViewIfNeeded(true);        
+      },
       close(){
-        this.$emit("close");
+        // 有必填项但没值则将choose移除 8-19
+        // 没点过完成,点关闭时校验是否有必填项--有直接移除
+        const type = this.data.moduleType;
+        const select = this.privateData.select;
+        if(type == moduleCP['symp'] && !select){//只处理主诉症状
+          const list = this.privateData.questionMapping;
+          if(list){
+            for(let i in list){
+              // if(list[i].required==1 && !list[i].value){
+              if(list[i].required==1){
+                this.$store.commit('delChoose', {id: this.privateData.id })
+                this.$store.commit('delText', { type: moduleCP['symp'], pId: this.privateData.id })
+              }
+            }
+          }
+        }
+        
+        this.$store.commit('setDetail',{detail:{}})
       },
-      complete(){//有选中内容才可以点完成#1919
-        if(this.checkF){
+      complete(){
+      //有选中内容才可以点完成#1919
+        // if(this.checkF){
+      //必填项都填完了才可以点完成
+        if(this.reqFinish){
           this.$refs.detail.saveData();
-          this.$emit("pComplete");
+          this.$store.commit('setSearchShow', false);
         }
       },
-      changeCheck(flag){
+      changeCheck(flag){//是否有选中项
         this.checkF = flag;
       },
+      changeFins(flag){//必填项是否都填了
+        this.reqFinish = flag;
+      },
       handleClear(){//清空
         // 校验是否有已填项,有--弹窗;无--return
         if(this.checkF){
@@ -87,43 +123,76 @@
         this.$refs.detail.clearData();
         this.showToast = false;
         this.checkF = false;
+        this.reqFinish = false;
         // 让detail组件更新
-        // this.privateData = JSON.parse(JSON.stringify(this.data));
-        this.$emit('reload',this.data.id);
+        const type = this.data.moduleType;
+        if(type == moduleCP['symp']){ //症状情况单独处理
+          const id = this.privateData.id;
+          const read = this.$store.state.symptom.datas;
+          const data = read[id];
+          this.$store.commit('setDetail',{detail:data,ppId:null,moduleType:moduleCP['symp']})
+        }
+        
       }
     },
-    props:['data','moduleType','ppId'],
     components:{
       Detail,
       Toast
-    }
+    },
+    computed: {
+      getStoreItem () {
+        return this.$store.state.detailInfo
+      }
+    },
+    watch: {
+      getStoreItem:{
+        handler(newVal){
+          this.data = newVal;
+          this.privateData = newVal.detail||{};
+        },
+        deep:true
+      }
+    },
   }
 </script>
 <style lang="less" scoped>
 @import '../less/base.less';
+  .detailBoxMask {
+    .mask;
+    z-index: 110;
+  }
+  .tmpDom {
+    height: 1rem;
+  }
   .detailBox-wrap{
     width: 100%;
     // overflow-y: auto;
     position: fixed;
     // bottom: 0; //iPhone6plus键盘收起会跳转
     top:45px;
+    bottom: 0;
     left: 0;
     z-index: 666;
     background: #fff;
     border-radius: .08rem .08rem 0 0;
     font-size: .3rem;
-    // animation: wave .4s ease-in;
     animation: wave .4s linear;
+    height: 100%;
+    overflow: hidden;
     .head{
-      // height: .88rem;
       height: 1rem; //增加了提示
       line-height: .88rem;
-      display: flex;
+      display: flex; //有清空时
       justify-content: space-between;
       border-bottom: 1px solid #E6E7EF;
       padding: 0 .4rem 0 .32rem;
       font-size: .28rem;
       color: #7C828E;
+      position: fixed;
+      width: 100%;
+      background-color: #fff;
+      top: 45px;
+      box-sizing: border-box;
       i{
         position: absolute;
         top:0.64rem;
@@ -152,28 +221,27 @@
     .main{
       height: 100%;
       width:100%;
-      overflow-y: auto;
-      // -webkit-overflow-scrolling : touch;//解决滑动卡顿问题
-    }
-    .foot{
-      .footer;
-      animation-delay:.6s;
-      animation: foo .4s linear;
-      /* width:100%;
-      height: .88rem;
-      line-height: .88rem;
-      text-align: center;
-      color:#fff;
-      font-size: .32rem;
-      background: linear-gradient(-270deg, #4F4FFF,#4F8BFF); */
-    }
-    .check{
-      color: #1A1A1A;
-    }
-    .noCheck{
-      background: #CACCFF !important;
+      padding-bottom: 1rem;
     }
   }
+  .foot{
+    .footer;
+    animation-delay:.6s;
+    animation: foo .4s linear;
+    /* width:100%;
+    height: .88rem;
+    line-height: .88rem;
+    text-align: center;
+    color:#fff;
+    font-size: .32rem;
+    background: linear-gradient(-270deg, #4F4FFF,#4F8BFF); */
+  }
+  .check{
+    color: #1A1A1A;
+  }
+  .noCheck{
+    background: #CACCFF !important;
+  }
   @keyframes wave {
     0%   {top:100% ;}
     25% {top: 75%;}

+ 73 - 69
src/components/DiagTreat.vue

@@ -1,40 +1,39 @@
 <template>
-  <div class="treat-wrap">
-    <div v-for="(it,i) in dtoList" 
-        v-if="dtoList"
-        :key="it.id"
-        class="label">
-      <p class="quest">{{i + 1 +'.' + (it.description||it.name)}}</p>
-      <img class="questionImg" :src="it.url.replace('{imageUrlPrefix}',imgUrl)" v-if="it.url">
+  <div class="treat-wrap treatper">
+    <div class="content">
+      <div v-for="(it,i) in dtoList" 
+          v-if="dtoList"
+          :key="it.id"
+          class="label">
+        <p class="quest">{{i + 1 +'.' + (it.description||it.name)}}</p>
+        <img class="questionImg" :src="it.url.replace('{imageUrlPrefix}',imgUrl)" v-if="it.url">
         <Label v-if="it.controlType==0" 
               :item="it" 
-              :indx="i" 
               :ppId="it.id"
-              :moduleType="datas.type"
-              @setDetail="setDetail"/>
+              :order="i"
+              :moduleType="datas.type"/>
         <!-- 上传图片 -->
         <UploadImg v-if="it.controlType==4" 
             :item="it" 
             :moduleType="datas.type"
-            :imgList="imgs"
-            />
+            :imgList="imgs"/>
         <!-- 输入框 -->
         <Input v-if="it.controlType==6 || it.controlType==7"
             :item="it"
             :key="it.id"
-            @updata="updataData($event,it.id)"/>
+            @updata="updataData($event,it.id,i)"/>
         <!-- 文本域 -->
         <ComTextArea v-if="it.controlType == 5"
             :item="it"
-            @updata="updataData($event,it.id)"/>
+            @updata="updataData($event,it.id,i)"/>
         <Radio v-if="it.controlType==1" 
             :item="it"
             :key="it.id"
-            @updata="updataData($event,it.id)"/>
+            @updata="updataData($event,it.id,i)"/>
         <CheckBox v-if="it.controlType==2" 
             :item="it"
             :key="it.id"
-            @updata="updataData($event,it.id)"/>
+            @updata="updataData($event,it.id,i)"/>
         <!-- 多行输入-->
         <template
             v-if="it.controlType == 3"
@@ -43,14 +42,14 @@
             <MultiLineInput
               :msg="part.name"
               :part="part"
-              @updata="updataData($event,it.id,index)"
+              @updata="updataData($event,it.id,i,index)"
             ></MultiLineInput>
         </template>
-    </div>
-    <div class="result" v-if="checkText.length>0">
-      <p class="title">{{datas.name}}</p>
-      <!-- <p v-for="(v,i) in checkText">{{v.text}}</p> -->
-      <p>{{getText()}}</p>
+      </div>
+      <div class="result" v-if="getText()">
+        <p class="title">{{datas.name}}</p>
+        <p>{{getText()}}</p>
+      </div>
     </div>
 
     <div class="foot" v-if="modluesLen==2">
@@ -61,14 +60,6 @@
       <span class="back" @click="beBack">{{'返回'+ preName}}</span>
       <span class="next" @click="toNext">{{'进入'+ nextName}}</span>
     </div>
-    <div class="detail" v-if="show">
-    <DetailBox @close="closeDetal" 
-            :data="labelDetail" 
-            :moduleType="datas.type"
-            :ppId="ppId"
-            v-if="labelDetail.questionMapping&&labelDetail.questionMapping.length>0"
-            @pComplete="complete"/>
-    </div>
   </div>
 </template>
 <script type="text/javascript">
@@ -77,9 +68,10 @@
   import DetailBox from './DetailBox.vue';
   import Input from '../common/Input.vue';
   import ComTextArea from '../common/ComTextArea.vue';
-  import {moduleCP,patt,imageUrlPrefix} from '@utils/tools';
+  import {moduleCP,patt,imageUrlPrefix,setScroll,trimDots} from '@utils/tools';
   import Radio from '../common/Radio.vue';
   import CheckBox from '../common/CheckBox.vue';
+  import BScroll from 'better-scroll';
   import MultiLineInput from '../common/MultiLineInput.vue';
   export default {
     name:'DiagTreat',
@@ -95,10 +87,21 @@
         show:false,
         ppId:null,
         imgUrl:imageUrlPrefix,
+        scroll:null
       }
     },
     props:['datas','preName','nextName','modluesLen'],
+    mounted(){
+      this.$nextTick(()=>{
+        let scroll = setScroll(BScroll,true,'.treatper')
+        this.scroll = scroll
+        scroll.on('scroll', this.onScroll)
+      })
+    },
     methods:{
+      onScroll() {
+        document.activeElement.scrollIntoViewIfNeeded(true);        
+      },
       beBack(){
         this.$emit('back');
       },
@@ -109,47 +112,51 @@
           this.$emit('next');
         }
       },
-      setDetail(obj){
-        this.labelDetail = obj.detail;
-        this.ppId = obj.ppId;
-        this.show = true;
-      },
-      complete(){
-        this.show = false;
-        this.labelDetail = {};
-        this.ppId = null;
-        // 处理明细选中的值
-      },
-      closeDetal(){
-        this.show = false;
-        this.labelDetail = {};
-        this.ppId = null;
-      },
       getText(){
         let textArr = this.checkText;
         let msg = "";
         for(let k in textArr){
-          if(textArr[k].textP){
-            msg += textArr[k].textP + ';'
+          if(textArr[k] && Array.isArray(textArr[k])){
+            let temp = textArr[k];
+            for(let j in temp){
+              if(temp[j] && temp[j].textP){
+                msg += temp[j].textP + ','
+              }
+            }
+          }else if(textArr[k]&&textArr[k].textP){
+            msg += textArr[k].textP + ','
           }
-        }          
-        return msg;
+        }    
+        return trimDots(msg.substring(0,msg.length-1));
       },
-      updataData(data,id,index){//输入框存值
+      updataData(data,id,order,index){//输入框存值
         let list = this.dtoList;
+        let value = "";
+        let valueP = "";
         for(let i in list){
-          // if(list[i].id==data.id){
           if(list[i].id==id){
             if(list[i].controlType == 3){//多行输入
               let detailList = list[i].questionDetailList;
               detailList.splice(index,1,data);
+              let temVal = "";
+              for(let k in detailList){
+                if(detailList[k].value){
+                  temVal += detailList[k].value + ','
+                }
+              }
+              value = valueP = temVal?temVal.substring(0,temVal.length-1):'';
             }else{
-              list.splice(i,1,data)
+              list.splice(i,1,data);
+              value = data.value;
+              valueP = data.valueP;
             }
           }
         }
         this.$store.commit('setDatas',{type:moduleCP['diagT'],data:data,pId:data.id,ppId:id});
-        this.$store.commit('setText',{type:moduleCP['diagT'],text:data.value.replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,''),textP:data.valueP.replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,''),pId:data.id,flag:true}); 
+        this.$store.commit('setText',{type:moduleCP['diagT'],text:value.replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,''),textP:valueP.replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,''),pId:data.id,flag:true,order:order}); 
+        this.$nextTick(()=>{
+          this.scroll.refresh()
+        })
       }
     },
     components:{
@@ -162,19 +169,26 @@
       CheckBox,
       MultiLineInput
     },
-    /*watch:{
-      dtoList:{
-        handler(newVal,oldVal){
+    computed:{
+      getItem(){
+        return this.$store.state.diagnose.text;
+      }
+    },
+    watch:{
+      getItem:{
+        handler(value){
+          this.checkText = value;
         },
         deep:true
       }
-    },*/
+    }
   }
 </script>
 <style lang="less" scoped>
 @import '../less/base.less';
   .treat-wrap{
     font-size: .3rem;
+    .btscroll;    
     .quest{
       color: #000;
       margin-bottom: .36rem;
@@ -182,11 +196,6 @@
     }
     .label{
       .label;
-      /* img{
-        width:.56rem;
-        height: .74rem;
-        vertical-align: top;
-      } */
     }
     .result{
       .result;
@@ -195,11 +204,6 @@
   .foot{
     .dbfooter;
   }
-  .detail{
-    .mask;
-    z-index: 66;
-  }
-  
 .footer{
   .footer;
 }

+ 330 - 0
src/components/Login.vue

@@ -0,0 +1,330 @@
+<template>
+  <div class="login">
+    <div class="top">
+      <div class="img">
+        <img src="../images/logo.png" alt />
+      </div>
+      <h4>欢迎使用智能预问诊</h4>
+    </div>
+    <div class="main">
+      <div class="iptWrap choose">
+        <p @click="handleShow">
+          {{name}}
+          <img src="../images/down.png" />
+        </p>
+        <div class="slideType" v-if="show">
+          <ul>
+            <li @click="handleType('手机号',103)">手机号</li>
+            <li @click="handleType('身份证号',101)">身份证号</li>
+            <li @click="handleType('病历号',102)">病历号</li>
+            <li @click="handleType('市民卡号',104)" style="border:0 none">市民卡号</li>
+          </ul>
+        </div>
+      </div>
+      <div class="iptWrap number">
+        <input
+          @blur="blur"
+          :maxlength="type==103?11:type==101?18:type==102?7:type==104?9:30"
+          v-model="value"
+          @input="changeVal"
+          :type="type==101||type==104?'text':'tel'"
+          class="input"
+          type="text"
+          :placeholder="'请输入'+name"
+        />
+      </div>
+      <div :class="['btn',value?'btnClick':'btnDis']" @click="handleDepart">进入预问诊</div>
+    </div>
+    <div class="tip">注:建议您可先输入病情情况,方便医生提前了解情况</div>
+    <Submit v-if="submit" :showType="showType" :fail="failMsg" @showSubmit="showSubmit"></Submit>
+    <Tiptoast
+        :show="showTip"
+				@close="close"
+				:data="message"/>
+  </div>
+</template>
+<script>
+import { phoneTest, identify, jgpattern } from "@utils/tools.js";
+import Submit from "../common/Submit";
+import Tiptoast from "../common/Tiptoast";
+import api from "@utils/api.js";
+export default {
+  name: "Login",
+  data() {
+    return {
+      showTip: false,
+      showType: "fail",
+      failMsg: "",
+      submit: false,
+      show: false,
+      type: "103",
+      name: "手机号",
+      value: "",
+      message:{
+        title: "",
+        text: ""
+      },
+      code:''
+    };
+  },
+  created(){
+    this.code = this.$route.query.hospitalCode||''
+  },
+  methods: {
+    close() {
+      this.showTip = false;
+    },
+    handleType(name, type) {
+      let tmpType = this.type;
+      if (tmpType != type) {
+        this.name = name;
+        this.type = type;
+        this.value = "";
+      }
+      this.show = false;
+    },
+    handleShow() {
+      const { show } = this;
+      this.show = !show;
+    },
+    blur() {
+      document.activeElement.scrollIntoViewIfNeeded(true);
+      setTimeout(() => {
+        document.activeElement.scrollIntoViewIfNeeded(true);
+      }, 300);
+    },
+    changeVal() {
+      document.activeElement.scrollIntoViewIfNeeded(true);
+      const { type, value } = this;
+      if (type == 102 || type == 103) {
+        this.value = value.replace(/[^\d]/g, "");
+      } else if (type == 101 || type == 104) {
+        this.value = value.replace(/[^\w\.\/]/ig, "");
+      }
+    },
+    defaultWaring(msg) {
+      this.$store.commit("handleToggleShow", false);
+      this.showType = "fail";
+      this.failMsg = msg;
+      this.submit = true;
+      let timer = setTimeout(() => {
+        this.submit = false;
+        clearTimeout(timer);
+      }, 2000);
+    },
+    showSubmit(flg) {
+      this.submit = flg;
+    },
+    handleDepart() {
+      const { type, value } = this;
+      if (value) {
+        if (type == 103) {
+          if (!phoneTest.test(value)) {
+            //验证不通过
+            this.defaultWaring("输入信息格式有误");
+            return;
+          }
+        } else if (type == 101) {
+          //身份证
+          if (!identify.test(value)) {
+            //验证不通过
+            this.defaultWaring("输入信息格式有误");
+            return;
+          }
+        } else if (type == 104) {
+          //病历号只能输入数字字母
+          if (!jgpattern.test(value)) {
+            //验证不通过
+            this.defaultWaring("输入信息格式有误");
+            return;
+          }
+        }
+        if(!this.code){
+          this.defaultWaring("医院编码必填");
+          return;
+        }
+        const param = {
+          patientInfo: this.value,
+          patientInfoType: this.type,
+          hospitalCode:this.code
+        };
+        api
+          .signIn(param)
+          .then(res => {
+            let result = res.data;
+            if (result.code == 0) {
+              // result.data.splice(0,1);//测试只有一条数据
+              localStorage.setItem('loginData',JSON.stringify(result.data))//保存登陆信息,扫码进入徐删除该参数
+              if (result.data.length > 1) {
+                this.$router.push({
+                  name: "Department",
+                  params: { result: result.data }
+                });
+              } else if (result.data.length == 1) {
+                let msg = result.data[0];
+                let params = {
+                  hospitalCode: msg.hospitalCode,
+                  hospitalDeptCode: msg.hospitalDeptCode,
+                  doctorCode: msg.doctorCode,
+                  patientCode: msg.patientCode,
+                  recordId: msg.recordId,
+                  time:(new Date((msg.recordTime).replace(/\-/g, "/"))).getTime()
+                };
+                localStorage.setItem('loginParam',JSON.stringify(params))//保存登陆信息,扫码进入徐删除该参数
+                this.$router.push({
+                  path: "/home",
+                  query: params
+                });
+              } else {
+                this.message.title = '温馨提示'
+                this.message.text = '暂无今日挂号信息,可更换登录方式再次尝试。'
+                this.showTip = true
+              }
+            } else {
+              if(res.msg.indexOf('暂无今日挂号信息') != -1){
+                this.message.title = '温馨提示'
+                this.message.text = '暂无今日挂号信息,可更换登录方式再次尝试。'
+                this.showTip = true
+              }else{
+                this.defaultWaring(res.msg);
+              }
+            }
+          })
+          .catch(() => {
+            this.defaultWaring("网络异常请稍后重试");
+          });
+      }
+    }
+  },
+  components: {
+    Submit,
+    Tiptoast
+  }
+};
+</script>
+<style lang="less" scoped>
+.login {
+  height: 100%;
+  width: 100%;
+  position: fixed;
+  background: linear-gradient(
+    180deg,
+    rgba(79, 79, 255, 1) 0%,
+    rgba(79, 137, 255, 1) 100%
+  );
+  padding: 0.1rem 0.6rem;
+  box-sizing: border-box;
+  .top {
+    .img {
+      width: 1.6rem;
+      height: 1.6rem;
+      background-color: #fff;
+      margin: 1rem auto 0 auto;
+      border-radius: 50%;
+      overflow: hidden;
+      padding:6px;
+      img {
+        width: 100%;
+      }
+    }
+    h4 {
+      font-size: 0.42rem;
+      text-align: center;
+      color: #fff;
+      margin-top: 0.4rem;
+      margin-bottom: 0.7rem;
+      font-weight: normal;
+    }
+  }
+  .main {
+    width: 100%;
+    height: 5.34rem;
+    background: #fff;
+    border-radius: 0.2rem;
+    padding: 0.8rem 0.6rem;
+    box-sizing: border-box;
+    font-size: 0.3rem;
+    .iptWrap {
+      width: 100%;
+      height: 0.88rem;
+      background: rgba(242, 242, 245, 1);
+      border-radius: 0.1rem;
+      padding: 0.23rem 0.3rem;
+      box-sizing: border-box;
+    }
+    .choose {
+      position: relative;
+      p {
+        width: 100%;
+        position: relative;
+        img {
+          position: absolute;
+          right: 0;
+          top: 0;
+          width: 0.4rem;
+          height: 0.4rem;
+        }
+      }
+      .slideType {
+        box-sizing: border-box;
+        position: absolute;
+        z-index: 10;
+        width: 100%;
+        top: 0.88rem;
+        left: 0;
+        box-shadow: 0px 4px 20px 0px rgba(102, 102, 102, 0.18);
+        border-radius: 0.1rem;
+        background-color: #fff;
+        padding: 0.1rem 0.3rem 0 0.3rem;
+        box-sizing: border-box;
+        font-size: 0.28rem;
+        li {
+          border-bottom: 1px solid #f5f5f5;
+          height: 0.6rem;
+          line-height: 0.6rem;
+          box-sizing: border-box;
+        }
+      }
+    }
+
+    .number {
+      margin: 0.3rem 0 0.8rem 0;
+      .input {
+        float: left;
+        color: rgba(51, 51, 51, 1);
+        height: 0.42rem;
+        line-height: 0.42rem;
+        width: 100%;
+        font-size: .3rem;
+        background-color: transparent;
+      }
+    }
+    .btn {
+      width: 100%;
+      height: 0.88rem;
+      line-height: 0.88rem;
+      text-align: center;
+      background: linear-gradient(
+        270deg,
+        rgba(79, 139, 255, 1) 0%,
+        rgba(79, 79, 255, 1) 100%
+      );
+      border-radius: 0.44rem;
+      color: #fff;
+      font-size: 0.32rem;
+      font-weight: 500;
+    }
+    .btnDis {
+      opacity: 0.3;
+    }
+    .btnClick {
+      opacity: 1;
+    }
+  }
+  .tip {
+    color: #fff;
+    font-size: 0.24rem;
+    margin-top: 0.5rem;
+  }
+}
+</style>

+ 73 - 64
src/components/Others.vue

@@ -1,34 +1,34 @@
 <template>
-  <div class="other-wrap">
-    <div v-for="(it,i) in dtoList" 
-        v-if="dtoList"
-        :key="it.id"
-        class="label">
+  <div class="other-wrap otherper">
+    <div class="content">
+      <div v-for="(it,i) in dtoList" 
+          v-if="dtoList"
+          :key="it.id"
+          class="label">
         <p class="quest">{{i + 1 +'.' + (it.description||it.name)}}</p>
         <img class="questionImg" :src="it.url.replace('{imageUrlPrefix}',imgUrl)" v-if="it.url">
-        <!-- <Label v-if="it.controlType==0" -->
         <Label v-if="it.controlType==0"
               :item="it"
               :ppId="it.id" 
-              :moduleType="datas.type" 
-              @setDetail="setDetail"/>
+              :order="i"
+              :moduleType="datas.type"/>
         <!-- 输入框 -->
         <Input v-if="it.controlType==6 || it.controlType==7"
             :item="it"
             :key="it.id"
-            @updata="updataData($event,it.id)"/>
+            @updata="updataData($event,it.id,i)"/>
         <!-- 文本域 -->
         <ComTextArea v-if="it.controlType == 5"
             :item="it"
-            @updata="updataData($event,it.id)"/>
+            @updata="updataData($event,it.id,i)"/>
         <Radio v-if="it.controlType==1" 
             :item="it"
             :key="it.id"
-            @updata="updataData($event,it.id)"/>
+            @updata="updataData($event,it.id,i)"/>
         <CheckBox v-if="it.controlType==2" 
             :item="it"
             :key="it.id"
-            @updata="updataData($event,it.id)"/>
+            @updata="updataData($event,it.id,i)"/>
         <!-- 多行输入-->
         <template
             v-if="it.controlType == 3"
@@ -37,13 +37,14 @@
             <MultiLineInput
               :msg="part.name"
               :part="part"
-              @updata="updataData($event,it.id,index)"
+              @updata="updataData($event,it.id,i,index)"
             ></MultiLineInput>
         </template>
-    </div>
-    <div class="result" v-if="checkText.length>0">
-      <p class="title">{{datas.name}}</p>
-      <p>{{getText()}}</p>
+      </div>
+      <div class="result" v-if="getText()">
+        <p class="title">{{datas.name}}</p>
+        <p>{{getText()}}</p>
+      </div>
     </div>
     <div class="foot" v-if="modluesLen==3&&!nextName||modluesLen==2">
       <span class="back" @click="beBack">{{'返回'+ preName}}</span>
@@ -53,14 +54,6 @@
       <span class="back" @click="beBack">{{'返回'+ preName}}</span>
       <span class="next" @click="toNext">{{'进入'+ nextName}}</span>
     </div>
-    <div class="detail" v-if="show">
-      <DetailBox @close="closeDetal" 
-              :data="labelDetail" 
-              :moduleType="datas.type"
-              :ppId="ppId"
-              v-if="labelDetail.questionMapping&&labelDetail.questionMapping.length>0"
-              @pComplete="complete"/>
-    </div>
   </div>
 </template>
 <script type="text/javascript">
@@ -70,29 +63,39 @@
   import Toast from '../common/Toast.vue';
   import Input from '../common/Input.vue';
   import ComTextArea from '../common/ComTextArea.vue';
-  import {moduleCP,patt,imageUrlPrefix} from '@utils/tools';
+  import {moduleCP,patt,imageUrlPrefix,setScroll,trimDots} from '@utils/tools';
   import Radio from '../common/Radio.vue';
   import CheckBox from '../common/CheckBox.vue';
   import MultiLineInput from '../common/MultiLineInput.vue';
+  import BScroll from 'better-scroll';
   export default {
     name:'Others',
     data(){
       let {origin,datas,text} = this.$store.state.others;
       return{
         msg:"其他情况",
-        // imgs:this.$store.state.others.imgSrc,
-        // dtoList:origin, //模板数据
         dtoList:datas, //模板数据
         labelDetail:{}, //标签明细
         checkText:text, //选中的文字
         ppId:null,
         show:false,
         imgUrl:imageUrlPrefix,
+        scroll:null
       }
     },
     props:['datas','preName','nextName','modluesLen'],
     created(){},
+    mounted(){
+      this.$nextTick(()=>{
+        let scroll = setScroll(BScroll,true,'.otherper')
+        this.scroll = scroll
+        scroll.on('scroll', this.onScroll)
+      })
+    },
     methods:{
+      onScroll() {
+        document.activeElement.scrollIntoViewIfNeeded(true);
+      },
       beBack(){
         this.$emit('back');
       },
@@ -103,49 +106,53 @@
           this.$emit('next');
         }
       },
-      setDetail(obj){
-        this.labelDetail = obj.detail;
-        this.ppId = obj.ppId;
-        this.show = true;
-      },
-      complete(){
-        this.show = false;
-        this.labelDetail = {};
-        this.ppId = null;
-        // 处理明细选中的值
-      },
-      closeDetal(){
-        this.show = false;
-        this.labelDetail = {};
-        this.ppId = null;
-      },
-      updataData(data,id,index){//输入框存值
+      updataData(data,id,order,index){//输入框存值
         let list = this.dtoList;
+        let value = "";
+        let valueP = "";
         for(let i in list){
-          // if(list[i].id==data.id){
           if(list[i].id==id){
             if(list[i].controlType == 3){//多行输入
               let detailList = list[i].questionDetailList;
               detailList.splice(index,1,data);
+              let temVal = "";
+              for(let k in detailList){
+                if(detailList[k].value){
+                  temVal += detailList[k].value + ','
+                }
+              }
+              value = valueP = temVal?temVal.substring(0,temVal.length-1):'';
             }else{
-              list.splice(i,1,data)
-            } 
+              list.splice(i,1,data);
+              value = data.value;
+              valueP = data.valueP;
+            }
           }
         }
         
-        // this.$store.commit('setOrigin',{type:'3',data:data,pId:data.id});
         this.$store.commit('setDatas',{type:moduleCP['other'],data:data,pId:data.id,ppId:id});
-        this.$store.commit('setText',{type:moduleCP['other'],text:data.value.replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,''),textP:data.valueP.replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,''),pId:data.id,flag:true}); 
+        this.$store.commit('setText',{type:moduleCP['other'],text:value.replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,''),textP:valueP.replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,''),pId:data.id,flag:true,order:order}); 
+        
+        this.$nextTick(()=>{
+          this.scroll.refresh()
+        })
       },
       getText(){
         let textArr = this.checkText;
         let msg = "";
         for(let k in textArr){
-          if(textArr[k].textP){
-            msg += textArr[k].textP + ';'
-          }          
-        }
-        return msg;
+          if(textArr[k] && Array.isArray(textArr[k])){
+            let temp = textArr[k];
+            for(let j in temp){
+              if(temp[j] && temp[j].textP){
+                msg += temp[j].textP + ','
+              }
+            }
+          }else if(textArr[k]&&textArr[k].textP){
+            msg += textArr[k].textP + ','
+          }
+        }    
+        return trimDots(msg.substring(0,msg.length-1));
       }
     },
     components:{
@@ -158,20 +165,26 @@
       CheckBox,
       MultiLineInput
     },
-    /*watch:{
-      dtoList:{
-        handler(newVal,oldVal){
-          console.log("其他史数据更新:",newVal,this.$store.state.others.text)
+    computed:{
+      getItem(){
+        return this.$store.state.others.text;
+      }
+    },
+    watch:{
+      getItem:{
+        handler(value){
+          this.checkText = value;
         },
         deep:true
       }
-    },*/
+    }
   }
 </script>
 <style lang="less" scoped>
 @import '../less/base.less';
   .other-wrap{
     font-size: .3rem;
+    .btscroll;
     .quest{
       color: #000;
       margin-bottom: .36rem;
@@ -187,10 +200,6 @@
   .foot{
     .dbfooter;
   }
-  .detail{
-    .mask;
-    z-index: 66;
-  }
   .questionImg {
     width: 96%;
   }

+ 77 - 90
src/components/PathInfo.vue

@@ -1,72 +1,44 @@
 <template>
   <div class="path-wrap">
-    <p class="info">挂号用户信息查询如下:</p>
-    <div class="con">
-      <p class="name">
-        <span>{{pathInfo.patientName}}</span>|
-        <span>{{pathInfo.patientSex}}</span>|
-        <span>{{pathInfo.patientAge}}岁</span>
-      </p>
-      <p>
-        <span>挂号科室:</span>
-        <span>{{pathInfo.selfDeptName}}</span>
-      </p>
-      <div class="dept">
-        <p>
-          <span>门诊号:</span>
-          <span>{{pathInfo.recordId}}</span>
+    <div class="content">
+      <p class="info">挂号用户信息查询如下:</p>
+      <div class="con">
+        <p class="name">
+          <span>{{pathInfo.patientName}}</span>|
+          <span>{{pathInfo.patientSex}}</span>|
+          <span>{{pathInfo.patientAge}}岁</span>
         </p>
         <p>
           <span>预约医生:</span>
           <span>{{pathInfo.doctorName}}</span>
         </p>
-      </div>
-      <p>
-        <span>预约时间:</span>
-        <span>{{pathInfo.systemTime}}</span>
-      </p>
-      <!-- <div class="dept">
-        <p>
-          <span>挂号科室:</span>
-          <span>{{pathInfo.selfDeptName}}</span>
-        </p>
-        <p>
-          <span>门诊号:</span>
-          <span>{{pathInfo.recordId}}</span>
-        </p> 
-      </div>
-      <div class="doct">
-        <p>
-          <span>预约医生:</span>
-          <span>{{pathInfo.doctorName}}</span>
-        </p>
         <p>
           <span>预约时间:</span>
-          <span>{{pathInfo.systemTime}}</span>
+          <span>{{time}}</span>
         </p>
-      </div> -->
-      <p class="already" v-if="type !== 1">{{text[type]}}</p>
-    </div>
-    <div class="out-box">
-      <div class="emery">
-        <div class="baner">
-          <p>{{pathInfo.hospitalName}}</p>
-          <p class="big">智能预问诊</p>
-        </div>
-        <div class="inner">
-          <p>该系统通过智能引导式问诊,帮助医生规范、全面的采集患者的症状、体征、病史等信息,从而实现诊疗流程的优化和配置。</p>
-          <button @click="getStart">开始</button>
-        </div>
-        <!-- <p v-if="type==3">您已完成过一次预问诊,是否再次录入</p> -->
+        <p class="already" v-if="type !== 1">{{text[type]}}</p>
       </div>
-      <div class="child" v-if="child.length>0&&child[0].value==1 && !hideChild">
-        <div class="baner">
-          <p>{{pathInfo.hospitalName}}</p>
-          <p class="big">儿童体质检测</p>
+      <div class="out-box">
+        <div class="emery">
+          <div class="baner">
+            <p>{{pathInfo.hospitalName}}</p>
+            <p class="big">智能预问诊</p>
+          </div>
+          <div class="inner">
+            <p>该系统通过智能引导式问诊,帮助医生规范、全面的采集患者的症状、体征、病史等信息,从而实现诊疗流程的优化和配置。</p>
+            <button @click="getStart">开始</button>
+          </div>
+          <!-- <p v-if="type==3">您已完成过一次预问诊,是否再次录入</p> -->
         </div>
-        <div class="inner">
-          <p>该标准将为0-12岁儿童在为体质辨识及与中医体质相关疾病的预防、养生保健、健康管理提供依据,使体质分类科学化、规范化。</p>
-          <button>开始</button>
+        <div class="child" v-if="child.length>0&&child[0].value==1 && !hideChild">
+          <div class="baner">
+            <p>{{pathInfo.hospitalName}}</p>
+            <p class="big">儿童体质检测</p>
+          </div>
+          <div class="inner">
+            <p>该标准将为0-12岁儿童在为体质辨识及与中医体质相关疾病的预防、养生保健、健康管理提供依据,使体质分类科学化、规范化。</p>
+            <button>开始</button>
+          </div>
         </div>
       </div>
     </div>
@@ -80,7 +52,8 @@
 <script type="text/javascript">
   import api from '@utils/api.js'
   import Submit from '../common/Submit';
-  import {getUrlArgObject} from '@utils/tools.js'
+  import {getUrlArgObject,setScroll,dateParser} from '@utils/tools.js'
+  import BScroll from 'better-scroll';
   export default {
     name:'PathInfo',
     data(){
@@ -97,7 +70,10 @@
         isReady:false,
         hideChild:true,  //隐藏儿童
         submit:false,
-        message:''
+        scroll:null,
+        message:'',
+        time:'',
+        params:{}
       }
     },
     created(){
@@ -105,14 +81,34 @@
       this.getSysConfig();
       this.$store.commit('initAllData');//初始化store数据
     },
+    mounted(){
+      this.$nextTick(()=>{
+        let scroll = setScroll(BScroll,true,'.path-wrap')
+        this.scroll = scroll
+      })
+    },
     methods:{
       getPathInfo(){
+        let query = this.$route.query
+        let hasQuery = JSON.stringify(query) == '{}'
+        let tmpTime = dateParser(!hasQuery&&query.recordTime) || (localStorage.getItem('loginParam')&&dateParser(JSON.parse(localStorage.getItem('loginParam')).time))
+        this.time = tmpTime
         const params = {
-          'hospitalCode':getUrlArgObject('hospitalCode'),
-          'hospitalDeptCode':getUrlArgObject('hospitalDeptCode'),
-          'doctorCode':getUrlArgObject('doctorCode'),
-          'patientCode':getUrlArgObject('patientCode'),
-          'recordId':getUrlArgObject('recordId')
+          'hospitalCode':!hasQuery&&query.hospitalCode||'',
+          'hospitalDeptCode':!hasQuery&&query.hospitalDeptCode||'',
+          'doctorCode':!hasQuery&&query.doctorCode||'',
+          'patientCode':!hasQuery&&query.patientCode||'',
+          'recordId':!hasQuery&&query.recordId||'',
+          'recordTime':!hasQuery&&query.recordTime||''
+        }
+        if(!hasQuery&&query.scan){//扫码进入的
+          localStorage.removeItem('loginParam')
+          localStorage.removeItem('loginData')
+          localStorage.setItem('scan',true)//保存扫码标记
+          localStorage.setItem('infoParam',JSON.stringify(params))//保存扫码信息,登录进入需删除该参数
+        }else{//登陆进入的
+          localStorage.removeItem('infoParam')
+          localStorage.removeItem('scan')
         }
         api.getPathInfo(params).then((res)=>{
           const result = res.data;
@@ -125,8 +121,10 @@
         })
       },
       getSysConfig(){
+        let query = this.$route.query
+        let hasQuery = JSON.stringify(query) == '{}'
         const param = {
-          'hospitalCode':getUrlArgObject('hospitalCode')
+          'hospitalCode':!hasQuery&&query.hospitalCode||'',
         }
         api.getSysConfig(param).then((res)=>{
           const result = res.data;
@@ -165,7 +163,6 @@
             const datas = result.data;
             this.$store.commit('saveAll',datas)
             let access = datas.filter(item=>item.type == 1).length>0
-            // console.log(datas.filter(item=>item.type == 1)>0)
             this.isReady=access
           }else{
             this.defaultWaring(result.msg)
@@ -173,11 +170,16 @@
         })
       },
       getStart(){
+        const pathInfo = this.pathInfo;
+        if(JSON.stringify(pathInfo)=='{}'){
+          this.defaultWaring('网络异常请稍后重试');
+          return
+        }
         if(this.isReady){
           // this.$router.push({path:'/tab'})
           this.$router.replace({path:'/tab'})
         }else{
-          this.defaultWaring('网络异常请稍后重试')
+          this.defaultWaring('请先维护症状模块')
         }
       },
       defaultWaring(msg){
@@ -196,9 +198,15 @@
 </script>
 <style lang="less" scoped>
   .path-wrap{
-    padding-top: .5rem;
     font-size: .28rem;
-    box-sizing: border-box;
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    .content {
+      padding-top: .5rem;
+      padding-bottom: .2rem;
+      box-sizing: border-box;
+    }
     .info{
       font-size: .32rem;
       font-weight: 700;
@@ -232,19 +240,6 @@
           margin-right: .25rem;
         }
       }
-      /* .dept,.doct{
-        display: inline-block;
-        p{
-          display: inline-block;
-          margin-top: .27rem;
-          span{
-            color: #7C828E;
-          }
-        }
-      }
-      .doct{
-        margin-left: .26rem;
-      } */
       .already{
         position: absolute;
         left: 0;
@@ -262,17 +257,13 @@
     .emery,.child{
       display: inline-block;
       vertical-align: top;
-      // width:5.3rem;
       width:5.1rem;
       margin-top: .91rem;
-      // margin-left: .6rem;
       box-sizing: border-box;
       .baner{
         box-sizing: border-box;
         width:100%;
-        // height: 2.52rem;
         height: 2.3rem;
-        // padding: .66rem 0 0 .6rem;
         padding-top: .5rem;
         p{
           color:#fff;
@@ -283,7 +274,6 @@
         }
       }
       .inner{
-        // height: 4.98rem;
         height: 4.5rem;
         box-shadow:-.05rem .05rem .10rem -.04rem #989da3,.05rem .05rem .10rem -.04rem #989da3;
         border-radius: 0 0 .20rem .20rem;
@@ -301,14 +291,11 @@
           height: .88rem;
           color: #fff;
           font-size: .32rem;
-          // margin-top: .20rem;
           margin: .40rem 0 0 -.05rem;
           background: -webkit-gradient(linear, right top, left top, from(#4F8BFF), to(#4F4FFF));
           background: -webkit-linear-gradient(right, #4F8BFF, #4F4FFF);
           box-shadow: 0 .12rem .24rem 0 rgba(79,129,255,0.40);
           border-radius: .44rem;
-          // position: absolute;
-          // bottom: .7rem;
         }
       }
     }

+ 177 - 123
src/components/Preview.vue

@@ -1,108 +1,53 @@
 <template>
-  <div class="preview" ref="preview">
-    <div class="personMsg">
-      <p class="baseMsg">{{pathInfo.patientName}}&nbsp;&nbsp;&nbsp;&nbsp;{{pathInfo.patientSex}}&nbsp;&nbsp;&nbsp;&nbsp;{{pathInfo.patientAge}}岁</p>
-      <table>
-        <tr>
-          <td colspan="2">挂号科室:{{pathInfo.selfDeptName}}</td>
-        </tr>
-        <tr>
-          <td>门诊号:{{pathInfo.recordId}}</td>
-          <td>预约医生:{{pathInfo.doctorName}}</td>
-        </tr>
-        <tr>
-          <td colspan="2">就诊时间:{{pathInfo.systemTime}}</td>
-        </tr>
-      </table>
-      <div class="line"></div>
-      <p>采集时间:{{pathInfo.systemTime}}</p>
-    </div>
-    <div class="personMsg personMsg2">
-      <ul class="previewParts">
-        <!-- <li v-if="symptom.choose.length>0"> -->
-        <li>
-          <h4><i :style="{'background': '#FF9A9A'}"></i> 主诉:</h4>
-          <p>
-            <span v-for="(item,idx) in symptom.choose" :key="item.name+idx">{{item.name+(idx == symptom.choose.length-1?'':'、')}}</span>
-          </p>
-        </li>
-        <!-- <li v-if="diagnose.text.length>0||symptom.choose.length>0"> -->
-        <li>
-          <h4><i :style="{'background': '#3D69D9'}"></i> 现病史:</h4>
-          <p>
-            <span v-for="(item,idx) in symptom.text" :key="item.text+idx">{{trimDots&&trimDots(item.textP+(idx!=0 && idx == symptom.choose.length-1?'。':';'))}}</span>
-          </p>
-          <p>
-            <span v-for="(item,idx) in diagnose.text" :key="item.text+idx">{{trimDots&&trimDots(item.textP+(idx!=0 && idx == diagnose.text.length-1?'。':';'))}}</span>
-          </p>
-        </li>
-        <li v-if="showLis[moduleCP['other']]==1">
-          <h4><i></i> 其他史:</h4>
-          <p>
-            <span v-for="(item,idx) in others.text" :key="item.text+idx">{{trimDots&&trimDots(item.textP+(idx!=0 && idx == others.text.length-1?'。':';'))}}</span>
-          </p>
-        </li>
-        <li v-if="showLis[moduleCP['suplement']]==1">
-          <h4><i></i> 补充内容:</h4>
-          <p>{{addContent.txt}}</p>
-        </li>
-        <li v-if="JSON.stringify(diagnose.imgSrc) !='{}'" 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="foot">
-      <span
-        class="back"
-        @click="back"
-      >{{'返回'+ preName}}</span>
-      <span
-        class="next"
-        @click="saveAllImage"
-      >提 交</span>
-    </div>
-    <Submit
-      v-if="submit"
-      :showType="showType"
-      @showSubmit="showSubmit"
-    ></Submit>
-    <Loading v-if="loadingShow"></Loading>
-    <div class="doctorData" @click="handleClick(true)">医生端数据展示</div>
-    <div class="personMsgDoc" v-if="showDoc">
-      <div class="personMsgDocModal" @click.prevent="handleClick(false)"></div>
-      <div class="personMsgDocDetail">
-        <img class="close" src="../images/small-close.png" alt="" @click="handleClick(false)">
+  <div class="wrapper">
+    <div class="preview previewper">
+      <div class="content">
+        <div class="tmpDiv"></div>
+        <div class="personMsg personMsg1">
+          <p class="baseMsg">{{pathInfo.patientName}}&nbsp;&nbsp;&nbsp;&nbsp;{{pathInfo.patientSex}}&nbsp;&nbsp;&nbsp;&nbsp;{{pathInfo.patientAge}}岁</p>
+          <table>
+            <tr>
+              <td colspan="2">挂号科室:{{pathInfo.selfDeptName}}</td>
+            </tr>
+            <tr>
+              <td>门诊号:{{pathInfo.recordId}}</td>
+              <td>预约医生:{{pathInfo.doctorName}}</td>
+            </tr>
+            <tr>
+              <td colspan="2">就诊时间:{{time}}</td>
+            </tr>
+          </table>
+          <!-- <div class="line"></div>
+          <p>采集时间:{{pathInfo.systemTime}}</p> -->
+        </div>
         <div class="personMsg personMsg2">
           <ul class="previewParts">
             <!-- <li v-if="symptom.choose.length>0"> -->
             <li>
               <h4><i :style="{'background': '#FF9A9A'}"></i> 主诉:</h4>
               <p>
-                <span v-for="(item,idx) in symptom.choose" :key="item.name+idx">{{item.name+(idx == symptom.choose.length-1?'':'、')}}</span>
+                <span v-for="(item,idx) in symptom.choose" :key="item.name+idx">
+                {{item.specialP?(item.description||item.name)+item.specialP+(idx == symptom.choose.length-1?'':','):(item.description||item.name)+(idx == symptom.choose.length-1?'':',')}}
+                </span>
               </p>
             </li>
             <!-- <li v-if="diagnose.text.length>0||symptom.choose.length>0"> -->
             <li>
               <h4><i :style="{'background': '#3D69D9'}"></i> 现病史:</h4>
+              <p v-for="item in symptom.text">{{item.textP}}</p>
               <p>
-                <span v-for="(item,idx) in symptom.text" :key="item.text+idx">{{trimDots&&trimDots(item.text+(idx == symptom.choose.length-1?'。':';'))}}</span>
-              </p>
-              <p>
-                <span v-for="(item,idx) in diagnose.text" :key="item.text+idx">{{trimDots&&trimDots(item.text+(idx == diagnose.text.length-1?'。':';'))}}</span>
+                <span>{{getDetailText(diagnose.text,false).view}}</span>
               </p>
             </li>
             <li v-if="showLis[moduleCP['other']]==1">
               <h4><i></i> 其他史:</h4>
               <p>
-                <span v-for="(item,idx) in others.text" :key="item.text+idx">{{trimDots&&trimDots(item.text+(idx == others.text.length-1?'。':';'))}}</span>
+                <span>{{getDetailText(others.text,false).view}}</span>
               </p>
             </li>
             <li v-if="showLis[moduleCP['suplement']]==1">
               <h4><i></i> 补充内容:</h4>
-              <p>{{addContent.txtDoc}}</p>
+              <p>{{addContent.txt}}</p>
             </li>
             <li v-if="JSON.stringify(diagnose.imgSrc) !='{}'" class="imgLis">
               <h4 class="imgTitle"><i></i> 最近一次治疗报告:</h4>
@@ -112,15 +57,72 @@
             </li>
           </ul>
         </div>
+        <div class="doctorData" @click="handleClick(true)">医生端数据展示</div>
       </div>
     </div>
+    <div class="foot">
+        <span
+          class="back"
+          @click="back"
+        >{{'返回'+ preName}}</span>
+        <span
+          class="next"
+          @click="saveAllImage"
+        >提 交</span>
+      </div>
+      <Submit
+        v-if="submit"
+        :showType="showType"
+        @showSubmit="showSubmit"
+      ></Submit>
+      <Loading v-if="loadingShow"></Loading>
+      <div class="personMsgDoc" v-if="showDoc">
+        <div class="personMsgDocModal" @click="handleClick(false)"></div>
+        <div class="personMsgDocDetail">
+          <img class="close" src="../images/small-close.png" alt="" @click="handleClick(false)">
+          <div class="personMsg personMsg2">
+            <ul class="previewParts">
+              <li>
+                <h4><i :style="{'background': '#FF9A9A'}"></i> 主诉:</h4>
+                <p>
+                  <span v-for="(item,idx) in symptom.choose" :key="item.name+idx">{{item.special?item.name+item.special+(idx == symptom.choose.length-1?'':','):item.name+(idx == symptom.choose.length-1?'':',')}}</span>
+                </p>
+              </li>
+              <li>
+                <h4><i :style="{'background': '#3D69D9'}"></i> 现病史:</h4>
+                <p v-for="item in symptom.text">{{item.text}}</p>
+                <p>
+                  <span>{{getDetailText(diagnose.text,false).content}}</span>
+                </p>
+              </li>
+              <li v-if="showLis[moduleCP['other']]==1">
+                <h4><i></i> 其他史:</h4>
+                <p>
+                  <span>{{getDetailText(others.text,false).content}}</span>
+                </p>
+              </li>
+              <li v-if="showLis[moduleCP['suplement']]==1">
+                <h4><i></i> 补充内容:</h4>
+                <p>{{addContent.txtDoc}}</p>
+              </li>
+              <li v-if="JSON.stringify(diagnose.imgSrc) !='{}'" 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>
+      </div>
   </div>
 </template>
 <script>
 import api from '@utils/api.js';
 import Submit from '../common/Submit';
 import Loading from '../common/Loading';
-import {moduleCP,trimDots} from '@utils/tools.js'
+import BScroll from 'better-scroll';
+import {moduleCP,trimDots,setScroll,dateParser} from '@utils/tools.js'
 export default {
   props: ['preName','showLis','loadingShow'],
   data() {
@@ -139,20 +141,36 @@ export default {
       submit: false,
       showType: 'fail',
       imgList:[],
-      // show:loadingShow,//提交等待的动画loading
       tmpNum:0,
       moduleCP:moduleCP,
       showDoc:false,
-      trimDots:trimDots
+      trimDots:trimDots,
+      time:''
     }
   },
+  created(){
+    this.getTime();
+  },
+  mounted() {
+    this.$nextTick(()=>{
+      let scroll = setScroll(BScroll,true,'.previewper')
+      this.scroll = scroll
+    })
+  },
   methods: {
-    handleClick(flg){
-      if(flg){
-        this.$refs.preview.style.overflow = 'hidden'
+    getTime() {
+      let scan = localStorage.getItem('scan');
+      let params = JSON.parse(localStorage.getItem('infoParam'));
+      let param = JSON.parse(localStorage.getItem('loginParam'));
+      let tmpArr = localStorage.getItem('recordTime')
+      let tmpTime = tmpArr&&Array.isArray(JSON.parse(tmpArr))?JSON.parse(tmpArr):[];
+      if(!scan){
+        this.time = dateParser(param.time)
       }else{
-        this.$refs.preview.style.overflow = 'auto'
+        this.time = dateParser(params.recordTime)
       }
+    },
+    handleClick(flg){
       this.showDoc = flg
     },
     showSubmit(flg) {
@@ -187,13 +205,11 @@ export default {
           //   }
           // })
         }
-        // return
         api.uploadImageThums(formData).then((res) => {//获取图片
-          let result = res.data;
-          if (result.code == 0) {//图片提交成功再保存数据
-            // this.showType = 'success'
-            // this.submit = true
-            let reportList = []
+          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.narrowImage = result[i].thumbnail.url
@@ -219,39 +235,69 @@ export default {
         return;
       } else {//没有图片直接保存数据
         this.$store.commit('handleToggleShow', true);
-        this.saveAllDate()
+        this.saveAllDate();
       }
     },
-    getStr(arr,flg){
-      let tmpStr = '',tmpStrDoc = '',obg={};
-      for(let i = 0;i<arr.length;i++){
-        tmpStr+=arr[i].text+';'
-        tmpStrDoc+=arr[i].textP+';'
+    getDetailText(textArr,flg){
+      let msg = "",obg={},msgP = "";
+      if(flg == 1){
+        for(let k in textArr){
+          let item = textArr[k]
+          if(item.special){
+            msg+=item.name+item.special+(k == textArr.length-1?'':',')
+            msgP+=item.name+item.specialP+(k == textArr.length-1?'':',')
+          }else{
+            msg+=item.name+(k == textArr.length-1?'':',')
+            msgP+=item.name+(k == textArr.length-1?'':',')
+          }
+        }
+      }else{
+        for(let k in textArr){
+          if(textArr[k] && Array.isArray(textArr[k])){
+            let temp = textArr[k];
+            for(let j in temp){
+              if(temp[j]){
+                msg += temp[j].text + ','
+                msgP += temp[j].textP + ','
+              }
+            }
+          }else if(textArr[k]){
+            msg += textArr[k].text + ','
+            msgP += textArr[k].textP + ','
+          }
+        }
       }
-      obg.content=tmpStr
-      obg.contentValue=tmpStrDoc
+      
+      obg.view=trimDots(msgP.replace(/,$/,''))
+      obg.content=trimDots(msg.replace(/,$/,''))
+      obg.contentJson=trimDots(msg.replace(/,$/,''))
+      obg.contentValue=trimDots(msg.replace(/,$/,''))
       obg.type=flg
       return obg;
     },
     saveAllDate() {
       const {pathInfo,symptom,diagnose,others,addContent} = this
-      let detailList = []
-      if(symptom.text.length>0){
-        detailList.push(this.getStr(symptom.text,1))
-      }
-      if(diagnose.text.length>0){
-        detailList.push(this.getStr(diagnose.text,2))
-      }
-      if(others.text.length>0){
-        let obg = {}
-        detailList.push(this.getStr(others.text,3))
-      }
-      if(addContent.txt){
-        let obg = {}
-        obg.content=addContent.txtDoc
-        obg.contentValue=addContent.txt
-        obg.type=4
-        detailList.push(obg)
+      let detailList = [{type:1},{type:2},{type:3},{type:4}]
+      for(let i = 0;i < detailList.length;i++){
+        if(i == 0){
+          detailList[0]=this.getDetailText(symptom.choose,1)
+        }else if(i == 1){
+          let tmpArr = []
+          let tmpStr = this.getDetailText(diagnose.text,2).content
+          for(let j = 0;j < symptom.text.length;j++){
+            tmpArr.push(symptom.text[j].text)
+          }
+          tmpStr.length>0?tmpArr.push(tmpStr):null
+          detailList[1].content=tmpArr.join()+tmpStr
+          detailList[1].contentJson=JSON.stringify(tmpArr)
+          detailList[1].contentValue=tmpArr.join()+tmpStr
+        }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.txt
+        }
       }
       let params = {
         "dataJson": "1",
@@ -310,6 +356,7 @@ export default {
 @import "../less/base.less";
 .foot {
   .dbfooter;
+  z-index: 998;
 }
 .doctorData {
   float: right;
@@ -325,10 +372,15 @@ export default {
   top: 0;
   left: 0;
   box-sizing: border-box;
-  padding: 0.3rem 0.4rem 1rem .4rem;
-  overflow: auto;
+  padding: 0 0.4rem 1rem .4rem;
+  overflow: hidden;
   -webkit-overflow-scrolling:touch;
+  .btscroll;  
+}
+.tmpDiv {
+  height: .3rem;
 }
+
 .imgView {
   width: 1.86rem;
   height: 1.9rem;
@@ -338,6 +390,7 @@ export default {
   box-sizing: border-box;
   position: relative;
   overflow: hidden;
+  border-radius: 0.08rem;
   img {
     position: absolute;
     left: 50%;
@@ -415,6 +468,7 @@ export default {
     height: 1px;
   }
 }
+
 .personMsg2 {
   padding-right: 0;
 }

+ 44 - 40
src/components/Search.vue

@@ -1,44 +1,46 @@
 <template>
-  <div class="searchWrap">
-    <div class="searchTop">
-      <div class="iptWrap">
-        <img
-          class="searchImg"
-          src="../images/searchB.png"
-          alt=""
-        >
-        <input
-          type="text"
-          autofocus
-          placeholder="请搜索"
-          v-model="searchVal"
-        >
+    <portal to="notification-search">
+      <div class="searchWrap">
+        <div class="searchTop">
+          <div class="iptWrap">
+            <img
+              class="searchImg"
+              src="../images/searchB.png"
+              alt=""
+            >
+            <input
+              type="text"
+              autofocus
+              placeholder="请搜索"
+              v-model="searchVal"
+            >
+          </div>
+          <span @click="search">取消</span>
+        </div>
+        <div class="searchList">
+          <p
+            class="waring"
+            v-if="!searchVal&&!hasMore&&searchLis.length==0"
+          >请输入搜索内容</p>
+          <p
+            class="waring"
+            v-if="hasMore&&searchVal"
+          >暂无搜索结果</p>
+          <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'}"
+            ><img
+                class="searchImgLis"
+                src="../images/search.png"
+                alt=""
+              >{{item.description||item.name}}{{(item.tagName&&(item.description||item.name != item.tagName))?' ('+item.tagName+')':''}}</li>
+          </ul>
+        </div>
       </div>
-      <span @click="search">取消</span>
-    </div>
-    <div class="searchList">
-      <p
-        class="waring"
-        v-if="!searchVal&&!hasMore&&searchLis.length==0"
-      >请输入搜索内容</p>
-      <p
-        class="waring"
-        v-if="hasMore&&searchVal"
-      >暂无搜索结果</p>
-      <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'}"
-        ><img
-            class="searchImgLis"
-            src="../images/search.png"
-            alt=""
-          >{{item.name}}</li>
-      </ul>
-    </div>
-  </div>
+    </portal>
 </template>
 <script>
 import api from '@utils/api.js';
@@ -57,6 +59,7 @@ export default {
       if (curVal.trim() == "") {
         this.searchVal = "";
         this.searchLis = [];
+        this.hasMore = false
         return;
       }
       if (curVal != "" && curVal != oldVal) {
@@ -113,8 +116,9 @@ export default {
   width: 100%;
   top: 0;
   left: 0;
-  z-index: 55;
+  z-index: 102;
   background-color: #ededed;
+  font-size: .3rem;
 }
 .searchTop {
   padding: 0.15rem 0.4rem;

+ 143 - 117
src/components/Symptom.vue

@@ -1,41 +1,51 @@
 <template>
-  <div class="symp-wrap">
-    <div
-      class="choose"
-      v-if="chooseSymp.length>0"
-    >
-      <p class="quest">已选症状</p>
-      <p
-        class="choo-symp"
-        v-for="(v,i) in chooseSymp"
+  <div class="symp-wrap symper">
+    <div class="content">
+      <div
+        class="choose"
+        v-if="chooseSymp.length>0"
       >
-        <span @click="showChecked(v)">{{v.name}}</span>
-        <span @click="deletSymp(v,i)"><img
-            src="../images/del.png"
+        <p class="quest">已选症状</p>
+        <p
+          class="choo-symp"
+          v-for="(v,i) in chooseSymp"
+        >
+          <span @click="showChecked(v)">{{v.description || v.name}}</span>
+          <span @click="deletSymp(v,i)"><img
+              src="../images/del.png"
+              alt=""
+            ></span>
+        </p>
+      </div>
+      <div class="label">
+        <p class="quest" id="test">{{quesText}}<img
+            @click="search(true)"
+            class="searchImg"
+            src="../images/search.png"
             alt=""
-          ></span>
-      </p>
-    </div>
-    <div class="label">
-      <p class="quest">{{quesText}}<img
-          @click="search(true)"
-          class="searchImg"
-          src="../images/search.png"
-          alt=""
-        ></p>
-      <span
-        class="symp"
-        v-for="(it,ind) in symp"
-        :key="it.conceptId"
-        @click="showDetil(it)"
-      >{{it.name}}</span>
-    </div>
-    <div
-      class="result"
-      v-if="checkText.length>0"
-    >
-      <p class="title">{{nameStr}}</p>
-      <p v-for="(value,index) in checkText">{{value.textP}}</p>
+          ></p>
+        <!-- <span
+          class="symp"
+          v-for="(it,ind) in symp"
+          :key="it.conceptId"
+          @click="showDetil(it)"
+        >{{it.description || it.name}}</span> -->
+        <!-- 暂时隐藏长按显示功能 -->
+        <span
+          class="symp"
+          v-for="(it,ind) in symp"
+          :key="it.conceptId"
+          @touchstart.stop.prevent="touchstart(it)"
+          @touchend.stop.prevent="touchend(it)"
+        >{{it.description || it.name}}</span>
+      </div>
+      <div
+        class="result"
+        v-if="checkText.length>0"
+      >
+        <p class="title">{{nameStr}}</p>
+        <p v-for="(value,index) in checkText">{{value.textP}}</p>
+      </div>
     </div>
     <div v-if="modluesLen>1"
       :class="['footer',{'nofoot':chooseSymp.length==0}]"
@@ -45,19 +55,6 @@
       :class="['footer',{'nofoot':chooseSymp.length==0}]"
       @click="toNext"
     >预览并提交病历</div>
-    <div
-      class="detail"
-      v-if="show"
-    >
-      <DetailBox
-        @close="closeDetal"
-        :data="labelDetail"
-        :moduleType="1"
-        v-if="labelDetail.questionMapping&&labelDetail.questionMapping.length>0"
-        @pComplete="complete"
-        @reload="reload"
-      />
-    </div>
     <Toast
       :message="delText"
       :show="showToast"
@@ -65,33 +62,35 @@
       @cancel="cancelDel"
     />
     <Search
-      v-if="searchShow"
+      v-if="this.$store.state.searchShow"
       @search="search"
       @showDetil="showDetil"
       :age="age"
       :chooseSymp="chooseSymp"
       :sexType="sexType"
     ></Search>
+    <Tiptoast :show="showExp" :data="message" @close="closeTip"/>
   </div>
 </template>
 <script type="text/javascript">
 import api from '@utils/api.js';
 import DetailBox from './DetailBox.vue';
 import Toast from '../common/Toast.vue';
+import Tiptoast from '../common/Tiptoast.vue';
 import Search from './Search.vue';
-import {moduleCP} from '@utils/tools'
+import {moduleCP,setScroll,trimDots} from '@utils/tools'
+import BScroll from 'better-scroll';
 export default {
   name: 'Symptom',
   props:['modluesLen','nameStr'],
   data() {
-    let { datas, pathInfo } = this.$store.state;
+    let { datas, pathInfo,searchShow } = this.$store.state;
     const { choose, text } = this.$store.state.symptom;
     return {
       age: pathInfo.patientAge,
       sexType: pathInfo.patientSex == '男' ? 1 : (pathInfo.patientSex == '女' ? 2 : 3),
       deptName: pathInfo.selfDeptName,
       hosCode: pathInfo.hospitalCode,
-      show: false, //显示明细
       chooseSymp: choose, //已选症状
       symp: [], //症状
       labelDetail: {}, //明细
@@ -100,10 +99,18 @@ export default {
       delText: "是否删除该信息?<br/>(已填内容将清除)",
       delIndex: null,
       showToast: false,
-      searchShow: false,//显示搜索界面
+      searchShow: searchShow,//显示搜索界面
       tmpItem:{},//检索的症状
       isSearch:false,
-      quesText:"请问您有哪些不适?",
+      scroll:null,
+      quesText:"请问您这次哪里最不舒服?",
+      startTime:'',
+      timer:null,
+      showExp:false,
+      message:{
+        title:'',
+        text:''
+      }
     }
   },
   created() {
@@ -116,12 +123,40 @@ export default {
       this.getSympList(); //常见
     }
   },
+  mounted(){
+    this.$nextTick(()=>{
+      let scroll = setScroll(BScroll,true,'.symper')
+      this.scroll = scroll
+      scroll.on('scroll', this.onScroll)
+    })
+  },
   methods: {
-    searchVal(val) {
-      console.log(val)
+    touchstart(it){
+      this.startTime = +new Date();
+      const that = this;
+      this.timer = setTimeout(function(){
+        // 长按事件
+          that.showExp = true;
+          if(it.explains){
+            that.message.title = it.description || it.name;
+            that.message.text = it.explains;
+          }else{
+            that.message.title = "";
+            that.message.text = "暂无资料";
+          }
+          
+        },600)
+    },
+    closeTip(){
+      this.showExp = false,
+      this.message.title = '';
+      this.message.text = '';
+    },
+    onScroll() {
+      document.activeElement.scrollIntoViewIfNeeded(true);        
     },
     search(flg) {
-      this.searchShow = flg
+      this.$store.commit('setSearchShow', flg);
     },
 
     getSympList() {
@@ -147,16 +182,13 @@ export default {
       }else{
         this.$emit('next');
       }
-
     },
-    showDetil(item,flg) {
-      this.tmpItem=item
-      this.isSearch=flg||false
+    common(item,flg){
       this.questId = item.questionId || item.id || item.conceptId;
       const id = item.questionId || item.id; //常见症状questionId,推送id,两者均有可能没有
       //将选中的name存到store中的text
-      this.$store.commit('setText', { type: moduleCP['symp'], text: item.name,textP: item.name, pId: this.questId });
-      this.quesText = "请问您还有其他不适吗?";
+      this.$store.commit('setText', { type: moduleCP['symp'], text: item.name,textP: item.description||item.name, pId: this.questId });
+      
       if (id) {
         const param = {
           "age": this.age,
@@ -170,35 +202,44 @@ export default {
             this.labelDetail = result.data;
             this.$store.commit('setOrigin', { type: moduleCP['symp'], data: result.data });
             if (mapping && mapping.length > 0) {
-              this.show = true;
+              this.$store.commit('setDetail',{detail:result.data,ppId:null,moduleType:moduleCP['symp']})
               if(flg){
                 return
               }
               this.chooseSymp.push(item);
-            } else { //没有详情,推送
-              const sympText = this.getSympText();
-              this.getPush(sympText);
+            } else { 
               this.chooseSymp.push(item);
-              this.searchShow = false
-              // this.complete()
+              this.$store.commit('setSearchShow', false);
             }
           }
         })
-      } else {//没有questionId或id 则直接调推送
+      } else {//没有questionId或id 
         this.chooseSymp.push(item);
-        const sympText = this.getSympText();
-        this.getPush(sympText);
         this.checkText = this.$store.state.symptom.text;
       }
-
     },
-    getSympText() {
+    showDetil(item,flg) {//搜索点开的详情
+      this.tmpItem=item
+      this.isSearch=flg||false
+      this.common(item,flg);
+    },
+    touchend(item,flg) {//症状点开详情
+      clearTimeout(this.timer);
+      let endTime = +new Date();
+      if(endTime - this.startTime < 500){//点击事件
+        this.common(item,flg);
+      }
+      this.startTime = "";
+    },
+    getSympText() {//推送使用医生端信息
       const text = this.$store.state.symptom.text;
       let msg = "";
       for (let i in text) {
-        msg += text[i].text;
+        if(text[i] && text[i].text){
+          msg += text[i].text;
+        }
       }
-      return msg;
+      return trimDots(msg);
     },
     getPush(symptoms) {//推理
       const param = {
@@ -214,13 +255,6 @@ export default {
         }
       })
     },
-    closeDetal() {
-      // 推理 
-      const sympText = this.getSympText();
-      this.getPush(sympText);
-      this.show = false;
-      this.questId = null;
-    },
     deletSymp(item, index) {
       this.delIndex = index;
       this.questId = item.questionId || item.id || item.conceptId;
@@ -237,13 +271,14 @@ export default {
       this.$store.commit('setDatas', { type: moduleCP['symp'], pId: this.questId ,data:''})
       // 删除完-常见;其他-推送
       if (this.chooseSymp.length > 0) {
-        const sympText = this.getSympText();
-        this.getPush(sympText);//删除后重新调推理-入参:拼好的内容
+
       } else {
         // 全部删除完 重新走问诊流程
         // this.$router.push("/")
-        this.$router.replace({path:'/'})
-        // this.getSympList();
+        // this.$router.replace({path:'/'})
+        // 停留在当前页 8-19
+        this.quesText = "请问您这次哪里最不舒服?";
+        this.getSympList();
       }
       this.cancelDel();
     },
@@ -253,46 +288,48 @@ export default {
       this.questId = null;
       this.delText = "是否删除该信息?<br/>(已填内容将清除)";
     },
-    complete() {//明细填写完成
-      this.searchShow = false;
-      this.checkText = this.$store.state.symptom.text;
-      this.show = false;
-      this.questId = null;
-      // 推理 
-      const sympText = this.getSympText();
-      this.getPush(sympText);
-    },
     showChecked(item) {
       const origin = this.$store.state.symptom.origin;
       const read = this.$store.state.symptom.datas;
       const data = read[(item.questionId||item.id)] || origin[(item.questionId||item.id)];
-      if (data.questionMapping && data.questionMapping.length > 0) {
-        this.labelDetail = data;
-        this.show = true;
+      if (data&&data.questionMapping && data.questionMapping.length > 0) {
+        this.$store.commit('setDetail',{detail:data,ppId:null,moduleType:moduleCP['symp']})       
       }
     },
-    reload(id) {//清空重新赋值
-      const read = this.$store.state.symptom.datas;
-      const data = read[id];
-      this.labelDetail = data;
-    }
   },
   components: {
     DetailBox,
     Toast,
-    Search
+    Search,
+    Tiptoast
   },
+  watch:{
+    checkText:{//更新推送
+      handler(newVal,oldVal){
+        const sympText = this.getSympText();
+        if(sympText){
+          this.getPush(sympText);
+          this.quesText = "请问您还有其他不适吗?";
+        }else{
+          this.getSympList();
+          this.quesText = "请问您这次哪里最不舒服?";
+        } 
+      },
+      deep:true
+    }
+  }
 }
 </script>
 <style lang="less" scoped>
 @import "../less/base.less";
+
 .symp-wrap {
   font-size: 0.3rem;
+  .btscroll;
   .quest {
     color: #000;
     margin-bottom: 0.36rem;
     font-weight: 700;
-    padding-right: .3rem;
     .searchImg {
       width: 0.44rem;
       height: 0.44rem;
@@ -305,21 +342,17 @@ export default {
   .choo-symp{
       display: inline-block;
       min-width:1.9rem;
-      // min-width:1.42rem;
       height: .74rem;
-      // background: linear-gradient(-270deg, #4F4FFF, #4F8BFF);
       background: linear-gradient(-270deg, #3638EE, #4E72FF);
       box-shadow: 0 .08rem .16rem 0 rgba(79,129,255,0.40);
       border-radius: .08rem;
       white-space: nowrap;
-      // margin: 0 .3rem .3rem 0;
       margin: 0 .25rem .3rem 0;
       span{
         display: inline-block;
         vertical-align: top;
       }
       span:first-child{
-        // min-width:1.34rem;
         min-width:1.42rem;
         height: .74rem;
         line-height: .74rem;
@@ -327,7 +360,6 @@ export default {
         color: #fff;
       }
       img{
-        // width:.56rem;
         width:.48rem;
         height: .74rem;
       }
@@ -366,12 +398,6 @@ export default {
   .footer;
 }
 .nofoot{
-  // opacity: 0.3;
-  // background: linear-gradient(-270deg,#4F4FFF, #4F8BFF);
   background:#CACCFF;
 }
-.detail{
-  .mask;
-  z-index: 66;
-}
 </style>

+ 48 - 25
src/components/TabPage.vue

@@ -4,9 +4,9 @@
       v-if="modlues&&modlues.length>0 && moduleShow">
       <p v-for="(it,index) in modlues"
         :style="{'width':1/modlues.length*100+'%'}"
-        :key="it.id">
+        :key="it.id"
+        @click="clickTab(it,index)">
         <span :class="{current:index==number,comp:finish[it.type]}" v-if="type[it.type]==1">
-          <!-- <i>{{it.type}}</i> -->
           <i>{{index+1}}</i>
           {{it.name}}
         </span>
@@ -42,7 +42,7 @@
           @back="beBack"
         />
         <AddContent
-          v-show="flag == moduleCP['suplement']&&item.type==moduleCP['suplement']&&moduleShow"
+          v-if="flag == moduleCP['suplement']&&item.type==moduleCP['suplement']&&moduleShow"
           :modluesLen="modluesLen"
           :allMoudles="item"
           :preName="modlues[idx-1]&&modlues[idx-1].name"
@@ -58,6 +58,10 @@
         @back="beBack" 
       />
     </div>
+    <!-- 详情页 -->
+    <div class="detail" v-if="this.$store.state.detailShow">
+    <DetailBox />
+    </div>
   </div>
 </template>
 <script type="text/javascript">
@@ -68,12 +72,14 @@ import Others from './Others.vue';
 import Preview from './Preview.vue';
 import {moduleConfig,moduleCP} from '../utils/tools.js';
 import $ from 'jquery';
+import DetailBox from './DetailBox.vue';
 export default {
   name: 'TabPage',
   data() {
     let sysConfig = this.$store.state.sysConfig;
     let tmpAllMoudles = this.$store.state.allMoudles;
     let allMoudles = moduleConfig(sysConfig,tmpAllMoudles);
+    const { choose} = this.$store.state.symptom;
     return {
       config: sysConfig,
       modlues: allMoudles.data,
@@ -94,15 +100,35 @@ export default {
       },
       number:0,
       moduleCP:moduleCP,
+      symChoose:choose
     }
   },
   created() {
-    if (this.config.length == 0) {
-      // this.$router.go(-1)
-      this.$router.replace({path:'/'})
+    if (this.config.length == 0) {//登录进去返回到列表页,扫码返回到开始页
+      let scan = localStorage.getItem('scan');
+      let params = JSON.parse(localStorage.getItem('infoParam'));
+      let param = JSON.parse(localStorage.getItem('loginParam'));
+      let data = JSON.parse(localStorage.getItem('loginData'));
+      if(!scan){
+        if(data.length>1){
+          this.$router.replace({path:'/department'});
+        }else{
+          this.$router.replace({path:'/home',query:param});
+        }
+      }else{
+        this.$router.replace({path:'/home',query:Object.assign({}, params,{scan:true})});
+      }
     }
   },
   methods: {
+    // 症状情况有内容后才可以点击tab栏
+    clickTab(item,index){
+      if(this.symChoose.length>0){
+        this.number = index;
+        this.flag = item.type;
+        this.finish[parseInt(item.type)] = true;
+      }
+    },
     getPreviewName(){
       let len = this.modluesLen,tmpModule = this.modlues;
       let preName = '';
@@ -138,12 +164,7 @@ export default {
       }
       let flag = parseInt(this.flag),num=this.number;
       this.number = ++num;
-      
-      for(let j in this.finish){
-        if(j <= flag){
-          this.finish[j] = true
-        }
-      }
+
       for(let i = 0;i < this.modlues.length;i++){
         let part = this.modlues[i];
         if(part.type == flag){
@@ -152,7 +173,12 @@ export default {
           }
         }
       }
-      $('body').scrollTop(0);
+      
+      for(let j in this.finish){
+        if(j == this.flag){
+          this.finish[j] = true
+        }
+      }
     },
     beBack(preview) {
       if(preview === 'preview'){
@@ -162,18 +188,17 @@ export default {
       let flag = parseInt(this.flag),num=this.number;
       this.number = --num;
 
-      for(let j in this.finish){
-        if(j <= flag){
-          this.finish[j] = true
-        }
-      }
       for(let i = 0;i < this.modlues.length;i++){
         let part = this.modlues[i];
         if(part.type == flag){
           this.flag = this.modlues[i-1].type
         }
       }
-      $('body').scrollTop(0);
+      for(let j in this.finish){
+        if(j == this.flag){
+          this.finish[j] = true
+        }
+      }
     },
     toggleModule(flg){
       this.moduleShow = flg
@@ -184,11 +209,13 @@ export default {
     DiagTreat,
     Others,
     AddContent,
-    Preview
+    Preview,
+    DetailBox
   }
 }
 </script>
 <style lang="less" scoped>
+@import '../less/base.less';
 .tab-wrap {
   width: 100%;
   height: 100%;
@@ -200,7 +227,7 @@ export default {
     left: 0;
     width: 100%;
     background: #fff;
-    z-index: 50;
+    z-index: 101;
     height: 0.82rem;
     line-height: 0.82rem;
     border-bottom: 1px solid #ededed;
@@ -220,8 +247,6 @@ export default {
       line-height: 0.5rem;
       color: #7c828e;
       text-align: center;
-      // margin-left: 0.2rem;
-      // margin-right: 0.19rem;
     }
     .current {
       color: #0043e8;
@@ -234,8 +259,6 @@ export default {
 }
   .content {
     font-size: 0.3rem;
-    // padding: 0.45rem 0.6rem;
-    // padding: 0.45rem 0.3rem 0.45rem 0.6rem;
     padding: 0.45rem 0 0.45rem 0.3rem;
   }
 }

BIN
src/images/bg-title.png


BIN
src/images/down.png


BIN
src/images/icon-go.png


BIN
src/images/icon_close.png


BIN
src/images/icon_close@2x.png


BIN
src/images/logo.png


BIN
src/images/right .png


BIN
src/images/right.png


+ 20 - 7
src/less/base.less

@@ -20,6 +20,7 @@
   position: fixed;
   bottom: 0;
   left: 0;
+  z-index: 1000;
 }
 .dbfooter{
   width:100%;
@@ -27,7 +28,6 @@
   position: fixed;
   bottom: 0;
   left: 0;
-  // background: #F2F2F5;
   background: #e5ecfc;
   z-index: 66;
   display: flex;
@@ -40,14 +40,10 @@
     vertical-align: top;
   }
   .back{
-    // width: 2.5rem;
     width: 40%;
-    // color: #7C828E;
     color: #0043E8;
   }
   .next{
-    // width: 5rem;
-    // width: 4.91rem;
     width: 58%;
     color: #fff;
     background: linear-gradient(-270deg, #4F4FFF,#4F8BFF);
@@ -60,7 +56,6 @@
   padding-bottom: .2rem;
   .symp{
     display: inline-block;
-    // width:1.9rem;
     min-width:1.9rem;
     height: .74rem;
     line-height: .74rem;
@@ -68,7 +63,6 @@
     border-radius: .08rem;
     text-align: center;
     color: #7C828E;
-    // margin: 0 .3rem .3rem 0;
     margin: 0 .25rem .3rem 0;
     padding: 0 .05rem;
     box-sizing: border-box;
@@ -94,4 +88,23 @@
     color: #666;
     line-height: .44rem;
   }
+}
+
+.btscroll {
+  position: fixed;
+  height: 100%;
+  width: 100%;
+  left: 0;
+  padding-left: .3rem;
+  padding-right: .3rem;
+  z-index: 99;
+  box-sizing: border-box;
+  .content {
+    padding-bottom: 2.3rem;
+    box-sizing: border-box;
+  }
+}
+
+.toastWrapper {
+  background-color: #000;
 }

+ 3 - 4
src/less/index.less

@@ -62,14 +62,13 @@ a {
 
 html,body{
   width: 100%;
-  // height: auto !important;
-  height: auto;
-  overflow-y: auto;
+  height: 100%;
+  position: absolute;
+  overflow: hidden;
 }
 html{
   margin: 0;
   padding: 0;
-  // font-size: @font-size;  //750px,1vw = 750*1%=7.5px
   font-size: 13.33333333vw !important;
 }
 

+ 4 - 1
src/main.js

@@ -4,6 +4,8 @@ import store from './store.js';
 import App from './App.vue';
 import preview from 'vue-photo-preview';
 import 'vue-photo-preview/dist/skin.css';
+import PortalVue from 'portal-vue';
+Vue.use(PortalVue);
 Vue.use(preview);
 Vue.config.productionTip = false;
 
@@ -15,4 +17,5 @@ new Vue({
     App
   },
   template:'<App/>'
-});
+});
+

+ 17 - 0
src/router/index.js

@@ -2,11 +2,18 @@ import Vue from 'vue';
 import Router from 'vue-router';
 import PathInfo from '@components/PathInfo.vue';
 import TabPage from '@components/TabPage.vue';
+import Login from '@components/Login.vue';
+import Department from '@components/Department.vue';
 Vue.use(Router);
 const router = new Router({
   routes:[
     {
       path:'/',
+      name:'Login',
+      component:Login
+    },
+    {
+      path:'/home',
       name:'PathInfo',
       component:PathInfo
     },
@@ -14,6 +21,16 @@ const router = new Router({
       path:'/tab',
       name:'TabPage',
       component:TabPage
+    },
+    /*{
+      path:'/login',
+      name:'Login',
+      component:Login
+    },*/
+    {
+      path:'/department',
+      name:'Department',
+      component:Department
     }
   ]
 })

+ 78 - 31
src/store.js

@@ -5,6 +5,7 @@ Vue.use(Vuex);
 
 const store = new Vuex.Store({
   state:{
+    searchShow:false,
     pathInfo:{}, //患者信息-后续提交要用
     sysConfig:[], //系统配置项
     allMoudles:[], //模板
@@ -33,7 +34,9 @@ const store = new Vuex.Store({
       txt:'',
       txtDoc:''
     },
-    loadingShow:false
+    loadingShow:false,
+    detailInfo:{},
+    detailShow:false
   },
   mutations:{
     initAllData(state){
@@ -63,6 +66,18 @@ const store = new Vuex.Store({
         txtDoc:''
       }
     },
+    setDetail(state,param){//明细
+      const detail = param.detail;
+      if(JSON.stringify(detail)=='{}'){
+        state.detailShow = false;
+      }else{
+        state.detailInfo = Object.assign({},param);
+        state.detailShow = true;
+      }
+    },
+    setSearchShow(state,flg){//搜索显示与否
+      state.searchShow = flg;
+    },
     setDataAll(state,param){
       let res = state.allMoudles
       for(let i = 0;i<res.length;i++){
@@ -197,36 +212,63 @@ const store = new Vuex.Store({
           }
           break;
         case moduleCP['diagT']: //诊疗情况
-          let diaText = state.diagnose.text;
-          if(diaText.length > 0){
-            for(let i in diaText){
-              if(diaText[i].pId==param.pId){
-                if(param.flag){
-                  diaText.splice(i,1,param);
+          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;
                 }
-                return
+              }
+            }else{
+              if(param.flag){
+                diaText[param.order] = param;
               }
             }
-            diaText.push(param);
           }else{
-            diaText.push(param);
+            if(param.arrFlag){
+              let temp = [];
+              temp[param.index] = param;
+              diaText[param.order] = temp;
+            }else{
+              diaText[param.order] = param;
+            }
           }
+          state.diagnose.text = diaText;
           break;
         case moduleCP['other']: //其他情况
-          let otherText = state.others.text;
-          if(otherText.length > 0){
-            for(let i in otherText){
-              if(otherText[i].pId==param.pId){
-                if(param.flag){
-                  otherText.splice(i,1,param);
+          let otherText = JSON.parse(JSON.stringify(state.others.text));
+          let oitem = otherText[param.order];
+          if(oitem){
+            // 判断是对象还是数组--数组则区分index
+            if(Array.isArray(oitem)){
+              if(param.flag){//详情完成-覆盖
+                oitem[param.index] = param;
+              }else{ //直接点label--无则覆盖
+                if(!oitem[param.index]){
+                  oitem[param.index] = param;
                 }
-                return
+              }
+            }else{
+              if(param.flag){
+                otherText[param.order] = param;
               }
             }
-            otherText.push(param);
           }else{
-            otherText.push(param);
+            if(param.arrFlag){
+              let temp = [];
+              temp[param.index] = param;
+              otherText[param.order] = temp;
+            }else{
+              otherText[param.order] = param;
+            }
           }
+          state.others.text = otherText;
           break;
         case moduleCP['suplement']:
           let addText = state.addContent.txt
@@ -250,20 +292,16 @@ const store = new Vuex.Store({
           }
           break;
         case moduleCP['diagT']: //诊疗情况
-          let diaText = state.diagnose.text;
-          for(let i in diaText){
-            if(diaText[i].pId==param.pId){
-              diaText.splice(i,1)
-            }
-          }
+          let diaText = JSON.parse(JSON.stringify(state.diagnose.text));
+          let temp = diaText[param.order];
+          temp[param.index] = null;
+          state.diagnose.text = diaText;
           break;
         case moduleCP['other']:
-          let otherText = state.others.text;
-          for(let i in otherText){
-            if(otherText[i].pId==param.pId){
-              otherText.splice(i,1)
-            }
-          }
+          let otherText = JSON.parse(JSON.stringify(state.others.text));
+          let otemp = otherText[param.order];
+          otemp[param.index] = null;
+          state.others.text = otherText;
           break;
         case moduleCP['suplement']:
 
@@ -275,6 +313,15 @@ const store = new Vuex.Store({
     setChoose(state,param){ //症状情况-已选症状
       state.symptom.choose = param.choose;
     },
+    delChoose(state,param){ //详情有必填项未填--移除症状
+      const id = param.id;
+      let symp = state.symptom.choose;
+      for(let i=0; i<symp.length; i++){
+        if(id == (symp[i].id || symp[i].questionId)){
+          symp.splice(i,1);
+        }
+      }
+    },
     setImgFile(state,param){//区别模块
       const type = parseInt(param.type);
       switch(type){

+ 4 - 0
src/utils/api.js

@@ -12,6 +12,7 @@ const urls = {
   uploadImageThum:'/api/prec/file/uploadImageThum',//单个文件上传同时生成缩略图
   uploadImageThums:'/api/prec/file/uploadImageThums',//多个文件上传同时生成缩略图
   getTagInfos:'/api/prec/retrieval/getTagInfos',//检索
+  signIn:'/api/prec/patientInfo/signIn',//登录
   // uploadImageThums:'http://192.168.3.1:8849/file/uploadImageThums',//多个文件上传同时生成缩略图
 }
 
@@ -49,4 +50,7 @@ export default {
   saveInquiry(param){
     return axios.post(urls.saveInquiry,param)
   },
+  signIn(param){
+    return axios.post(urls.signIn,param)
+  },
 }

+ 119 - 39
src/utils/tools.js

@@ -1,13 +1,13 @@
 
 const qs = require('qs');
 const $ = require('jquery');
-const imageUrlPrefix = 'http://223.93.170.82:10082';//'http://192.168.2.121:82' //后台图片地址
+const imageUrlPrefix = 'http://192.168.2.241:82' //后台图片地址
 // const imageUrlPrefix = 'http://192.168.2.236:82' //后台图片地址
 
 const getUrlArgObject = (parm) => {
     let query = window.location.search;
     let args = qs.parse(query.substr(1));
-    return args[parm];//返回对象
+    return args[parm];//返回对象  
 }
 
 const deepClone = (arr) =>{
@@ -107,14 +107,36 @@ const getModelExpStr = (str,txt,des) =>{
 
 // 替换输入框占位符
 const patt = /\$\{[^\]]+\}/g;
+// 手机号验证
+const phoneTest = /^[1]([3-9])[0-9]{9}$/;
+//身份证验证
+/**15位
+ * [1-9]\d{5}                  前六位地区,非0打头    
+ * \d{2}                       出生年份后两位00-99
+ * ((0[1-9])|(10|11|12))       月份,01-12月
+ * (([0-2][1-9])|10|20|30|31)  日期,01-31天
+ * \d{2}[0-9Xx]                顺序码两位,一位校验码最后一位数字或者大小写X
+ */
+/**18位
+ * 
+ * 
+ * [1-9]\d{5}                 前六位地区,非0打头
+ * (18|19|([23]\d))\d{2}      出身年份,覆盖范围为 1800-3999 年
+ * ((0[1-9])|(10|11|12))      月份,01-12月
+ * (([0-2][1-9])|10|20|30|31) 日期,01-31天
+ * \d{3}[0-9Xx]:              顺序码三位, 一位校验码数字或者大小写X
+ */
+const identify = /(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}[0-9Xx]$)|(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)/;
+//只能是数字和字母
+const jgpattern = /^[A-Za-z0-9]+$/;
 
 const getAllStr = (allData) =>{//获取界面数据,拼接字符串
   // console.log(allData,777777)
   let allStr = '',data = allData.data,allStrDoc = '',obj={};
   for(let i = 0;i < data.length;i++){
     if(data[i].controlType != 3&&data[i].value){
-        allStr += (data[i].valueP).replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,'')+';'
-        allStrDoc += (data[i].value).replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,'')+';'
+        allStr += (data[i].valueP).replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,'')+''
+        allStrDoc += (data[i].value).replace(patt,'').replace(/\#\{/g,'').replace(/\}/g,'')+''
     }
     if(data[i].controlType == 3){//多列选择
       let tmpStr = '',tmpDoc='';
@@ -122,16 +144,16 @@ const getAllStr = (allData) =>{//获取界面数据,拼接字符串
         let tmpName = data[i].questionDetailList[j]
         if(tmpName&&tmpName.value&&tmpName.value!='/'){
           let obj = getModelExpStr(tmpName.name,'',tmpName.description)
-          tmpStr+=obj.prefix+tmpName.valueP+obj.suffix+(j ==(data[i].questionDetailList.length-1)?';':',')
-          tmpDoc+=obj.prefix+tmpName.value+obj.suffix+(j ==(data[i].questionDetailList.length-1)?';':',')
+          tmpStr+=obj.prefix+tmpName.valueP+obj.suffix+','
+          tmpDoc+=obj.prefix+tmpName.value+obj.suffix+','
         }
       }
       allStr+=tmpStr
       allStrDoc+=tmpDoc
     }
   }
-  obj.allStr = trimDots(allStr)
-  obj.allStrDoc = trimDots(allStrDoc)
+  obj.allStr = trimDots(allStr.replace(/,$/,''))
+  obj.allStrDoc = trimDots(allStrDoc.replace(/,$/,''))
   return obj;
 }
 
@@ -209,53 +231,69 @@ function fixedKeyboard() {
         setTimeout(() => {
           activeElement.scrollIntoView(true);
           let top = $('.main').scrollTop();
+          let tops = $('.detailBoxMain').css("transform").replace(/[^0-9\-,]/g,'').split(',')[5];
+          console.log(tops,4444)
           $('.main').scrollTop(top-30); //预留题目位置
+          $('.detailBoxMain').css({"transform":'translate(0px, -'+tops+'"30") scale(1) translateZ("0px")'}); // translate(0px, -47px) scale(1) translateZ(0px);
+
         }, 400);
       }
-    }
+    }  
   })
 }
 
 // 移动到可视区--选项中的输入框,因阻止了冒泡
 function scrollToV(e){
-  setTimeout(function() {
-    // e.target.scrollIntoView(false);
-    e.target.scrollIntoView(true); //true--元素顶部与可视区顶部对齐;false--元素底部与可视区底部对齐
-    let mainH = $('.main').height();
-    let top = $('.main').scrollTop();
-    $('.main').scrollTop(top-30); //预留题目位置
-    /*let HH = mainH-clientY;
-    if(clientY < 210 || (mainH-clientY)>88){
-      e.target.scrollIntoView(false); //底部对齐
-    }else if(HH < 200){
-      e.target.scrollIntoView(true);//顶部对齐
-    }
-    else{
-      e.target.scrollIntoView();
-    }*/
-  }, 400)
+  // setTimeout(function() {
+  //   // e.target.scrollIntoView(false);
+  //   e.target.scrollIntoView(true); //true--元素顶部与可视区顶部对齐;false--元素底部与可视区底部对齐
+  //   let mainH = $('.main').height();
+  //   let top = $('.main').scrollTop();
+  //   $('.main').scrollTop(top-30); //预留题目位置
+  //   /*let HH = mainH-clientY;
+  //   if(clientY < 210 || (mainH-clientY)>88){
+  //     e.target.scrollIntoView(false); //底部对齐
+  //   }else if(HH < 200){
+  //     e.target.scrollIntoView(true);//顶部对齐
+  //   }
+  //   else{
+  //     e.target.scrollIntoView(); 
+  //   }*/
+  // }, 400)
 }
 
 function trimDots(str){
-  return str.replace(/[,,.。::"“??”;;、!!]+/g,function(word){
+  return str.replace(/[,,.。::"“??”‘’'';;、!!]+/g,function(word){
     return word.substr(0,1);
-  }).replace(/^[,,.。::"“??”;;、!!\s]+/,'');
+  }).replace(/^[,,.。::"“??”‘’'';;、!!\s]+/,'');
 }
 
 // 拼值,并去掉占位符
-function concatVal(data){
+function concatVal(data,flg){
   let value = ""; //医生
   let valueP = ""; //患者
-  for(let k in data){
-    if(data[k].select==1){
-      if(data[k].value){
-        let str = data[k].name.replace(patt,data[k].value);
-        let strP = (data[k].description || data[k].name).replace(patt,data[k].value);
-        value += str + ',';
-        valueP += strP + ',';
-      }else{
-        value += data[k].name.replace(patt,'') + ',';
-        valueP += (data[k].description || data[k].name).replace(patt,'') + ',';
+  let tmpStrHas = [],tmpStrNo = [],tmpAll=[];
+  if(flg){
+    tmpStrHas = data.filter((item)=>item.select == 1)
+    tmpStrNo = data.filter((item)=>item.select == 2)
+    tmpAll = tmpStrHas.concat(tmpStrNo)
+    for(let k in tmpAll){
+      let tmpStr = tmpAll[k].select==1?'有':'无';
+      value += tmpStr+tmpAll[k].name.replace(patt,'') + ',';
+      valueP += tmpStr+(tmpAll[k].description || tmpAll[k].name).replace(patt,'') + ',';
+    }
+  }else{
+    for(let k in data){
+      if(data[k].select){
+        if(data[k].value){
+          let str = data[k].name.replace(patt,data[k].value);
+          let strP = (data[k].description || data[k].name).replace(patt,data[k].value);
+          value += str + ',';
+          valueP += strP + ',';
+        }else{
+          value += data[k].name.replace(patt,'') + ',';
+          valueP += (data[k].description || data[k].name).replace(patt,'') + ',';
+        }
       }
     }
   }
@@ -263,6 +301,42 @@ function concatVal(data){
   return {value:value?value.substring(0,value.length-1):'',valueP:valueP?valueP.substring(0,valueP.length-1):''};
 }
 
+function setScroll(scroll,flg,wrapper){
+  return new scroll(wrapper?wrapper:'.wrapper',{
+      scrollY: flg,
+      click: true,
+      probeType:3,
+      bounceTime:500
+  })
+}
+
+function compare(property){
+  return function(obj1,obj2){
+      var value1 = (new Date(obj1[property].replace(/\-/g, "/"))).getTime();
+      var value2 = (new Date(obj2[property].replace(/\-/g, "/"))).getTime();
+      return value1 - value2;
+  }
+}
+
+// 时间戳转换日期
+function dateParser(timestamp,link = '-'){
+  if(!timestamp){
+    return ''
+  }
+  if(timestamp.length == 10){
+    timestamp = timestamp*1000
+  }
+  let time = new Date(timestamp-0);
+  let year = time.getFullYear();
+  let month = time.getMonth()+1;
+  let date = time.getDate();
+  let hour = time.getHours().toString().padStart(2,'0');
+  let minute = time.getMinutes().toString().padStart(2,'0');
+  let second = time.getSeconds().toString().padStart(2,'0');
+  let result = year+link+(month<10?"0"+month:month)+link+(date<10?"0"+date:date)+' '+hour+':'+minute+':'+second;
+  return result;
+}
+
 module.exports =  {
   imageUrlPrefix,
   getUrlArgObject,
@@ -278,7 +352,13 @@ module.exports =  {
   isIos,
   trimDots,
   concatVal,
-  isWX
+  setScroll,
+  isWX,
+  phoneTest,
+  identify,
+  jgpattern,
+  compare,
+  dateParser
 }