浏览代码

新增踢出电子病历正在编辑的人员操作,以及修复恢复的功能。

xiaochan 2 年之前
父节点
当前提交
a3b7109e08

+ 10 - 0
src/api/zhu-yuan-yi-sheng/emr-socket.js

@@ -32,6 +32,16 @@ export function isThereADoctorEditing(sid) {
     })
 }
 
+export function forcedKickingOutOfPersonnelByDocumentId(documentId) {
+    return request({
+        url: '/emrSocket/forcedKickingOutOfPersonnelByDocumentId',
+        method: 'get',
+        params: {documentId}
+    })
+}
+
+
+
 export function repeatedlyOpenTheSamePatient(sid) {
     return request({
         url: '/emrSocket/repeatedlyOpenTheSamePatient',

+ 0 - 3
src/components/zhu-yuan-yi-sheng/emr/EmrSidebar.vue

@@ -44,8 +44,6 @@
           </span>
         </template>
       </el-tree>
-
-
     </div>
     <right-click-menu :mouse-position="mousePosition" :config="opt"/>
   </div>
@@ -193,7 +191,6 @@ const handleNodeClick = async (val, node, parent, event) => {
         times: props.huanZheXinXi.admissTimes
       });
     }
-
   }
   if (val.children) {
     return

+ 9 - 7
src/components/zhu-yuan-yi-sheng/emr/HistoricalEmr.vue

@@ -41,14 +41,16 @@
 </template>
 
 <script setup name='HistoricalEmr' lang="ts">
-import XcDialogV2 from "@/components/xiao-chan/dialog/XcDialogV2.vue";
+import XcDialogV2 from "../../../components/xiao-chan/dialog/XcDialogV2.vue";
 import {nextTick, onMounted, ref} from "vue";
-import {EMRInteractive} from '@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/emr-init'
-import {getHistory} from '@/api/zhu-yuan-yi-sheng/emr-patient'
-import {getFormatDatetime} from '@/utils/date'
+import {
+  EMRInteractive
+} from '../../../views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/emr-init'
+import {getHistory} from '../../../api/zhu-yuan-yi-sheng/emr-patient'
+import {getFormatDatetime} from '../../../utils/date'
 import {ElMessageBox} from "element-plus";
-import {BizException, ExceptionEnum} from "@/utils/BizException";
-import {getWindowSize} from '@/utils/window-size'
+import {BizException, ExceptionEnum} from "../../../utils/BizException";
+import {getWindowSize} from '../../../utils/window-size'
 
 const props = defineProps({
   docunentId: {
@@ -78,8 +80,8 @@ const restoreData = (row) => {
   ElMessageBox.confirm('是否要还原到此节点。', '提示', {
     type: 'warning'
   }).then(() => {
+    row._id = row.documentId
     delete row.documentId
-    delete row.reversion
     emit('restoreData', row)
   }).catch(() => {
   })

+ 155 - 141
src/components/zhu-yuan-yi-sheng/emr/web-socket/EmrWebSocket.vue

@@ -1,30 +1,30 @@
 <template>
-    <div class="chat_room"
-         ref="roomRef"
-         @click="dialog = true">
-        <div class="count">
-            {{ userSize }}
-        </div>
+  <div class="chat_room"
+       ref="roomRef"
+       @click="dialog = true">
+    <div class="count">
+      {{ userSize }}
     </div>
+  </div>
 
-    <emr-chat-box
-            v-if="dialog"
-            ref="dialogRef"
-            :current-editor-user="props.currentEditorUser"
-            @closed="dialog = false"
-            :user-list="userList"
-            :sid="sid"/>
+  <emr-chat-box
+      v-if="dialog"
+      ref="dialogRef"
+      :current-editor-user="props.currentEditorUser"
+      @closed="dialog = false"
+      :user-list="userList"
+      :sid="sid"/>
 
 
-    <el-dialog v-model="errDialog" title="与服务器断开连接"
-               :show-close="false"
-               :close-on-press-escape="false"
-               :close-on-click-modal="false">
-        <div v-loading="errDialog"
-             element-loading-text="正在尝试重新连接..."
-             style="width: 100%;height: 400px"/>
+  <el-dialog v-model="errDialog" title="与服务器断开连接"
+             :show-close="false"
+             :close-on-press-escape="false"
+             :close-on-click-modal="false">
+    <div v-loading="errDialog"
+         element-loading-text="正在尝试重新连接..."
+         style="width: 100%;height: 400px"/>
 
-    </el-dialog>
+  </el-dialog>
 
 </template>
 
@@ -37,16 +37,19 @@ import {getRoomPeople, sendAMessage} from '@/api/zhu-yuan-yi-sheng/emr-socket'
 import {ElNotification} from "element-plus";
 import EmrChatBox from "@/components/zhu-yuan-yi-sheng/emr/web-socket/EmrChatBox.vue";
 import {$ref} from "vue/macros";
+import {
+  emrMitt
+} from '../../../../views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/emr-init'
 
 const props = defineProps({
-    patInfo: {
-        type: Object,
-        default: null
-    },
-    currentEditorUser: {
-        type: Object,
-        default: null
-    }
+  patInfo: {
+    type: Object,
+    default: null
+  },
+  currentEditorUser: {
+    type: Object,
+    default: null
+  }
 })
 const roomRef = ref<HTMLElement | null>(null)
 
@@ -62,176 +65,187 @@ let userData = store.state.user.info
 let sid = $ref(null)
 
 const onmessageFunc = {
-    "connect": async (data) => {
-        await queryTheNumberOfPeopleInTheRoom()
-        xcMessage.success('连接成功')
-    },
-    "connectToJoin": async (val) => {
-        await queryTheNumberOfPeopleInTheRoom()
-        let userInfo = userMap.value[val]
-        ElNotification({
-            type: 'success',
-            title: '有新的连接加入',
-            dangerouslyUseHTMLString: true,
-            message: `<span>姓名:${userInfo.name}</span>
+  "connect": async (data) => {
+    await queryTheNumberOfPeopleInTheRoom()
+    xcMessage.success('连接成功')
+  },
+  "connectToJoin": async (val) => {
+    await queryTheNumberOfPeopleInTheRoom()
+    let userInfo = userMap.value[val]
+    ElNotification({
+      type: 'success',
+      title: '有新的连接加入',
+      dangerouslyUseHTMLString: true,
+      message: `<span>姓名:${userInfo.name}</span>
                 <br>
                 <span>科室:${userInfo.deptName}</span>`
-        })
-        console.log("连接加入 %s, 数据 %o", val, userMap.value)
-    },
-    "exitEmrEditor": async (val) => {
-        let userInfo = userMap.value[val]
-        ElNotification({
-            type: 'error',
-            title: '有连接退出',
-            dangerouslyUseHTMLString: true,
-            message: `<span>姓名:${userInfo.name}</span>
+    })
+    console.log("连接加入 %s, 数据 %o", val, userMap.value)
+  },
+  "exitEmrEditor": async (val) => {
+    let userInfo = userMap.value[val]
+    ElNotification({
+      type: 'error',
+      title: '有连接退出',
+      dangerouslyUseHTMLString: true,
+      message: `<span>姓名:${userInfo.name}</span>
                 <br>
                 <span>科室:${userInfo.deptName}</span>`
-        })
-        console.log("连接退出 %s,数据 %o", val, userMap.value)
-        await queryTheNumberOfPeopleInTheRoom()
-    },
-    "message": async (val) => {
-        if (dialog.value) {
-            dialogRef.value.queryJump();
-        }
-        dialog.value = true
-        console.log("接受消息 %o", val)
-    },
-    "notice": (val) => {
-        ElNotification({
-            type: 'success',
-            title: '查看或编辑',
-            message: val
-        })
-    },
-    "closeSoctek": (val) => {
-        if (navigator.userAgent.indexOf("Firefox") !== -1 || navigator.userAgent.indexOf("Chrome") !== -1) {
-            window.location.href = "about:blank";
-            window.close();
-        } else {
-            window.opener = null;
-            window.open("", "_self");
-            window.close();
-        }
+    })
+    console.log("连接退出 %s,数据 %o", val, userMap.value)
+    await queryTheNumberOfPeopleInTheRoom()
+  },
+  "message": async (val) => {
+    if (dialog.value) {
+      dialogRef.value.queryJump();
+    }
+    dialog.value = true
+    console.log("接受消息 %o", val)
+  },
+  "notice": (val) => {
+    ElNotification({
+      type: 'success',
+      title: '查看或编辑',
+      message: val
+    })
+  },
+  "closeSoctek": (val) => {
+    if (navigator.userAgent.indexOf("Firefox") !== -1 || navigator.userAgent.indexOf("Chrome") !== -1) {
+      window.location.href = "about:blank";
+      window.close();
+    } else {
+      window.opener = null;
+      window.open("", "_self");
+      window.close();
     }
+  },
+  "forceRefresh": (val) => {
+    emrMitt.emit('forceRefresh')
+  }
 }
 
 const userSize = computed(() => {
-    return Object.keys(userMap.value).length
+  return Object.keys(userMap.value).length
 })
 
 const userList = computed(() => {
-    return Object.values(userMap.value)
+  return Object.values(userMap.value)
 })
 
 const queryTheNumberOfPeopleInTheRoom = async () => {
-    userMap.value = await getRoomPeople(sid) as any
+  userMap.value = await getRoomPeople(sid) as any
 }
 
 function initWebSocket(patNo, times) {
-    if (stringIsBlank(patNo)) {
-        return null
-    }
-
-    if ('WebSocket' in window) {
-        sid = 'emr_' + patNo.trim() + '_' + times;
-        const url = SOCKET_URL + sid + '?userCode=' + userData.code;
-        webSocket = new WebSocket(url);
-    } else {
-        alert('该浏览器不支持websocket!');
-        webSocket = 'unsupport';
-    }
+  if (stringIsBlank(patNo)) {
+    return null
+  }
 
-    webSocket.onopen = async () => {
-        errDialog.value = false
-    }
+  if ('WebSocket' in window) {
+    sid = 'emr_' + patNo.trim() + '_' + times;
+    const url = SOCKET_URL + sid + '?userCode=' + userData.code;
+    webSocket = new WebSocket(url);
+  } else {
+    alert('该浏览器不支持websocket!');
+    webSocket = 'unsupport';
+  }
 
+  webSocket.onopen = async () => {
+    errDialog.value = false
+  }
 
-    webSocket.onmessage = async function (e) {
-        let data = JSON.parse(e.data)
-        for (let key in data) {
-            onmessageFunc[key](data[key])
-        }
 
+  webSocket.onmessage = async function (e) {
+    let data = JSON.parse(e.data)
+    for (let key in data) {
+      onmessageFunc[key](data[key])
     }
+  }
 
-    webSocket.onclose = () => {
-        errDialog.value = true
-        initWebSocket(props.patInfo.inpatientNo, props.patInfo.admissTimes)
-    }
+  webSocket.onclose = () => {
+    errDialog.value = true
+    initWebSocket(props.patInfo.inpatientNo, props.patInfo.admissTimes)
+  }
 
 }
 
 const medicalRecordSwitching = async (name) => {
-    await sendAMessage(sid, "notice", name)
+  await sendAMessage(sid, "notice", name)
 }
 
 
 let documentSocket = null
 let documentSid = null
 const documentChange = (id) => {
-    documentSid = 'documentEmr_' + id + '_' + userData.code
-    if (documentSocket != null) {
-        documentSocket.close()
-        documentSocket = null
+  documentSid = 'documentEmr_' + id + '_' + userData.code
+  if (documentSocket != null) {
+    documentSocket.close()
+    documentSocket = null
+  } else {
+    if ('WebSocket' in window) {
+      initDocumentSocket()
     } else {
-        if ('WebSocket' in window) {
-            initDocumentSocket()
-        } else {
-            alert('该浏览器不支持websocket!');
-            documentSocket = null;
-        }
+      alert('该浏览器不支持websocket!');
+      documentSocket = null;
     }
+  }
+
+
 }
 
 const initDocumentSocket = () => {
-    if (documentSid == null) return
-    let temp = SOCKET_URL + documentSid
+  if (documentSid == null) return
+  let temp = SOCKET_URL + documentSid
 
-    documentSocket = new WebSocket(temp)
+  documentSocket = new WebSocket(temp)
 
-    documentSocket.onopen = () => {
-        console.log('连接成功')
-    }
+  documentSocket.onopen = () => {
+    console.log('连接成功')
+  }
 
-    documentSocket.onclose = () => {
-        initDocumentSocket()
+  documentSocket.onmessage = async function (e) {
+    let data = JSON.parse(e.data)
+    for (let key in data) {
+      onmessageFunc[key](data[key])
     }
+  }
+
+  documentSocket.onclose = () => {
+    initDocumentSocket()
+  }
 
 }
 
 const clearDocument = () => {
-    if (documentSocket != null) {
-        documentSocket.close()
-        documentSocket = null
-        documentSid = null
-    }
+  if (documentSocket != null) {
+    documentSocket.close()
+    documentSocket = null
+    documentSid = null
+  }
 }
 
 const clearSocket = () => {
-    if (webSocket != null) {
-        webSocket.close()
-        webSocket = null
-    }
+  if (webSocket != null) {
+    webSocket.close()
+    webSocket = null
+  }
 }
 
 onMounted(async () => {
-    await nextTick()
-    initWebSocket(props.patInfo.inpatientNo, props.patInfo.admissTimes)
+  await nextTick()
+  initWebSocket(props.patInfo.inpatientNo, props.patInfo.admissTimes)
 })
 
 onBeforeUnmount(() => {
-    clearDocument()
-    clearSocket()
+  clearDocument()
+  clearSocket()
 })
 
 defineExpose({
-    medicalRecordSwitching,
-    documentChange,
-    clearDocument,
-    clearSocket
+  medicalRecordSwitching,
+  documentChange,
+  clearDocument,
+  clearSocket
 })
 
 </script>

+ 3 - 0
src/components/zhu-yuan-yi-sheng/yi-zhu-lu-ru/yz-edit/YzEditor.vue

@@ -710,6 +710,9 @@ const toAddAnOrder = async () => {
       })
       for (let i = yzData.value.length - 1; i >= 0; i--) {
         let item = yzData.value[i];
+        if (item.statusFlag !== '1') {
+          continue;
+        }
         let key = i;
         let orderNo = item.actOrderNo
         if (tempMap.has(orderNo)) {

+ 38 - 11
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/EmrMain.vue

@@ -301,7 +301,7 @@ import sleep from "@/utils/sleep";
 import EmrWebSocket from "@/components/zhu-yuan-yi-sheng/emr/web-socket/EmrWebSocket.vue";
 import {stringIsBlank} from "@/utils/blank-utils";
 import {isDev, needRule} from "@/utils/public";
-import {isThereADoctorEditing} from "@/api/zhu-yuan-yi-sheng/emr-socket";
+import {forcedKickingOutOfPersonnelByDocumentId, isThereADoctorEditing} from "@/api/zhu-yuan-yi-sheng/emr-socket";
 import {onDeactivated} from "vue";
 import EmrFirstPageOfMedicalRecord from "@/components/zhu-yuan-yi-sheng/emr/EmrFirstPageOfMedicalRecord.vue";
 import EmrResultReturns
@@ -565,16 +565,33 @@ const editJudgment = async () => {
   if (currentEditorUser === null) {
     emrSocket.value.documentChange(documentId);
   } else if (currentEditorUser.code != userData.code) {
-    ElMessageBox.alert(`医生:【${currentEditorUser.name}】,科室:【${currentEditorUser.deptName}】,正在编辑病历,请医生退出后,重新打开病历。`, '提示', {
-      type: 'error'
+    ElMessageBox.confirm(`医生:【${currentEditorUser.name}】,
+    科室:【${currentEditorUser.deptName}】,
+    正在编辑病历,请医生退出后,重新打开病历。
+    <br />
+    <span style="color: red">强制提出人员会导致当前正在编辑的医生
+    ,退出当前病历在点击之前请确保没有医生正在编辑了。</span>
+    `, '提示', {
+      type: 'error',
+      confirmButtonText: '只读查看',
+      cancelButtonText: '强制踢出人员',
+      distinguishCancelAndClose: true,
+      dangerouslyUseHTMLString: true,
     }).then(() => {
-    }).catch(() => {
+      editor.setEditorMode('readonly')
+    }).catch(async (value) => {
+      if (value === 'cancel') {
+        await forcedKickingOutOfPersonnelByDocumentId(documentId)
+      } else {
+        editor.setEditorMode('readonly')
+      }
+      console.log(value)
     })
-    editor.setEditorMode('readonly')
   }
   readonlyPattern()
 }
 
+
 // 点击保存病历
 const clickSaveData = async () => {
   if (caseHistoryUrl === '/emr/runtime/#/editor') return
@@ -595,9 +612,9 @@ const clickSaveData = async () => {
   } catch {
   }
   // 解析 id
-  await analysisIframeSrcSearch()
+  let id = await analysisIframeSrcSearch()
   let data = {
-    emrDocumentId: documentId,
+    emrDocumentId: id,
     emrCategoryCode: categoryCode,
     patNo: props.huanZheXinXi.inpatientNo,
     times: props.huanZheXinXi.admissTimes,
@@ -617,9 +634,7 @@ const clickSaveData = async () => {
     //   ElMessage.warning(res.data.data)
     // })
   }
-
   saveDialog.dialog = true
-
   data.fragment = 解析病程记录()
   saveDialog.prompt(templateName, async (value) => {
     data.name = value
@@ -1030,7 +1045,6 @@ const courseSegmentLocking = async () => {
   emrSidebarRef.value.diseaseDurationRecordTime(documentId, courseTitles);
 }
 
-
 /**
  * 删除数据元,
  * 根据男性女性删除 月经史 数据元
@@ -1193,12 +1207,16 @@ const styleBarRef = ref(null)
  */
 const analysisIframeSrcSearch = async () => {
   let id = editor.documentData._id
+  let temp
   if (stringIsBlank(id)) {
     // 这个是 唯一 id 调用服务的雪花算法
-    documentId = await getUuid()
+    temp = await getUuid()
+    documentId = temp
   } else {
     documentId = id
+    temp = id
   }
+  return temp
 }
 
 // 恢复历史数据
@@ -1333,6 +1351,15 @@ onMounted(async () => {
     }
   })
 
+  emrMitt.on("forceRefresh", () => {
+    try {
+      editor.setEditorMode('readonly')
+    } catch {
+    }
+    isEditorChange = false
+    location.reload();
+  })
+
 
   watch(() => visibility.value, () => {
     // 离开页面的时候清空定时器

+ 0 - 1
src/views/settings/Test.vue

@@ -1,5 +1,4 @@
 <template>
-  {{ obj }}
   <xc-combo-grid-v2
       v-model="obj"
       clearable