Browse Source

电子病历优化和页面编辑优化

xiaochan 1 year ago
parent
commit
d3663a8d77

+ 7 - 6
src/components/cy/cy-monaco-editor/CyMonacoEditor.tsx

@@ -223,15 +223,16 @@ export function CyJsonEditorDialog<T extends object>(json: T | string,
 
     const dialog = (
         <CyDialog title='json编辑'
+                  bodyHeight='50vh'
                   {...defaultProps}
                   confirmClick={confirmClick}
         >
-            {{
-                default: () => <JsonEditor
-                    ref={cyJsonEditorRef}
-                    data={json}
-                />
-            }}
+                  {{
+                      default: () => <JsonEditor
+                          ref={cyJsonEditorRef}
+                          data={json}
+                      />
+                  }}
 
         </CyDialog>
     )

+ 2 - 0
src/components/cy/dialog/CyDialogTest.vue

@@ -1,5 +1,6 @@
 <script setup lang="ts">
 import {openDrugManual} from "@/views/hospitalization/zhu-yuan-yi-sheng/public-js/zhu-yuan-yi-sheng";
+import CyDialog from "@/components/cy/dialog/src/CyDialog.vue";
 
 function open() {
   openDrugManual('01195', '01').then(res => {
@@ -13,6 +14,7 @@ function open() {
     打开
   </el-button>
 
+
 </template>
 
 <style scoped lang="scss">

+ 12 - 23
src/components/cy/dialog/src/CyDialog.vue

@@ -42,12 +42,8 @@ export default defineComponent({
   <div
       ref="containerRef"
       :style="{ zIndex  }"
-      :class="[
-      ns.b('container'),
-  ]">
-    <div
-        :class="[ ns.e('dialog')]"
-    >
+      :class="[ns.b('container')]">
+    <div :class="[ ns.e('dialog')]">
       <ElFocusTrap
           loop
           focus-start-el="container"
@@ -59,28 +55,23 @@ export default defineComponent({
         <div
             ref="boxRef"
             :style="boxStyle"
-            :class="[
-            ns.e('box'),
-            ns.is('fullScreen' , fullScreen)
-        ]"
-
+            :class="[ns.e('box'),ns.is('fullScreen' , fullScreen)]"
         >
           <header
               ref="headerRef"
-              :class="[
-            ns.e('header'),
-          ]"
+              :class="[ns.e('header')]"
           >
-        <span>
-           {{ title }}
-        </span>
+            <span>{{ title }}</span>
+            <el-button icon="Close"
+                       v-if="showCancelButton"
+                       size="small"
+                       circle
+                       @click="handleCancel"/>
           </header>
           <div
               ref="bodyRef"
               :style="bodyStyle"
-              :class="[
-            ns.e('body'),
-          ]"
+              :class="[ns.e('body')]"
           >
             <slot
                 :width="state.bodySize.width"
@@ -89,9 +80,7 @@ export default defineComponent({
           </div>
           <footer
               ref="footerRef"
-              :class="[
-            ns.e('footer'),
-          ]"
+              :class="[ns.e('footer')]"
           >
             <el-button
                 v-if="showCancelButton"

+ 3 - 0
src/components/cy/dialog/src/cy-dialog.scss

@@ -54,6 +54,9 @@
     letter-spacing: -.025em;
     line-height: 1;
 
+    display: flex;
+    justify-content: space-between;
+
     span {
       line-height: 24px;
       font-size: 18px;

+ 1 - 1
src/components/xiao-chan/xc-table/XcTable.vue

@@ -51,7 +51,7 @@ const props = defineProps({
     type: String
   },
   height: {
-    type: Number,
+    type: [Number, String],
     default: "100%"
   },
   localPaging: {

+ 1 - 1
src/components/zhu-yuan-yi-sheng/he-li-yong-yao/YaoPingXiangQing.vue

@@ -4,7 +4,7 @@
              ignore-error
   >
     <iframe v-if="showIframe"
-            style="width: 100%;height: 100%;margin: 0;padding: 0;border: 0"
+            class="layout_full_iframe"
             :src="src"
     />
   </cy-dialog>

+ 31 - 33
src/components/zhu-yuan-yi-sheng/yi-zhu-lu-ru/EmrControlRuleDialog.vue

@@ -1,43 +1,39 @@
 <template>
-  <el-dialog v-model="dialog" title="病历质控" :fullscreen="isFullscreen" class="not_padding">
-    <el-button @click="tabsName = '审核信息'" :type="tabsName === '审核信息' ? 'primary' : ''">
-      审核信息
-    </el-button>
-    <el-button @click="tabsName = '时限提示'" :type="tabsName === '时限提示' ? 'primary' : ''">
-      时限提示
-    </el-button>
-    <div v-show="tabsName === '审核信息'">
-      <xc-table :local-data="suggestion" :height="80">
-        <el-table-column prop="patNo" label="住院号" width="90"/>
-        <el-table-column prop="times" label="次数" width="40"/>
-        <el-table-column prop="patName" label="患者名称"/>
-        <el-table-column prop="emrName" label="病历"/>
-        <el-table-column prop="name" label="质控意见"/>
-        <el-table-column prop="remark" label="备注"/>
-        <el-table-column prop="approverName" label="审核人"/>
-        <el-table-column prop="scoringCriteriaName" label="等级"/>
-        <el-table-column prop="finalControl" label="是否终末">
-          <template #default="{row}">
+  <el-dialog v-model="dialog" title="病历质控" :fullscreen="isFullscreen"
+             class="el-dialog-fullscreen-fill">
+    <CyTabs height="100%" v-model="tabsName">
+      <CyTabPane name="审核信息" label="审核信息">
+        <xc-table :local-data="suggestion">
+          <el-table-column prop="patNo" label="住院号" width="90"/>
+          <el-table-column prop="times" label="次数" width="40"/>
+          <el-table-column prop="patName" label="患者名称"/>
+          <el-table-column prop="emrName" label="病历"/>
+          <el-table-column prop="name" label="质控意见"/>
+          <el-table-column prop="remark" label="备注"/>
+          <el-table-column prop="approverName" label="审核人"/>
+          <el-table-column prop="scoringCriteriaName" label="等级"/>
+          <el-table-column prop="finalControl" label="是否终末">
+            <template #default="{row}">
           <span v-if="row.finalControl === 1">
             <el-tag>是</el-tag>
           </span>
-          </template>
-        </el-table-column>
-      </xc-table>
-    </div>
-    <div style="overflow: auto;max-height: calc(100vh - 100px)" v-show="tabsName === '时限提示'">
-      <div v-for="(value , key) in timeLimitPromptData">
-        <div style="background: white;border-radius: 10px; padding: 5px 10px;margin: 5px 0">
-          {{ key }}
-          <div v-for="item in value" style="margin: 5px 0; padding: 5px 0"
-               :style="messageStyle(item)">
-            {{ item.message }}
+            </template>
+          </el-table-column>
+        </xc-table>
+      </CyTabPane>
+      <CyTabPane label="时限提示" name="时限提示">
+        <div v-for="(value , key) in timeLimitPromptData">
+          <div style="background: white;border-radius: 10px; padding: 5px 10px;margin: 5px 0">
+            {{ key }}
+            <div v-for="item in value" style="margin: 5px 0; padding: 5px 0"
+                 :style="messageStyle(item)">
+              {{ item.message }}
+            </div>
           </div>
         </div>
-      </div>
-    </div>
+      </CyTabPane>
+    </CyTabs>
   </el-dialog>
-
 </template>
 
 <script setup>
@@ -46,6 +42,8 @@ import {myPatientQualityControl, timeLimitPrompt} from "@/api/emr-control/emr-ti
 import XEUtils from 'xe-utils'
 import {yzMitt} from "@/views/hospitalization/zhu-yuan-yi-sheng/public-js/zhu-yuan-yi-sheng";
 import {useUserStore} from "@/pinia/user-store";
+import CyTabPane from "@/components/cy/tabs/src/CyTabPane.vue";
+import CyTabs from "@/components/cy/tabs/src/CyTabs";
 
 const userStore = useUserStore().userInfo
 const suggestion = ref([])

+ 9 - 0
src/css/layout.scss

@@ -47,6 +47,15 @@
   display: block;
 }
 
+.layout_full_iframe {
+  width: 100%;
+  height: 100%;
+  border-style: unset;
+  display: block;
+  padding: 0;
+  margin: 0;
+}
+
 .layout_container {
   @include max_h_w;
   display: flex;

+ 3 - 1
src/utils/emr/edit.ts

@@ -106,7 +106,7 @@ export declare type EditType = {
         setWalkerRoot: (walker: any, node: any) => any;
         createTreeWalker: (node: any) => any;
         getDataElementsFromWalker: (walker: any, name: string, value: string) => any
-        getElementsDataFromWalker: (walker: any, name: string) => any
+        getElementsDataFromWalker: (walker: any, name?: string) => any
     };
 
     setEditorMode: (val: EditorMode) => void;
@@ -215,6 +215,8 @@ export declare type EditType = {
         }
     }
 
+    getViewByElType: (value: any, name: string) => any
+
     /**
      * 自定义编辑器快捷键
      *

+ 18 - 1
src/utils/emr/emr-init-v2.ts

@@ -73,7 +73,7 @@ export interface UseEmrInitReturn {
 
 export interface LoadParams {
     //文档id
-    documentId?: string | null
+    documentId: string | null
     // 文档类型
     categoryCode?: string
     // 患者id
@@ -289,6 +289,7 @@ export function getBcjlUserInfo(value: any):
     {
         code: string, name: string
     } {
+
     if (XEUtils.has(value, '编辑者')) {
         return {
             code: XEUtils.get(value, '编辑者.value[0].code', ''),
@@ -301,3 +302,19 @@ export function getBcjlUserInfo(value: any):
         }
     }
 }
+
+
+export function parsingFragmentDataElements(editor: EditType | null, node) {
+    if (editor == null || node === null) {
+        return {}
+    }
+    const modelService = editor!.ModelService;
+    const walker = modelService.createTreeWalker(node);
+    return modelService.getElementsDataFromWalker(walker)
+}
+
+export enum RevisionShowMode {
+    不显示,
+    卡片,
+    嵌入
+}

+ 1 - 1
src/views/data-base/page-editor-help-v2/components/page-editor-v2/PageAddComponent.vue

@@ -26,7 +26,7 @@ function addComponentClick(item) {
   }
 
   if (typeof props.store?.pageData.value.params[comp.key] === 'undefined') {
-    props.store.pageData.value.params[comp.key] = ''
+    props.store!.pageData.value.params[comp.key] = item.data.defaultValue ?? ''
   }
 
   emits('addComponent', comp)

+ 4 - 1
src/views/data-base/page-editor-help-v2/page-help-v2.ts

@@ -15,6 +15,8 @@ import SystemDeptSelect from "@/components/system/dept-select/SystemDeptSelect.v
 import SystemStaffSelect from '@/components/system/staff-select/SystemStaffSelect.vue'
 import {xcMessage} from "@/utils/xiaochan-element-plus";
 import {CyJsonEditorDialog} from "@/components/cy/cy-monaco-editor/CyMonacoEditor";
+// @ts-ignore
+import SystemItemDrug from "@/components/system/item-drug/SystemItemDrug.vue";
 
 interface TableData {
     data: any[],
@@ -26,7 +28,8 @@ export const ElAndXc = {
     XcComboGridV2: XcComboGridV2,
     CyComboGrid: CyComboGrid,
     SystemDeptSelect: SystemDeptSelect,
-    SystemStaffSelect: SystemStaffSelect
+    SystemStaffSelect: SystemStaffSelect,
+    SystemItemDrug: SystemItemDrug
 }
 
 export const createFile = () => {

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

@@ -122,7 +122,6 @@
 <script setup lang="ts">
 import {nextTick, onDeactivated, onMounted, provide, ref, watch} from "vue";
 import {
-  copyAsDataSource,
   copyEnum,
   delEmrCopy,
   emrConfig,
@@ -135,7 +134,7 @@ import {
   showIframe,
   showIframeIsList
 } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/emr-init";
-import {ElMessage, ElMessageBox} from "element-plus";
+import {ElMessage} from "element-plus";
 import {BizException, ExceptionEnum} from "@/utils/BizException";
 import {onBeforeRouteLeave} from "vue-router";
 import {getServerDateApi, getUuid} from "@/api/public-api";
@@ -163,7 +162,14 @@ import {
 } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/force-refresh-func";
 import warning from '../../../../../assets/warning.png'
 import {DataElements, EditorMode, EditType, Runtime} from "@/utils/emr/edit";
-import {componentClick, getBcjlUserInfo, useEmrInit, UseEmrInitReturn} from "@/utils/emr/emr-init-v2";
+import {
+  componentClick,
+  getBcjlUserInfo,
+  parsingFragmentDataElements,
+  RevisionShowMode,
+  useEmrInit,
+  UseEmrInitReturn
+} from "@/utils/emr/emr-init-v2";
 import {reportQueryCenterApiByGet} from "@/api/base-data/report-center";
 import type {PatientDiagnosisIsCrb} from "@/api/zhu-yuan-yi-sheng/infectious-diseasest";
 import {infectiousDiseasesAreRequired,} from "@/api/zhu-yuan-yi-sheng/infectious-diseasest";
@@ -181,9 +187,6 @@ import {
   useHistoricalData
 } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/components/emr-function/useEmrFunction";
 import PatientInfoView from "@/components/zhu-yuan-yi-sheng/public/PatientInfoView.vue";
-import {
-  useEmrCache
-} from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/useEmrCache/useEmrCache";
 
 const EmrWebSocket = defineAsyncComponent(() =>
     import("@/components/zhu-yuan-yi-sheng/emr/web-socket/EmrWebSocket.vue"))
@@ -281,6 +284,11 @@ let emrCodeEnum = {
   courseRecord: 'shoucibingchengjilu'
 }
 
+function setRevisionShowMode(val: RevisionShowMode = RevisionShowMode.嵌入) {
+  reviewMode.value = val;
+  editor!.setRevisionShowMode(val);
+}
+
 const isCourse = () => {
   return categoryCode.value === 'shoucibingchengjilu' || categoryCode.value === 'xinshengerjianhujilu';
 }
@@ -368,12 +376,10 @@ const emrEvent = {
     fragmentsCannotBeInserted = true
     //插入的内容是区域片段
     if (nodes.length > 0 && nodes[0].view && nodes[0].view.type === 'area') {
-      let view = nodes[0].view
-      let modelService = editor.ModelService;
-      let node = view.model
-      let walker = modelService.createTreeWalker(node);
-      let values = modelService.getElementsDataFromWalker(walker, '编辑者');
-      let newDate = await getServerDateApi()
+      const view = nodes[0].view
+      const node = view.model
+      const values = parsingFragmentDataElements(editor, node)
+      const newDate = await getServerDateApi()
       // @ts-ignore
       view.setAttribute('fragment', {
         name: values['查房标题'].value,
@@ -388,14 +394,10 @@ const emrEvent = {
     fragmentsCannotBeInserted = false
   },
   "areaFocus": (evt, view) => {
-    let modelService = editor?.ModelService;
-    let node = view.model
-    let walker = modelService?.createTreeWalker(node);
-    let values = modelService?.getElementsDataFromWalker(walker, '编辑者');
-    let editorCode = getBcjlUserInfo(values).code;
-    if (editorCode) {
-      openTheTraceByUser(editorCode)
-    }
+    const node = view.model
+    const values = parsingFragmentDataElements(editor, node)
+    const editorCode = getBcjlUserInfo(values).code;
+    openTheTraceByUser(editorCode)
   },
   "beforeCopy": (evt, data) => {
     if (!copy) {
@@ -410,6 +412,20 @@ const emrEvent = {
     return copy
   },
   "componentClick": (evt, comp) => componentClick(evt, comp, patientData.value),
+  "beforeRevisionAccept": (evt, data) => {
+    try {
+      return beforeRevisionAccept(evt, data)
+    } catch {
+      return true
+    }
+  },
+  "beforeRevisionRefuse": (evt, data) => {
+    try {
+      return beforeRevisionAccept(evt, data)
+    } catch {
+      return true
+    }
+  },
 }
 
 const editJudgment = async () => {
@@ -918,10 +934,8 @@ const 入院病历 = 'ruyuanjiluzhuanyong'
 function generalMedicalRecords() {
   if (emrEditCreateLimit.isEdit(createId)) {
     setEditorModel('free')
-    editor?.setRevisionShowMode(1);
   } else {
     setEditorModel('readonly')
-    editor?.setRevisionShowMode(2);
   }
 }
 
@@ -968,15 +982,12 @@ const setEditorModeFun = () => {
 const openTheTraceByUser = (editorCode) => {
   if (readonlyPattern() || stringIsBlank(createId)) {
     editor!.setRevisionMode('off')
-    editor!.setRevisionShowMode(1);
     return
   }
   if (editorCode === userInfo.code) {
     editor!.setRevisionMode('off')
-    editor!.setRevisionShowMode(1);
   } else {
     editor!.setRevisionMode('on')
-    editor!.setRevisionShowMode(2);
     xcMessage.warning('当前病历创建人不是您,你的操作将会留痕。')
   }
 }
@@ -1518,6 +1529,7 @@ const initEdit = () => {
     popupFunc.setShortcutKey()
     setEditor();
     emrStore.cache.open();
+    setRevisionShowMode(RevisionShowMode.卡片)
   })
 }
 
@@ -1528,9 +1540,30 @@ const hisSaveEmrInit = () => {
   })
 }
 
-
 let hisSaveEmr: UseEmrInitReturn | null = null
 
+function beforeRevisionAccept(evt, data) {
+  if (isCourse()) {
+    const el = editMain?.iframe.contentWindow!.document.getElementById(data.id);
+    const area = editor!.getViewByElType(el, 'area')
+    const values = parsingFragmentDataElements(editor, area.model);
+    const {code} = getBcjlUserInfo(values)
+    if (code === userInfo.code) {
+      return true
+    } else {
+      xcMessage.error('片段你创建的无法使用此功能。')
+      return false
+    }
+  } else {
+    if (createId === userInfo.code) {
+      return true
+    } else {
+      xcMessage.error('病历不是你创建的无法使用此功能。')
+      return false
+    }
+  }
+}
+
 onMounted(async () => {
   doctorLevelFunc()
   await queryingBasicPatientInformation()
@@ -1656,7 +1689,7 @@ const 循环病程返回数据元 = (callback) => {
       } else {
         modelService.setWalkerRoot(walker, node);
       }
-      values = modelService.getElementsDataFromWalker(walker, '编辑者');
+      values = modelService.getElementsDataFromWalker(walker);
       callback(values, node)
     }
   }

+ 5 - 14
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/components/emr-function/EmrFunctionList.vue

@@ -26,6 +26,7 @@ import {
   emrRootContextKey
 } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-func/useEmrStore";
 import {useSystemStore} from "@/pinia/system-store";
+import {RevisionShowMode} from "@/utils/emr/emr-init-v2";
 
 interface EmrFunctionListProps {
   openRecovery: Function;
@@ -34,7 +35,6 @@ interface EmrFunctionListProps {
 }
 
 const root = inject(emrRootContextKey)
-
 const props = defineProps<EmrFunctionListProps>()
 
 let zoom = 1;
@@ -42,13 +42,11 @@ let zoom = 1;
 const size = useSystemStore().userConfig.emr_size
 const buttonSize = size === 'default' ? '28px' : '48px'
 
-console.log(size)
-
 const emits = defineEmits(['update:isOpenPage', 'update:reviewMode'])
 
 function setRevisionShowMode(value: number) {
-  emits('update:reviewMode', 2)
-  emrMitt.emit('editor')?.setRevisionShowMode(2);
+  emits('update:reviewMode', value)
+  emrMitt.emit('editor')?.setRevisionShowMode(value);
 }
 
 const businessFunctions = [
@@ -159,21 +157,14 @@ const functionList = ref<FunctionList[][]>([
           name: '嵌入模式',
           title: '开启后会在病历中会有其他医生的修改痕迹,默认开启',
           click() {
-            setRevisionShowMode(2)
+            setRevisionShowMode(RevisionShowMode.嵌入)
           }
         },
         {
           name: '卡片模式',
           title: '病历右侧会以列表的形式显示 添加,删除,更新的记录,可以通过该模式消除痕迹,选择 √ 或 X即可。',
           click() {
-            const editor = emrMitt.emit('editor');
-            if (editor!.isRevisionMode) {
-              setRevisionShowMode(2)
-              xcMessage.warning('您不是该病历或片段的创建人无法使用卡片模式')
-            } else {
-              setRevisionShowMode(1)
-            }
-
+            setRevisionShowMode(RevisionShowMode.卡片)
           }
         }
       ]