Bläddra i källkod

完善签名的路径

xiaochan 9 månader sedan
förälder
incheckning
120a109fc9

+ 2 - 2
src/components/cy/cy-el-tabs/TabsResizer.vue

@@ -6,7 +6,7 @@ import useCyTabs, { cyElTabsKey } from "@/components/cy/cy-el-tabs/index";
 const props = withDefaults(
   defineProps<{
     modelValue?: string | number;
-    tabPosition?: "left" | "right" | "top" | "bottom";
+    tabPosition?: "left" | "right";
     min?: string | number;
     max?: string | number;
     value?: string | number;
@@ -14,7 +14,7 @@ const props = withDefaults(
   {
     tabPosition: "left",
     value: "400",
-    min: 100,
+    min: "100",
     max: "500",
   }
 );

+ 2 - 3
src/components/cy/cy-el-tabs/index.ts

@@ -4,10 +4,9 @@ const useCyTabs = props => {
       ...props.value,
     };
 
-    if (typeof props.min === "undefined") {
+    if (typeof props.value.min === "undefined") {
       data.min = props.value.value;
     }
-
     return data;
   });
 
@@ -15,6 +14,6 @@ const useCyTabs = props => {
 };
 export type CyTabs = ReturnType<typeof useCyTabs>;
 
-export const cyElTabsKey: InjectionKey<CyTabs> = Symbol("cyElTabsKey");
+export const cyElTabsKey: InjectionKey<CyTabs> = Symbol("TabsResizer");
 
 export default useCyTabs;

+ 11 - 0
src/components/cy/magic-resizer.vue

@@ -53,6 +53,15 @@ export default {
       const horizontal = this.direction === "x";
       const start = horizontal ? event.clientX : event.clientY;
       const rect = event.target.parentElement.getBoundingClientRect();
+      const documentIframe = document.getElementsByTagName("iframe") ?? [];
+
+      if (documentIframe) {
+        const mask = document.createElement("div");
+        mask.style.cssText =
+          "position: absolute;top: 0;left: 0;width: 100vw;height: 100vh;z-index: 9999;cursor: col-resize";
+        mask.setAttribute("id", "mousemoveMask");
+        document.body.append(mask);
+      }
       document.onmousemove = e => {
         let delta = horizontal ? rect.width : rect.height;
         if (horizontal) {
@@ -73,6 +82,8 @@ export default {
         }
       };
       document.onmouseup = () => {
+        const mask = document.getElementById("mousemoveMask");
+        document.body.removeChild(mask);
         document.onmousemove = document.onmouseup = null;
       };
       event.stopPropagation();

+ 3 - 2
src/components/zhu-yuan-yi-sheng/emr/emr-template/comp/PatientEmrData.vue

@@ -98,10 +98,10 @@ const opt = [
   {
     name: "新建病历",
     click: data => {
-      useDialog<string>(AddEmrDialog, {
+      useDialog<any>(AddEmrDialog, {
         dialogProps: {
           title: `在【${data.name}】文件夹下面创建病历`,
-          top: 0,
+          top: "2%",
         },
         showConfirm: false,
         params: {
@@ -111,6 +111,7 @@ const opt = [
           ],
         },
       }).then(res => {
+        // @ts-ignore
         emrMitt.emit("loadTemplate", { ...res, parent: data.folderId });
       });
     },

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

@@ -188,7 +188,6 @@ import useCompRef from "@/utils/useCompRef";
 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 { useSystemStore } from "@/pinia/system-store";
-import { useComponentClick } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-func/emr-component-click";
 
 const EmrWebSocket = defineAsyncComponent(
   () => import("@/components/zhu-yuan-yi-sheng/emr/web-socket/EmrWebSocket.vue")
@@ -395,7 +394,6 @@ const emrEvent = {
       if (!isEmpty) {
         // 判断内容是否改变
         emrStore.store.isEditorChange = true;
-        emrSidebarRef.value!.changeTemplateType(2);
       }
     }
   },
@@ -449,13 +447,7 @@ const emrEvent = {
   },
   componentClick: (evt, view) => {
     const eleInfo = view.getAttribute("element");
-    if (eleInfo) {
-      !isDev && console.log(eleInfo);
-      useComponentClick(evt, view, eleInfo, {
-        patientInfo: patientInfo.value,
-        emrName: emrStore.store.templateName,
-      });
-    }
+    isDev && eleInfo && console.log(eleInfo);
   },
   beforeRevisionAccept: (evt, data) => {
     try {
@@ -491,7 +483,14 @@ const emrEventProxy = new Proxy(emrEvent, {
       } finally {
         const currentPlugins = emrStore.store.currentPlugins;
         currentPlugins.forEach(item => {
-          item?.event?.[p]?.(...val);
+          try {
+            item?.event?.[p]?.(...val);
+          } catch (e) {
+            if (e.message === "no elementHas") {
+              return;
+            }
+            console.error(e);
+          }
         });
       }
     };
@@ -768,19 +767,19 @@ const clickSaveData = async () => {
     insertEmrData(data)
       .then(res => {
         replaceDataElement(res);
-        saveSuccessFunc(data);
+        saveSuccessFunc();
       })
       .catch(error => {
         // 提取数据元失败,但病历已保存。不影响业务所以是保存成功的,虽然报错了
         if (error.code === 7002) {
           getOutline();
-          saveSuccessFunc(data);
+          saveSuccessFunc();
         }
       });
   });
 };
 
-async function saveSuccessFunc(saveData: saveType) {
+async function saveSuccessFunc() {
   emrStore.store.isEditorChange = false;
   await emrSidebarRef.value!.queryData();
   // 如果是第一次创建就需要跳转
@@ -1620,7 +1619,6 @@ const initEdit = () => {
       user: userInfo.code,
       name: userInfo.name,
     },
-    enableSignData: true,
     userCode: userInfo.code,
     login: {
       token: localStorage.token,

+ 0 - 10
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/components/EmrSidebar.tsx

@@ -134,12 +134,6 @@ const EmrSidebar = defineComponent({
       type: Boolean,
     },
   },
-  emits: [
-    "nodeClick",
-    "patientMedicalRecord",
-    "openAndSaveTheMedicalRecord",
-    "templateMedicalRecord",
-  ],
   setup(props, { emit, expose }) {
     const root = inject(emrRootContextKey);
 
@@ -158,7 +152,6 @@ const EmrSidebar = defineComponent({
       ).then(res => {
         if (res?.length > 0) {
           templateType.value = 2;
-          emit("patientMedicalRecord");
         }
         returnData.value.patientTree = res;
       });
@@ -352,9 +345,6 @@ const EmrSidebar = defineComponent({
 
     expose({
       queryData,
-      changeTemplateType: (val: number) => {
-        templateType.value = val;
-      },
       diseaseDurationRecordTime,
     });
 

+ 2 - 2
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/plugins/ca/EmrCAComp.vue

@@ -47,7 +47,7 @@ function change() {
   selectList.value = [];
   const editor = store.getEditor();
 
-  const data = getInternalByCode(editor, "患者CA签名", false);
+  const data = getInternalByCode(editor, "患者CA签名", "internal", false);
   if (data) {
     selectList.value = data.map((item, index) => {
       const name = "CA签名" + (index + 1);
@@ -71,7 +71,7 @@ function change() {
       };
     });
   }
-  const opinion = getInternalByCode(editor, "患者CA意见", false);
+  const opinion = getInternalByCode(editor, "患者CA意见", "internal", false);
   if (opinion) {
     signOpinionList.value = opinion.map((item, index) => {
       const { view } = store.editFun.getViewById(item.id);

+ 50 - 132
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/plugins/ca/emr-ca.tsx

@@ -8,9 +8,11 @@ import {
   EmrStore,
   rightCompIndex,
 } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-func/useEmrStore";
-import { EmrRightTabs } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/emr-init";
+import {
+  EmrRightTabs,
+  patientInfo,
+} from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/emr-init";
 import { stringNotBlank } from "@/utils/blank-utils";
-import { setEmrComponentClick } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-func/emr-component-click";
 import { ElMessageBox } from "element-plus";
 
 const GenerateSignature = defineAsyncComponent(
@@ -20,101 +22,6 @@ const GenerateSignature = defineAsyncComponent(
     )
 );
 
-const testInput = {
-  required: false,
-  readonly: false,
-  deletable: true,
-  privacy: false,
-  script: {
-    content: null,
-    dynamicScript: "2154eae0167611ef8717efceee160e36",
-  },
-  format: {
-    dataType: null,
-    showType: null,
-    minLength: null,
-    maxLength: null,
-    minRows: null,
-    maxRows: null,
-    scale: null,
-    enums: null,
-    dictionary: null,
-  },
-  element: {
-    id: "552c4a60167711ef8717efceee160e36",
-    type: "element",
-    name: "医生签名",
-    code: {
-      business: "自动签名",
-      internal: "编辑者CA签名",
-      dataElement: "",
-    },
-  },
-  tips: "医生签名",
-  borderStyle: "none",
-  style: {
-    id: "e6aRxaE7OLt",
-  },
-  picker: {
-    type: null,
-    propertiesConfig: {
-      signCount: {
-        name: "签名数量",
-        code: "signCount",
-        category: "extend",
-        categoryName: "扩展",
-        value: 1,
-        editor: {
-          type: "numberfield",
-          minvalue: 1,
-        },
-      },
-      maxHeight: {
-        name: "最大高度",
-        code: "maxHeight",
-        category: "extend",
-        categoryName: "扩展",
-        editor: {
-          type: "numberfield",
-        },
-      },
-      valign: {
-        name: "对齐方式",
-        code: "valign",
-        category: "extend",
-        categoryName: "扩展",
-        editor: {
-          type: "select",
-          valueField: "code",
-          displayField: "name",
-          store: {
-            type: "store",
-            fields: ["code", "name"],
-            data: [
-              {
-                code: "top",
-                name: "上对齐",
-              },
-              {
-                code: "middle",
-                name: "中对齐",
-              },
-              {
-                code: "bottom",
-                name: "下对齐",
-              },
-            ],
-          },
-        },
-      },
-    },
-  },
-  editable: false,
-  contentWrap: true,
-  signCount: 1,
-  type: "smarttext",
-};
-
 export type SignComp = {
   id: string;
   signType: number | null;
@@ -148,25 +55,6 @@ export const selectData = [
   },
 ];
 
-function getTestContent(editor: EditType, internal = "", dataElement = "") {
-  editor.setCursor("DOCUMENT_START");
-  const tmp = XEUtils.cloneDeep(testInput);
-  tmp.element.code.internal = internal;
-  tmp.element.code.dataElement = dataElement;
-  editor.execute("insertContents", {
-    value: [tmp],
-  });
-}
-
-function testFunc(editor: EditType) {
-  if (!isDev) return;
-  getTestContent(editor, "患者CA签名", "1");
-  getTestContent(editor, "患者CA签名", "2");
-  getTestContent(editor, "患者CA签名", "3");
-  getTestContent(editor, "患者CA签名", "4");
-  getTestContent(editor, "编辑者CA签名");
-}
-
 type saveType =
   | {
       // 病历的名称
@@ -178,12 +66,15 @@ type saveType =
     }
   | any;
 
+const us = useUserStore().userInfo;
+
 export function getInternalByCode(
   editor: EditType,
   name: string,
+  code: "internal" | "business" = "internal",
   removeNotNull = true
 ): DataElementItem[] {
-  const signatureControl = editor.getDataElements("internal", false, true);
+  const signatureControl = editor.getDataElements(code, false, true);
   let data = signatureControl[name] as DataElementItem[];
   if (!data) {
     return null;
@@ -271,7 +162,7 @@ export function emrCa() {
       {
         name: res.name,
         code: res.code,
-        signature: `http://172.16.32.167:8077/doctorSignatureImage/${res.code}.png`,
+        signature: `/doctorSignatureImage/${res.code}.png`,
       },
     ]);
   }
@@ -284,11 +175,6 @@ export function emrCa() {
         value: 400,
       },
     };
-    setEmrComponentClick((evt, view, eleInfo, value) => {
-      授权CA签名(evt, view, eleInfo, value).then(XEUtils.noop);
-      患者CA签名(evt, view, eleInfo, value);
-      老授权签名(evt, view, eleInfo, value).then(XEUtils.noop);
-    });
   };
 
   const loaded = () => {
@@ -337,6 +223,35 @@ export function emrCa() {
     });
   };
 
+  const caPush = async value => {
+    await pushSign(value).catch(async () => {
+      await ElMessageBox.alert(
+        "生成自己的签名失败,请检查是否开启了免签功能,或者云医签APP是否为登录状态,可重新保存病历触发签名功能。",
+        "签名失败",
+        {
+          type: "warning",
+        }
+      ).catch(XEUtils.noop);
+    });
+  };
+
+  const oldSign = () => {
+    const signatureControl = getInternalByCode(editor, "自动签名", "business");
+    if (signatureControl) {
+      signatureControl.forEach(item => {
+        const element = getViewById(editor, item.id);
+        element.view.sign([
+          {
+            name: us.name,
+            code: us.code,
+            signature: `/doctorSignatureImage/${us.code}.png`,
+          },
+        ]);
+      });
+      console.log(signatureControl);
+    }
+  };
+
   return {
     install({ e, s }) {
       editor = e;
@@ -345,17 +260,20 @@ export function emrCa() {
     },
     event: {
       loaded,
+      componentClick: (evt, view) => {
+        const eleInfo = view.getAttribute("element");
+        const value = {
+          patientInfo: patientInfo.value,
+          emrName: store.store.templateName,
+        };
+        授权CA签名(evt, view, eleInfo, value).then(XEUtils.noop);
+        患者CA签名(evt, view, eleInfo, value);
+        老授权签名(evt, view, eleInfo, value).then(XEUtils.noop);
+      },
     },
     beforeSaving: async value => {
-      await pushSign(value).catch(async () => {
-        await ElMessageBox.alert(
-          "生成自己的签名失败,请检查是否开启了免签功能,或者云医签APP是否为登录状态,可重新保存病历触发签名功能。",
-          "签名失败",
-          {
-            type: "warning",
-          }
-        ).catch(XEUtils.noop);
-      });
+      await caPush(value);
+      oldSign();
     },
   };
 }

+ 4 - 4
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/plugins/index.ts

@@ -3,6 +3,7 @@ import { emrCa } from "./ca/emr-ca";
 import { EditType } from "@/utils/emr/edit";
 import { EmrStore } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-func/useEmrStore";
 import opinion from "./opinion/index";
+import useMdt from "./mdt";
 
 export type BeforeSaving =
   | {
@@ -16,10 +17,10 @@ export type BeforeSaving =
   | any;
 
 export type Install = {
-  install: (value: { e: EditType; r: any; s: EmrStore }) => void;
+  install?: (value: { e: EditType; r: any; s: EmrStore }) => void;
 } & ReturnPlugins;
 
-export type EventKey = "loaded" | string;
+export type EventKey = "loaded" | "componentClick" | string;
 
 export type ReturnPlugins = {
   categoryCode?: string[];
@@ -29,5 +30,4 @@ export type ReturnPlugins = {
   funcList?: FunctionList[];
   beforeSaving?: (value: BeforeSaving) => any;
 };
-
-export { emrCa, opinion };
+export { emrCa, opinion, useMdt };

+ 60 - 0
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/plugins/mdt/index.ts

@@ -0,0 +1,60 @@
+import { Install } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/plugins";
+import { elementHas } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-func/useEmrStore";
+import { magicApi } from "@/utils/database/magic-api-request";
+import { useDialog } from "@/components/cy/CyDialog/index";
+import XEUtils from "xe-utils";
+
+const DialogDMT = defineAsyncComponent(
+  () =>
+    import(
+      "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/components/DialogMDT.vue"
+    )
+);
+
+let mdtData = [];
+
+const useMdt = (): Install => {
+  async function mdt(view) {
+    if (mdtData.length === 0) {
+      mdtData = await magicApi({
+        url: "/dataEmr/comp/mdtData",
+        method: "get",
+      });
+    }
+
+    let value = view.value;
+
+    if (XEUtils.isArray(value)) {
+      value = XEUtils.map(value, item => {
+        return item.cascader;
+      });
+    } else {
+      value = [];
+    }
+
+    useDialog(DialogDMT, {
+      dialogProps: {
+        title: "MDT人员",
+      },
+      // @ts-ignore
+      params: {
+        options: mdtData,
+        value: value,
+      },
+    }).then(res => {
+      view.setValue(res);
+      view.value = res;
+    });
+  }
+
+  return {
+    event: {
+      componentClick(evt, view) {
+        elementHas(view, "MDT");
+        mdt(view);
+      },
+    },
+  };
+};
+
+export default useMdt;

+ 0 - 61
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-func/emr-component-click.ts

@@ -1,61 +0,0 @@
-import { magicApi } from "@/utils/database/magic-api-request";
-import XEUtils from "xe-utils";
-import { useDialog } from "@/components/cy/CyDialog/index";
-
-const click = [];
-let mdtData = [];
-
-export function setEmrComponentClick(cb) {
-  click.push(cb);
-}
-
-export function useComponentClick(evt, view, eleInfo, data) {
-  click.forEach(item => {
-    item(evt, view, eleInfo, data);
-  });
-}
-
-const DialogDMT = defineAsyncComponent(
-  () =>
-    import(
-      "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/components/DialogMDT.vue"
-    )
-);
-
-async function useHandleMdt(evt, view, eleInfo, patientData) {
-  if (eleInfo?.code?.internal !== "MDT") {
-    return;
-  }
-  if (mdtData.length === 0) {
-    mdtData = await magicApi({
-      url: "/dataEmr/comp/mdtData",
-      method: "get",
-    });
-  }
-
-  let value = view.value;
-
-  if (XEUtils.isArray(value)) {
-    value = XEUtils.map(value, item => {
-      return item.cascader;
-    });
-  } else {
-    value = [];
-  }
-
-  useDialog(DialogDMT, {
-    dialogProps: {
-      title: "MDT人员",
-    },
-    // @ts-ignore
-    params: {
-      options: mdtData,
-      value: value,
-    },
-  }).then(res => {
-    view.setValue(res);
-    view.value = res;
-  });
-}
-
-setEmrComponentClick(useHandleMdt);

+ 18 - 2
src/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-func/useEmrStore.ts

@@ -62,7 +62,7 @@ export const useEmrStore = (patId: string) => {
     // 病历的编码
     categoryCode: "",
     // 如果不是模板就有这个
-    emrPatientData: {} as EmrPatientData,
+    emrPatientData: {} as EmrPatientData | {},
     parent: "",
     isEditorChange: false,
   });
@@ -86,7 +86,8 @@ export const useEmrStore = (patId: string) => {
     installPlugins(value: UseEmrInitReturn, tmpStore: any) {
       for (let key in plugins) {
         const item = plugins[key];
-        item.install({ e: value.editor, r: value.runtime, s: tmpStore });
+        if (item.install)
+          item.install({ e: value.editor, r: value.runtime, s: tmpStore });
         store.plugins.push(item);
       }
     },
@@ -231,5 +232,20 @@ interface EmrRootContext {
   store: EmrStore;
 }
 
+export const elementHas = (
+  view,
+  name,
+  code: "internal" | "business" = "internal"
+) => {
+  const element = view.getAttribute("element");
+  if (element) {
+    const data = XEUtils.get(element, `code.${code}`);
+    if (data === name) {
+      return element;
+    }
+  }
+  throw new Error("no elementHas");
+};
+
 export const emrRootContextKey: InjectionKey<EmrRootContext> =
   Symbol("emrRootContext");

+ 6 - 0
vite.config.js

@@ -56,6 +56,12 @@ export default defineConfig({
         changeOrigin: true, //支持跨域调用,这里配置为true
         rewrite: path => path.replace(/^\/emr/, ""),
       },
+      "/doctorSignatureImage": {
+        target: "http://172.16.32.167:8077",
+        secure: false, //如果运行时服务是https,此处配置为true
+        changeOrigin: true, //支持跨域调用,这里配置为true
+        rewrite: path => path.replace(/^\/emr/, ""),
+      },
     },
   },
   build: {