Эх сурвалжийг харах

feat: Add Dialog component and add dailog demo

陈凯龙 3 жил өмнө
parent
commit
a18ad8f4a8

+ 3 - 0
src/components/Dialog/index.ts

@@ -0,0 +1,3 @@
+import Dialog from './src/Dialog.vue'
+
+export { Dialog }

+ 107 - 0
src/components/Dialog/src/Dialog.vue

@@ -0,0 +1,107 @@
+<script setup lang="ts">
+import { ElDialog, ElScrollbar } from 'element-plus'
+import { propTypes } from '@/utils/propTypes'
+import { computed, useAttrs, ref, unref, useSlots, watch, nextTick } from 'vue'
+import { isNumber } from '@/utils/is'
+
+const slots = useSlots()
+
+const props = defineProps({
+  modelValue: propTypes.bool.def(false),
+  title: propTypes.string.def('Dialog'),
+  fullscreen: propTypes.bool.def(true),
+  maxHeight: propTypes.oneOfType([String, Number]).def('500px')
+})
+
+const getBindValue = computed(() => {
+  const delArr: string[] = ['fullscreen', 'title', 'maxHeight']
+  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(false)
+
+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()
+    if (val) {
+      const windowHeight = document.documentElement.offsetHeight
+      dialogHeight.value = `${windowHeight - 55 - 60 - (slots.footer ? 63 : 0)}px`
+      console.log(windowHeight)
+    } else {
+      dialogHeight.value = isNumber(props.maxHeight) ? `${props.maxHeight}px` : props.maxHeight
+    }
+  },
+  {
+    immediate: true
+  }
+)
+
+const dialogStyle = computed(() => {
+  return {
+    height: unref(dialogHeight)
+  }
+})
+</script>
+
+<template>
+  <ElDialog
+    v-bind="getBindValue"
+    :fullscreen="isFullscreen"
+    destroy-on-close
+    lock-scroll
+    :close-on-click-modal="false"
+  >
+    <template #title>
+      <div class="flex justify-between">
+        <slot name="title">
+          {{ title }}
+        </slot>
+        <Icon
+          v-if="fullscreen"
+          class="mr-15px cursor-pointer is-hover"
+          :icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'"
+          color="var(--el-color-info)"
+          @click="toggleFull"
+        />
+      </div>
+    </template>
+
+    <ElScrollbar :style="dialogStyle">
+      <slot></slot>
+    </ElScrollbar>
+
+    <template v-if="slots.footer" #footer>
+      <slot name="footer"></slot>
+    </template>
+  </ElDialog>
+</template>
+
+<style lang="less">
+.@{elNamespace}-dialog__header {
+  border-bottom: 1px solid var(--tags-view-border-color);
+}
+
+.@{elNamespace}-dialog__footer {
+  border-top: 1px solid var(--tags-view-border-color);
+}
+
+.is-hover {
+  &:hover {
+    color: var(--el-color-primary) !important;
+  }
+}
+</style>

+ 8 - 1
src/locales/en.ts

@@ -104,7 +104,8 @@ export default {
     table: 'Table',
     defaultTable: 'Basic example',
     editor: 'Editor',
-    richText: 'Rich text'
+    richText: 'Rich text',
+    dialog: 'Dialog'
   },
   analysis: {
     newUser: 'New user',
@@ -336,5 +337,11 @@ export default {
   richText: {
     richText: 'Rich text',
     richTextDes: 'Secondary packaging based on wangeditor'
+  },
+  dialogDemo: {
+    dialog: 'Dialog',
+    dialogDes: 'Secondary packaging of Dialog components based on ElementPlus',
+    open: 'Open',
+    close: 'Close'
   }
 }

+ 8 - 1
src/locales/zh-CN.ts

@@ -104,7 +104,8 @@ export default {
     table: '表格',
     defaultTable: '基础示例',
     editor: '编辑器',
-    richText: '富文本'
+    richText: '富文本',
+    dialog: '弹窗'
   },
   analysis: {
     newUser: '新增用户',
@@ -333,5 +334,11 @@ export default {
   richText: {
     richText: '富文本',
     richTextDes: '基于 wangeditor 二次封装'
+  },
+  dialogDemo: {
+    dialog: '弹窗',
+    dialogDes: '基于 ElementPlus 的 Dialog 组件二次封装',
+    open: '打开',
+    close: '关闭'
   }
 }

+ 8 - 0
src/router/index.ts

@@ -193,6 +193,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
           title: t('router.search')
         }
       },
+      {
+        path: 'dialog',
+        component: () => import('@/views/Components/Dialog.vue'),
+        name: 'Dialog',
+        meta: {
+          title: t('router.dialog')
+        }
+      },
       {
         path: 'icon',
         component: () => import('@/views/Components/Icon.vue'),

+ 25 - 0
src/views/Components/Dialog.vue

@@ -0,0 +1,25 @@
+<script setup lang="ts">
+import { ContentWrap } from '@/components/ContentWrap'
+import { Dialog } from '@/components/Dialog'
+import { ElButton } from 'element-plus'
+import { useI18n } from '@/hooks/web/useI18n'
+import { ref } from 'vue'
+
+const { t } = useI18n()
+
+const dialogVisible = ref(false)
+</script>
+
+<template>
+  <ContentWrap :title="t('dialogDemo.dialog')" :message="t('dialogDemo.dialogDes')">
+    <ElButton type="primary" @click="dialogVisible = !dialogVisible">
+      {{ t('dialogDemo.open') }}
+    </ElButton>
+    <Dialog v-model="dialogVisible" :title="t('dialogDemo.dialog')">
+      <div v-for="v in 10000" :key="v">{{ v }}</div>
+      <template #footer>
+        <el-button @click="dialogVisible = false">{{ t('dialogDemo.close') }}</el-button>
+      </template>
+    </Dialog>
+  </ContentWrap>
+</template>