|
|
@@ -0,0 +1,147 @@
|
|
|
+<script lang="ts" setup>
|
|
|
+import { propTypes } from '@/utils/propTypes'
|
|
|
+import { isNumber } from '@/utils/is'
|
|
|
+
|
|
|
+defineOptions({ name: 'ResearchProjectDialog' })
|
|
|
+
|
|
|
+const slots = useSlots()
|
|
|
+const emits = defineEmits(['update:modelValue'])
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ modelValue: propTypes.bool.def(false),
|
|
|
+ title: propTypes.string.def('Dialog'),
|
|
|
+ fullscreen: propTypes.bool.def(true),
|
|
|
+ width: propTypes.oneOfType([String, Number]).def('40%'),
|
|
|
+ closeOnClickModal: propTypes.bool.def(true),
|
|
|
+ closeOnPressEscape: propTypes.bool.def(true),
|
|
|
+ scroll: propTypes.bool.def(false),
|
|
|
+ maxHeight: propTypes.oneOfType([String, Number]).def('400px')
|
|
|
+})
|
|
|
+
|
|
|
+const getBindValue = computed(() => {
|
|
|
+ const delArr: string[] = ['fullscreen', 'title', 'maxHeight', 'appendToBody']
|
|
|
+ const attrs = useAttrs()
|
|
|
+ const obj = { ...attrs, ...props }
|
|
|
+ for (const key in obj) {
|
|
|
+ if (delArr.indexOf(key) !== -1) delete obj[key]
|
|
|
+ }
|
|
|
+ return obj
|
|
|
+})
|
|
|
+
|
|
|
+const isFullscreen = ref(props.fullscreen)
|
|
|
+const toggleFull = () => {
|
|
|
+ isFullscreen.value = !unref(isFullscreen)
|
|
|
+}
|
|
|
+const dialogHeight = ref(isNumber(props.maxHeight) ? `${props.maxHeight}px` : props.maxHeight)
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => isFullscreen.value,
|
|
|
+ async (val: boolean) => {
|
|
|
+ await nextTick()
|
|
|
+ dialogHeight.value = val
|
|
|
+ ? `${document.documentElement.offsetHeight - 55 - 60 - (slots.footer ? 63 : 0)}px`
|
|
|
+ : isNumber(props.maxHeight)
|
|
|
+ ? `${props.maxHeight}px`
|
|
|
+ : props.maxHeight
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+)
|
|
|
+
|
|
|
+const closing = ref(false)
|
|
|
+const closeHandler = () => {
|
|
|
+ emits('update:modelValue', false)
|
|
|
+ closing.value = true
|
|
|
+}
|
|
|
+const closedHandler = () => {
|
|
|
+ closing.value = false
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <ElDialog
|
|
|
+ v-bind="getBindValue"
|
|
|
+ :close-on-click-modal="closeOnClickModal"
|
|
|
+ :close-on-press-escape="closeOnPressEscape"
|
|
|
+ :fullscreen="isFullscreen"
|
|
|
+ :width="width"
|
|
|
+ destroy-on-close
|
|
|
+ lock-scroll
|
|
|
+ draggable
|
|
|
+ class="research-project-dialog"
|
|
|
+ :show-close="false"
|
|
|
+ @close="closeHandler"
|
|
|
+ @closed="closedHandler"
|
|
|
+ >
|
|
|
+ <template #header="{ close }">
|
|
|
+ <div class="relative h-54px flex items-center justify-between pl-15px pr-15px">
|
|
|
+ <slot name="title">{{ title }}</slot>
|
|
|
+ <div class="absolute right-15px top-[50%] h-54px flex translate-y-[-50%] items-center">
|
|
|
+ <Icon
|
|
|
+ v-if="fullscreen"
|
|
|
+ class="is-hover mr-10px cursor-pointer"
|
|
|
+ :icon="isFullscreen ? 'radix-icons:exit-full-screen' : 'radix-icons:enter-full-screen'"
|
|
|
+ color="var(--el-color-info)"
|
|
|
+ hover-color="var(--el-color-primary)"
|
|
|
+ @click="toggleFull"
|
|
|
+ />
|
|
|
+ <Icon
|
|
|
+ class="is-hover cursor-pointer"
|
|
|
+ icon="ep:close"
|
|
|
+ hover-color="var(--el-color-primary)"
|
|
|
+ color="var(--el-color-info)"
|
|
|
+ @click.stop="close"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <ElScrollbar v-if="scroll" :style="{ height: dialogHeight }"><slot></slot></ElScrollbar>
|
|
|
+ <slot v-else></slot>
|
|
|
+ <template v-if="slots.footer" #footer>
|
|
|
+ <div :style="{ 'pointer-events': closing ? 'none' : 'auto' }"
|
|
|
+ ><slot name="footer"></slot
|
|
|
+ ></div>
|
|
|
+ </template>
|
|
|
+ </ElDialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.research-project-dialog {
|
|
|
+ .#{$elNamespace}-overlay-dialog {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .#{$elNamespace}-dialog {
|
|
|
+ margin: 0 !important;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ max-height: calc(100vh - 40px);
|
|
|
+
|
|
|
+ &__header {
|
|
|
+ height: 54px;
|
|
|
+ padding: 0;
|
|
|
+ margin-right: 0 !important;
|
|
|
+ border-bottom: 1px solid var(--el-border-color);
|
|
|
+ }
|
|
|
+
|
|
|
+ &__body {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ overflow: auto;
|
|
|
+ padding: 15px !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__footer {
|
|
|
+ flex-shrink: 0;
|
|
|
+ background-color: var(--el-bg-color);
|
|
|
+ border-top: 1px solid var(--el-border-color);
|
|
|
+ }
|
|
|
+
|
|
|
+ &__headerbtn {
|
|
|
+ top: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|