Symptom.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. <template>
  2. <div class="symp-wrap symper btscroll">
  3. <div class="content">
  4. <p class="quest" v-if="chooseSymp.length>0">已选症状</p>
  5. <div
  6. class="choose"
  7. v-if="chooseSymp.length>0"
  8. >
  9. <p
  10. class="choo-symp"
  11. v-for="(v,i) in chooseSymp"
  12. >
  13. <span @click="showChecked(v,i)">{{v.description || v.name}}</span>
  14. <span @click="deletSymp(v,i)"><img
  15. src="../images/del.png"
  16. alt=""
  17. ></span>
  18. </p>
  19. </div>
  20. <div class="label">
  21. <p class="quest" id="test">{{quesText}}<img
  22. @click="search(true)"
  23. class="searchImg"
  24. src="../images/search.png"
  25. alt=""
  26. ></p>
  27. <div class="showHide" ref="showHide">
  28. <span
  29. class="symp"
  30. v-for="(it,ind) in symp"
  31. :key="it.conceptId"
  32. @touchstart.prevent="touchstart(it,ind)"
  33. @touchend.prevent="touchend(it,ind+1)"
  34. >{{it.description || it.name}}</span>
  35. </div>
  36. <p class="tip" v-show="chooseSymp.length==0">长按症状按钮可显示症状解释说明 <span @click="slideToggle" v-show="slide">{{slideTxt}}</span></p>
  37. </div>
  38. <div
  39. class="result"
  40. v-if="checkText.length>0"
  41. >
  42. <p class="title"><span class="line"></span>{{nameStr}}</p>
  43. <div class="bgResult">
  44. <template v-for="(value,index) in checkText">
  45. <!-- 患者于时间单位前诱因出现症状,其余题目的内容; -->
  46. <span :key="index" v-if="index==0">{{(value.idx==1?'':'伴')+value.textP}}{{checkText.length==1?'':','}}</span>
  47. <span :key="index" v-if="index==1">{{(checkText[0].idx == 1?'伴':'')+value.textP}}{{checkText.length==2?'':'、'}}</span>
  48. <span :key="index" v-if="index>1">{{value.textP}}{{index == checkText.length-1?'':'、'}}</span>
  49. </template>
  50. </div>
  51. </div>
  52. </div>
  53. <div v-if="modluesLen>1"
  54. @click="toNext"
  55. class="footer"
  56. >
  57. <div class="nextBtn" :class="{'nofoot':chooseSymp.length==0}">下一步</div>
  58. </div>
  59. <div v-if="modluesLen==1"
  60. class="footer"
  61. @click="toNext"
  62. >
  63. <div class="nextBtn" :class="{'nofoot':chooseSymp.length==0}">预览并提交病历</div>
  64. </div>
  65. <Toast
  66. :message="delText"
  67. :show="showToast"
  68. @comfirn="comfirnDel"
  69. @cancel="cancelDel"
  70. />
  71. <Submit v-if="submit" showType="fail" :fail="failMsg" @showSubmit="showSubmit"></Submit>
  72. <Search
  73. v-if="this.$store.state.searchShow"
  74. @search="search"
  75. @showDetil="showDetil"
  76. :age="age"
  77. :chooseSymp="chooseSymp"
  78. :sexType="sexType"
  79. ></Search>
  80. <Tiptoast :show="showExp" :data="message" @close="closeTip"/>
  81. </div>
  82. </template>
  83. <script type="text/javascript">
  84. import api from '@utils/api.js';
  85. import Toast from '../common/Toast.vue';
  86. import Tiptoast from '../common/Tiptoast.vue';
  87. import Search from './Search.vue';
  88. import {moduleCP,setScroll,trimDots} from '@utils/tools'
  89. import Submit from "../common/Submit";
  90. import BScroll from 'better-scroll';
  91. import $ from 'jquery';
  92. export default {
  93. name: 'Symptom',
  94. props:['modluesLen','nameStr'],
  95. data() {
  96. let { datas, pathInfo,searchShow } = this.$store.state;
  97. const { choose, text } = this.$store.state.symptom;
  98. return {
  99. age: pathInfo.patientAge,
  100. sexType: pathInfo.patientSex == '男' ? 1 : (pathInfo.patientSex == '女' ? 2 : 3),
  101. deptName: pathInfo.selfDeptName,
  102. hosCode: pathInfo.hospitalCode,
  103. chooseSymp: choose, //已选症状
  104. symp: [], //症状
  105. labelDetail: {}, //明细
  106. checkText: text, //症状情况文字
  107. questId: null, //id
  108. delText: "是否删除该信息?<br/>(已填内容将清除)",
  109. delIndex: null,
  110. showToast: false,
  111. searchShow: searchShow,//显示搜索界面
  112. tmpItem:{},//检索的症状
  113. isSearch:false,
  114. scroll:null,
  115. quesText:"请问您这次哪里最不舒服?",
  116. startTime:'',
  117. timer:null,
  118. showExp:false,
  119. message:{
  120. title:'',
  121. text:''
  122. },
  123. submit:false,
  124. start:{},
  125. end:{},
  126. slide:false,
  127. slideTxt:'展开',
  128. failMsg: "无法选择症状,已超过最大个数",
  129. }
  130. },
  131. created() {
  132. if (this.chooseSymp.length > 0) {
  133. this.quesText = "请问您还有其他不适吗?";
  134. // 推送
  135. const sympText = this.getSympText();
  136. this.getPush(sympText);
  137. } else {
  138. this.getSympList(); //常见
  139. }
  140. },
  141. mounted(){
  142. this.$nextTick(()=>{
  143. let scroll = setScroll(BScroll,true,'.symper')
  144. this.scroll = scroll
  145. scroll.on('scroll', this.onScroll)
  146. })
  147. },
  148. watch:{
  149. checkText:{//更新推送
  150. handler(newVal,oldVal){
  151. const sympText = this.getSympText();
  152. if(sympText){
  153. if(this.chooseSymp.length>1||localStorage.getItem("staticSymp")){
  154. this.getPush(sympText);
  155. }
  156. this.quesText = "请问您还有其他不适吗?";
  157. }else{
  158. this.getSympList();
  159. this.quesText = "请问您这次哪里最不舒服?";
  160. }
  161. },
  162. deep:true
  163. }
  164. },
  165. methods: {
  166. showSubmit(flg){
  167. this.submit = flg;
  168. },
  169. slideToggle(){
  170. let flg = this.slideTxt;
  171. if(flg == '展开'){
  172. this.$refs.showHide.style.height = 'auto'
  173. this.slideTxt = '收起'
  174. }else{
  175. this.$refs.showHide.style.height = '3rem'
  176. this.slideTxt = '展开'
  177. }
  178. },
  179. touchend(item,flg) {//症状点开详情
  180. clearTimeout(this.timer);
  181. this.end = this.$store.state.scroll
  182. if(JSON.stringify(this.start) != JSON.stringify(this.end)){
  183. return
  184. }
  185. let endTime = +new Date();
  186. if(endTime - this.startTime < 500){//点击事件
  187. if(this.chooseSymp.length == 0){
  188. item.idx = 1
  189. }
  190. this.common(item,flg);
  191. this.slideTxt = '展开'
  192. }
  193. this.startTime = "";
  194. },
  195. touchstart(it){
  196. this.start = this.$store.state.scroll
  197. this.startTime = +new Date();
  198. const that = this;
  199. this.timer = setTimeout(function(){
  200. // 长按事件
  201. that.showExp = true;
  202. if(it.explains){
  203. that.message.title = it.description || it.name;
  204. that.message.text = it.explains;
  205. }else{
  206. that.message.title = "";
  207. that.message.text = "暂无资料";
  208. }
  209. },600)
  210. },
  211. closeTip(){
  212. this.showExp = false,
  213. this.message.title = '';
  214. this.message.text = '';
  215. },
  216. onScroll(data) {
  217. this.$store.commit('setScroll', data);
  218. document.activeElement.scrollIntoViewIfNeeded(true);
  219. },
  220. search(flg) {
  221. this.$store.commit('setSearchShow', flg);
  222. },
  223. getSympList() {
  224. const param = {
  225. "age": this.age,
  226. "deptName": this.deptName,
  227. "sexType": this.sexType
  228. }
  229. api.getSymptom(param).then((res) => {
  230. const result = res.data;
  231. if (result.code == 0) {
  232. this.symp = result.data;
  233. if(result.data.length>9){
  234. this.slide = true
  235. }else{
  236. this.slide = false
  237. }
  238. }
  239. })
  240. },
  241. toNext() {
  242. // 把1切换成完成图标,且2高亮--判断有几个模块显示,1个--提交预览;1个以上--下一步
  243. if (this.chooseSymp.length == 0) { return }
  244. // 把症状情况的数据存起-已选
  245. this.$store.commit('setChoose', { choose: this.chooseSymp, type: moduleCP['symp'] });
  246. if(this.modluesLen==1){
  247. this.$emit('next','preview')
  248. }else{
  249. this.$emit('next');
  250. }
  251. },
  252. common(item,flg,sign){
  253. if(this.chooseSymp.length>12){
  254. this.$store.commit('setSearchShow', false);
  255. this.submit = true
  256. let timer = setTimeout(() => {
  257. this.submit = false;
  258. clearTimeout(timer);
  259. }, 2000);
  260. return
  261. }
  262. this.questId = item.questionId || item.id || item.conceptId;
  263. const id = item.questionId || item.id; //常见症状questionId,推送id,两者均有可能没有
  264. //将选中的name存到store中的text
  265. if (id&&this.chooseSymp.length == 0) {//只有第一次
  266. const param = {
  267. "age": this.age,
  268. "id": id,
  269. "sexType": this.sexType
  270. }
  271. localStorage.setItem("staticSymp",null)
  272. this.$store.commit('setText', { type: moduleCP['symp'], text: (this.chooseSymp.length == 0?'患者出现':'')+item.name,textP: (this.chooseSymp.length == 0?'患者出现':'')+(item.description||item.name), pId: this.questId,idx:this.chooseSymp.length == 0?1:'' });
  273. api.getById(param).then((res) => {
  274. const result = res.data;
  275. if (result.code == 0) {
  276. const mapping = result.data.questionMapping;
  277. this.labelDetail = result.data;
  278. if(this.chooseSymp.length == 0){
  279. result.data.idx = 1
  280. }
  281. this.$store.commit('setOrigin', { type: moduleCP['symp'], data: result.data });
  282. if (mapping && mapping.length > 0) {
  283. let numPlus = 0;
  284. let signNum = 1;//第一个打标的,保存为伴随
  285. for(let i = 0;i < mapping.length;i++){
  286. let tmpMap = mapping[i]
  287. if(tmpMap.flag == 3 && signNum == 1){
  288. ++signNum
  289. for(let j = 0;j < tmpMap.questionDetailList.length;j++){
  290. tmpMap.questionDetailList[j].questionId = tmpMap.questionDetailList[j].name
  291. }
  292. localStorage.setItem("staticSymp",JSON.stringify(tmpMap.questionDetailList))
  293. }
  294. }
  295. if(numPlus == mapping.length){
  296. localStorage.setItem("staticSymp",null)
  297. }
  298. this.$store.commit('setDetail',{detail:result.data,ppId:null,moduleType:moduleCP['symp'],sign:1,idx:this.chooseSymp.length})
  299. if(sign){
  300. return
  301. }
  302. this.$store.commit('setSearchShow', false);
  303. this.chooseSymp.push(item);
  304. } else {
  305. this.$store.commit('setSearchShow', false);
  306. this.chooseSymp.push(item);
  307. }
  308. const sympText = this.getSympText();
  309. this.getPush(sympText);
  310. }
  311. }).catch(()=>{
  312. if(this.chooseSymp.length == 1){
  313. const sympText = this.getSympText();
  314. this.getPush(sympText);
  315. }
  316. })
  317. } else {//没有questionId或id
  318. if(this.chooseSymp.length == 0){
  319. item.idx = 1
  320. }
  321. this.$store.commit('setText', { type: moduleCP['symp'], text: (this.chooseSymp.length == 0?'患者出现':'')+item.name,textP: (this.chooseSymp.length == 0?'患者出现':'')+(item.description||item.name), pId: this.questId,idx:this.chooseSymp.length == 0?1:'' });
  322. this.$store.commit('setSearchShow', false);
  323. this.chooseSymp.push(item);
  324. const sympText = this.getSympText();
  325. this.getPush(sympText);
  326. // this.checkText = this.$store.state.symptom.text;
  327. }
  328. },
  329. showDetil(item,flg) {//搜索点开的详情
  330. this.tmpItem=item
  331. this.isSearch=flg||false
  332. let num = this.chooseSymp.length+1;
  333. this.common(item,num,flg);
  334. },
  335. getSympText() {//推送使用医生端信息
  336. const text = this.$store.state.symptom.text;
  337. let msg = "";
  338. for (let i in text) {
  339. if(text[i] && text[i].text){
  340. msg += text[i].text;
  341. }
  342. }
  343. return trimDots(msg);
  344. },
  345. getPush(symptoms) {//推理
  346. const param = {
  347. "age": this.age,
  348. "hosCode": this.hosCode,
  349. "sex": this.sexType,
  350. "symptom": symptoms //症状+选择的明细,string
  351. }
  352. api.getPush(param).then((res) => {
  353. const result = res.data;
  354. if (result.code == 0) {
  355. let symp = result.data.symptom||[];
  356. let symped = JSON.parse(JSON.stringify(this.chooseSymp));//已选症状
  357. let sympStic = JSON.parse(localStorage.getItem('staticSymp'))||[];//首次有无症状
  358. let sympAll = sympStic.concat(symp);
  359. var obj = {};
  360. sympAll = sympAll.reduce(function(item, next) {
  361. obj[next.name] ? '' : obj[next.name] = true && item.push(next);
  362. return item;
  363. }, []);
  364. for(let i = 0;i < symped.length;i++){//去掉已选的已选症状
  365. for(let j = 0;j < sympAll.length;j++){//去掉
  366. if(sympAll[j].name == symped[i].name){
  367. sympAll.splice(j,1)
  368. }
  369. }
  370. }
  371. this.symp = sympAll.slice(0,12);
  372. this.$refs.showHide.style.height = 'auto'
  373. }
  374. }).catch(()=>{
  375. })
  376. },
  377. deletSymp(item, index) {
  378. this.delIndex = index;
  379. this.questId = item.questionId || item.id || item.conceptId;
  380. if (this.chooseSymp.length == 1) {
  381. if(item.idx != 1){
  382. this.delText = "是否删除该信息?<br/>删除后将重新填写预问诊流程 <br/>"
  383. }else{
  384. this.delText = "是否删除该信息?<br/>删除后将重新填写预问诊流程 <br/>(已填内容将清除)"
  385. }
  386. }else{
  387. if(item.idx != 1){
  388. this.delText = "是否删除该信息?"
  389. }
  390. }
  391. this.showToast = true;
  392. $(".btscroll").css({'position':'fixed'})
  393. $(".foot").css({'position':'fixed','bottom':'0'})
  394. },
  395. comfirnDel() {
  396. $(".btscroll").css({'position':'absolute','top':'0'})
  397. $(".foot").css({'position':'absolute','bottom':'0'})
  398. this.chooseSymp.splice(this.delIndex, 1);
  399. this.checkText.splice(this.delIndex, 1);
  400. this.$store.commit('delText', { type: moduleCP['symp'], pId: this.questId })
  401. // 删除setDatas数据,防止回读
  402. this.$store.commit('setDatas', { type: moduleCP['symp'], pId: this.questId ,data:''})
  403. // 删除完-常见;其他-推送
  404. if (this.chooseSymp.length > 0) {
  405. } else {
  406. // 全部删除完 重新走问诊流程
  407. // this.$router.push("/")
  408. // this.$router.replace({path:'/'})
  409. // 停留在当前页 8-19
  410. this.quesText = "请问您这次哪里最不舒服?";
  411. this.getSympList();
  412. }
  413. this.cancelDel();
  414. },
  415. cancelDel() {
  416. $(".btscroll").css({'position':'absolute','top':'0'})
  417. $(".foot").css({'position':'absolute','bottom':'0'})
  418. this.showToast = false;
  419. this.delIndex = null;
  420. this.questId = null;
  421. this.delText = "是否删除该信息?<br/>(已填内容将清除)";
  422. },
  423. showChecked(item,i) {
  424. const origin = this.$store.state.symptom.origin;
  425. const read = this.$store.state.symptom.datas;
  426. const data = read[(item.questionId||item.id)] || origin[(item.questionId||item.id)];
  427. if (data&&data.questionMapping && data.questionMapping.length > 0) {
  428. this.$store.commit('setDetail',{detail:data,ppId:null,moduleType:moduleCP['symp'],sign:1,idx:i})
  429. }
  430. },
  431. },
  432. components: {
  433. Toast,
  434. Search,
  435. Tiptoast,
  436. Submit
  437. }
  438. }
  439. </script>
  440. <style lang="less" scoped>
  441. @import "../less/base.less";
  442. .showHide {
  443. overflow: hidden;
  444. height: 3rem;
  445. }
  446. .tip span {
  447. color: #colors[theme];
  448. float: right;
  449. font-size: .28rem;
  450. }
  451. .symp-wrap {
  452. font-size: 0.3rem;
  453. .quest {
  454. color: #colors[quest];
  455. margin-bottom: 0.36rem;
  456. font-weight: 700;
  457. .searchImg {
  458. width: 0.44rem;
  459. height: 0.44rem;
  460. float: right;
  461. }
  462. }
  463. }
  464. .choose{
  465. padding-bottom: .2rem;
  466. .choo-symp{
  467. display: inline-block;
  468. min-width:2rem;
  469. height: .74rem;
  470. background: #colors[btn];
  471. border-radius: .08rem;
  472. white-space: nowrap;
  473. margin: 0 .25rem .3rem 0;
  474. span{
  475. display: inline-block;
  476. vertical-align: top;
  477. }
  478. span:first-child{
  479. min-width:1.42rem;
  480. height: .74rem;
  481. line-height: .74rem;
  482. text-align: center;
  483. color: #fff;
  484. }
  485. img{
  486. width:.48rem;
  487. height: .74rem;
  488. }
  489. }
  490. .choo-symp:nth-child(3n+3){
  491. margin-right: 0;
  492. }
  493. .label{
  494. .label;
  495. }
  496. .result{
  497. padding-right: .3rem;
  498. // .title{
  499. // color: #colors[btn];
  500. // padding-left: .1rem;
  501. // margin-bottom: .19rem;
  502. // font-weight: 700;
  503. // }
  504. p{
  505. color: #666;
  506. line-height: .44rem;
  507. }
  508. }
  509. .footer{
  510. .footer;
  511. }
  512. }
  513. .label{
  514. .label;
  515. }
  516. .result{
  517. .result;
  518. }
  519. .footer{
  520. .footer;
  521. }
  522. .nofoot{
  523. background:#CACCFF!important;
  524. }
  525. </style>