Prechádzať zdrojové kódy

肖蟾的diallog 配合 setdialogtojs

xiaochan 1 rok pred
rodič
commit
dc61b52ca8

+ 3 - 3
src/App.vue

@@ -175,7 +175,7 @@ function getWindowSize() {
 </script>
 
 <style lang="scss">
-::-webkit-scrollbar {
+::-webkit-scrollbar:not(.cy-dialog__dialog) {
   width: 10px;
   height: 10px;
 
@@ -185,7 +185,7 @@ function getWindowSize() {
 
 }
 
-::-webkit-scrollbar-thumb {
+::-webkit-scrollbar-thumb:not(.cy-dialog__dialog) {
   border-radius: 4px;
   background: rgba(144, 147, 153, .3);
 
@@ -194,7 +194,7 @@ function getWindowSize() {
   }
 }
 
-::-webkit-scrollbar-button {
+::-webkit-scrollbar-button:not(.cy-dialog__dialog) {
   width: 0;
   height: 0;
   display: none;

+ 1 - 7
src/components/cy/combo-grid/src/index.ts

@@ -8,13 +8,7 @@ import {listFilter} from "@/utils/list-utlis";
 //@ts-ignore
 import Sortable from 'sortablejs'
 import {WritableComputedRef} from "vue";
-
-const isPromise = (val: Promise<any | unknown>) => {
-    if (val === null || typeof val === 'undefined') {
-        return false
-    }
-    return isObject(val) && isFunction(val.then) && isFunction(val.catch);
-};
+import {isPromise} from "@/utils/public";
 
 const isKorean = (text: string) =>
     /([\uAC00-\uD7AF\u3130-\u318F])+/gi.test(text)

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

@@ -1,9 +1,22 @@
 <script setup lang="ts">
-import CyDialog from "@/components/cy/dialog/src/CyDialog.vue";
+import {openDrugManual} from "@/views/hospitalization/zhu-yuan-yi-sheng/public-js/zhu-yuan-yi-sheng";
+import {ElDialog} from 'element-plus'
+
+function open() {
+  openDrugManual('01195', '01').then(res => {
+    console.log('then', res)
+  }).catch(res => {
+    console.log('catch', res)
+  })
+}
 </script>
 
 <template>
-  <CyDialog :emit="() => {}" title="我的"/>
+  <el-button @click="open">
+    打开
+  </el-button>
+  <el-input></el-input>
+
 </template>
 
 <style scoped lang="scss">

+ 66 - 65
src/components/cy/dialog/src/CyDialog.vue

@@ -1,56 +1,31 @@
-<!--<script setup lang="ts">-->
-<!--import './cy-dialog.scss'-->
-<!--import {UseCyDialog} from "./useCyDialog";-->
-<!--import {useZIndex, ElButton} from "element-plus";-->
-<!--import {ref} from 'vue'-->
-
-<!--export declare type Props = {-->
-<!--  title?: string,-->
-<!--  emit: () => void,-->
-<!--  fullScreen?: boolean,-->
-<!--}-->
-
-<!--const props = withDefaults(-->
-<!--    defineProps<Props>(),-->
-<!--    {-->
-<!--      fullScreen: false-->
-<!--    }-->
-<!--)-->
-
-
-<!--const emits = defineEmits()-->
-
-<!--const {-->
-<!--  ns,-->
-<!--  headerRef,-->
-<!--  footerRef,-->
-<!--  containerRef,-->
-<!--  bodyHeightStyle,-->
-<!--  boxRef,-->
-<!--  bodyRef,-->
-<!--  observerHeight-->
-<!--} = UseCyDialog(props)-->
-
-<!--const zIndex = ref(useZIndex().nextZIndex())-->
-<!--</script>-->
 <script lang="ts">
-import {ElButton} from 'element-plus'
-import {CyDialogProps, UseCyDialog} from "@/components/cy/dialog/src/useCyDialog";
+import {
+  ElButton,
+  useZIndex,
+  ElFocusTrap
+} from 'element-plus'
+import {CyDialogProps, IsCyDialog, UseCyDialog} from "@/components/cy/dialog/src/useCyDialog";
 import './cy-dialog.scss'
 
 const COMPONENT_NAME = 'CyDialog'
+
+
 export default defineComponent({
   name: COMPONENT_NAME,
   componentName: COMPONENT_NAME,
   components: {
-    ElButton
+    ElButton,
+    ElFocusTrap
   },
   props: CyDialogProps,
-  setup(props, {emit}) {
+  setup(props: IsCyDialog, {emit}) {
     const API = UseCyDialog(props)
+    const zIndex = ref(useZIndex().nextZIndex())
 
     return {
-      ...API
+      ...API,
+      zIndex,
+      props
     }
   }
 })
@@ -65,43 +40,69 @@ export default defineComponent({
       ns.b('container'),
   ]">
     <div
-        ref="boxRef"
-        :class="[
+        :class="[ ns.e('dialog')]"
+    >
+      <ElFocusTrap
+          loop
+          focus-start-el="container"
+          :trapped="true"
+          :focus-trap-el="containerRef"
+          @focusout-prevented="onFocusoutPrevented"
+      >
+        <div
+            ref="boxRef"
+            :class="[
             ns.e('box'),
             ns.is('fullScreen' , fullScreen)
         ]"
-    >
-      <header
-          ref="headerRef"
-          :class="[
+        >
+
+          <header
+              ref="headerRef"
+              :class="[
             ns.e('header'),
           ]"
-      >
+          >
         <span>
            {{ title }}
         </span>
-      </header>
-      <div
-          ref="bodyRef"
-          :style="bodyHeightStyle"
-          :class="[
+          </header>
+          <div
+              ref="bodyRef"
+              :style="bodyHeightStyle"
+              :class="[
             ns.e('body'),
           ]"
-      >
-        <slot
-            :width="observerHeight.bodySize.width"
-            :height="observerHeight.bodySize.height"
-        />
-      </div>
-      <footer
-          ref="footerRef"
-          :class="[
+          >
+            <slot
+                :width="state.bodySize.width"
+                :height="state.bodySize.height"
+            />
+          </div>
+          <footer
+              ref="footerRef"
+              :class="[
             ns.e('footer'),
           ]"
-      >
-        <el-button @click="" type="danger" size="default">取消</el-button>
-        <el-button style="margin-right: 15px" @click="" size="default" type="primary">确认</el-button>
-      </footer>
+          >
+            <el-button
+                @click="handleCancel"
+                type="danger"
+                size="default"
+            >
+              {{ cancelText ?? '取消' }}
+            </el-button>
+            <el-button
+                style="margin-right: 15px"
+                @click="handleConfirm"
+                size="default"
+                type="primary"
+            >
+              {{ confirmText ?? '确认' }}
+            </el-button>
+          </footer>
+        </div>
+      </ElFocusTrap>
     </div>
   </div>
 </template>

+ 38 - 15
src/components/cy/dialog/src/cy-dialog.scss

@@ -1,28 +1,51 @@
-.cy-combo-grid-container {
+.cy-dialog-container * {
+  box-sizing: border-box;
+}
+
+
+.cy-dialog-container {
   position: fixed;
-  width: 100vw;
-  height: 100vw;
   top: 0;
   left: 0;
+  bottom: 0;
+  right: 0;
+  height: 100%;
   background-color: rgba(0, 0, 0, .5);
-  display: flex;
-  justify-content: center;
+  overflow: auto;
 
-  .cy-combo-grid__box {
-    width: 600px;
-    height: 400px;
+  .cy-dialog__dialog {
+    position: fixed;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    overflow: auto;
+
+  }
+
+  .cy-dialog__box {
+    position: relative;
     background: white;
-    margin-top: 10%;
-    border-radius: 10px;
+    height: max-content;
+    width: 500px;
+    margin: 15vh auto 50px;
+    border-radius: 2px;
+    box-shadow: 0 12px 32px 4px rgba(0, 0, 0, .04), 0 8px 20px rgba(0, 0, 0, .08);
+    overflow-wrap: break-word;
   }
 
   .is-fullScreen {
-    width: 100vw;
-    height: 100vw;
-    margin-top: 0;
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    padding: 0;
+  }
+
+  .cy-dialog__body {
+    padding: 10px;
   }
 
-  .cy-combo-grid__header {
+  .cy-dialog__header {
     line-height: 20px;
     text-align: center;
     padding: 10px;
@@ -37,7 +60,7 @@
     }
   }
 
-  .cy-combo-grid__footer {
+  .cy-dialog__footer {
     text-align: right;
     padding: 10px;
     line-height: 30px;

+ 98 - 23
src/components/cy/dialog/src/useCyDialog.ts

@@ -2,67 +2,139 @@ import {ExtractPropTypes, ref} from 'vue'
 import {useCyNamespace} from "@/utils/xiaochan-element-plus";
 import {useResizeObserver} from "@vueuse/core";
 import {useDraggable} from "element-plus";
+import {ClosingMethod, compList} from "@/components/js-dialog-comp/useDialogToJs";
+import {isPromise} from "@/utils/public";
 
-
-export const CyDialogProps = buildProps({
+export const CyDialogProps = {
     title: String,
     fullScreen: {
         type: Boolean,
         default: false
+    },
+    confirmText: {
+        type: String,
+        default: '确认',
+    },
+    cancelText: {
+        type: String,
+        default: '取消',
+    },
+    confirmClick: {
+        type: Function,
+        default: null
+    },
+    cancelClick: {
+        type: Function,
+        default: null
+    },
+    bodyHeight: {
+        type: [Number, String],
+        default: '500px'
+    },
+    bodyWidth: {
+        type: [Number, String],
+        default: '500px'
     }
-})
+}
 
 export type IsCyDialog = ExtractPropTypes<typeof CyDialogProps>
 
 export function UseCyDialog(props: IsCyDialog) {
-    const ns = useCyNamespace('combo-grid')
+    const ns = useCyNamespace('dialog')
     const headerRef = ref()
     const footerRef = ref()
     const containerRef = ref()
     const boxRef = ref()
     const bodyRef = ref()
+    const ctx = getCurrentInstance()
 
-    const observerHeight = ref({
-        headerHeight: 0,
-        footerHeight: 0,
-        boxHeight: 0,
+    const state = reactive({
         bodySize: {
             height: 0,
             width: 0
-        }
+        },
+        headerHeight: 0,
+        footerHeight: 0,
+    })
+
+    const draggable = computed(() => {
+        return true;
     })
 
     const bodyHeightStyle = computed(() => {
-        return {
-            height: observerHeight.value.boxHeight - observerHeight.value.headerHeight - observerHeight.value.footerHeight + 'px'
+        if (props.fullScreen) {
+            return {
+                height: `calc(100% - ${state.headerHeight}px - ${state.footerHeight}px)`
+            }
+        } else {
+            return {
+                height: props.bodyHeight
+            }
         }
     })
 
     useResizeObserver(headerRef, (entries) => {
-        observerHeight.value.headerHeight = entries[0].target.offsetHeight
-    })
-
-    useResizeObserver(boxRef, (entries) => {
-        observerHeight.value.boxHeight = entries[0].target.offsetHeight
+        state.headerHeight = entries[0].target.offsetHeight
     })
 
     useResizeObserver(footerRef, (entries) => {
-        observerHeight.value.footerHeight = entries[0].target.offsetHeight
+        state.footerHeight = entries[0].target.offsetHeight
     })
 
     useResizeObserver(bodyRef, (entries) => {
-        observerHeight.value.bodySize = {
+        state.bodySize = {
             height: entries[0].target.offsetHeight,
             width: entries[0].target.offsetWidth,
         }
     })
 
-    const draggable = computed(() => {
-        return true;
-    })
-
     useDraggable(boxRef, headerRef, draggable)
 
+    function closed(closingMethod, ...val) {
+        compList.value[ctx?.attrs.id].onClosed(closingMethod, val)
+
+    }
+
+    function handleConfirm() {
+        let value = null
+        let isDone = true
+
+        function next(val) {
+            isDone = false
+            closed(ClosingMethod.CONFIRM, val)
+        }
+
+        if (props.confirmClick) {
+            isDone = false
+            props.confirmClick(next)
+        }
+
+        isDone && next(value)
+    }
+
+    function handleCancel() {
+        let value = null
+        let isDone = true
+
+        function next(val) {
+            isDone = false
+            closed(ClosingMethod.CANCEL, val)
+        }
+
+        if (props.cancelClick) {
+            isDone = false
+            props.cancelClick(next)
+        }
+
+        isDone && next(value)
+    }
+
+    function onFocusoutPrevented(event: CustomEvent) {
+        if (event.detail?.focusReason === 'pointer') {
+            event.preventDefault()
+        }
+    }
+
 
     return {
         ns,
@@ -72,6 +144,9 @@ export function UseCyDialog(props: IsCyDialog) {
         containerRef,
         boxRef,
         bodyRef,
-        observerHeight
+        state,
+        handleConfirm,
+        handleCancel,
+        onFocusoutPrevented
     }
 }

+ 1 - 1
src/components/js-dialog-comp/JsDialogComp.vue

@@ -12,7 +12,7 @@ import {computed} from "vue";
 const comp = computed(() => {
   const temp = []
   for (let key in compList.value) {
-    temp.push(compList.value[key])
+    temp.push(compList.value[key].comp)
   }
   return temp
 })

+ 9 - 3
src/components/js-dialog-comp/useDialogToJs.ts

@@ -11,12 +11,14 @@ export const dialogEmits = {
 }
 
 export const compList = ref<{
-    [key: string]: any
+    [key: string]: {
+        comp: any
+    }
 }>({})
 
 function setDialogToJs<P extends Component>(comp: P, data: any) {
     return new Promise<any>((resolve, reject) => {
-        const id = "cy_" + generateRandomString(5)
+        const id = "cy-dialog_js__" + generateRandomString(5)
 
         function del() {
             delete compList.value[id]
@@ -34,9 +36,13 @@ function setDialogToJs<P extends Component>(comp: P, data: any) {
                 }
                 del()
             },
+            id,
             ...data
         }
-        compList.value[id] = h(comp, props)
+        compList.value[id] = {
+            comp: h(comp, props),
+            onClosed: props.onClosed
+        }
     })
 }
 

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

@@ -1,26 +1,23 @@
 <template>
-  <el-dialog v-model="dialog"
-             title="药品说明书"
-             @close="emit('closed',ClosingMethod.CONFIRM)">
-    <div :style="{height: getWindowSize.h / 1.4 + 'px',width : '100%'}">
-      <iframe v-if="showIframe"
-              style="width: 100%;height: 100%"
-              :src="src">
-      </iframe>
-    </div>
-  </el-dialog>
+  <cy-dialog title="药品说明书"
+             body-height="500px"
+  >
+    <iframe v-if="showIframe"
+            style="width: 100%;height: 100%;margin: 0;padding: 0;border: 0"
+            :src="src"
+    />
+  </cy-dialog>
 </template>
 
 <script setup>
 /**
  * <p>
- * 描述:
+ * 描述:药品说明书
  * </p>
  * @author xc
  * @date 2022-03-29 15:36
  */
-import {getWindowSize} from "@/utils/window-size";
-import {ClosingMethod} from "@/components/js-dialog-comp/useDialogToJs";
+import CyDialog from "@/components/cy/dialog/src/CyDialog.vue";
 
 const props = defineProps({
   code: {
@@ -30,11 +27,8 @@ const props = defineProps({
     type: String,
   }
 })
-const emit = defineEmits(['closed'])
 
-const dialog = ref(true)
 const src = ref('')
-
 const showIframe = ref(false)
 
 onMounted(() => {

+ 9 - 1
src/utils/public.ts

@@ -1,7 +1,7 @@
 // @ts-ignore
 import store from '@/store'
 import {xcMessage} from "./xiaochan-element-plus";
-import XEUtils from "xe-utils";
+import XEUtils, {isFunction, isObject} from "xe-utils";
 
 export function needRule(...val) {
     const userRoles = store.state.user.info.roles
@@ -133,3 +133,11 @@ export const SYSTEM_CONFIG = {
     // @ts-ignore
     HOSPITAL_CODE: import.meta.env.VITE_HOSPITAL_CODE,
 }
+
+
+export const isPromise = (val: Promise<any | unknown>) => {
+    if (val === null || typeof val === 'undefined') {
+        return false
+    }
+    return isObject(val) && isFunction(val.then) && isFunction(val.catch);
+};

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

@@ -592,9 +592,15 @@ const emrEvent = {
     }
   },
   "beforeCopy": (evt, data) => {
+    if (!copy) {
+      xcMessage.warning('')
+    }
     return copy
   },
   "beforePaste": (evt, data) => {
+    if (!copy) {
+      xcMessage.warning('')
+    }
     return copy
   }
 }

+ 1 - 2
src/views/hospitalization/zhu-yuan-yi-sheng/public-js/zhu-yuan-yi-sheng.ts

@@ -836,9 +836,8 @@ export const clearAssociate = () => {
 }
 
 export function openDrugManual(code: string, serial: string) {
-    setDialogToJs(YaoPingXiangQing, {
+    return setDialogToJs(YaoPingXiangQing, {
         code: code + '_' + serial
-    }).then(_r => {
     })
 }