Prechádzať zdrojové kódy

优化Dialog组件,增加customClass属性以支持自定义样式,调整样式和逻辑以提升可读性和功能性;更新首页组件以集成登录弹窗,添加登录提示信息,增强用户体验。

xbx 1 týždeň pred
rodič
commit
546936fce1

+ 92 - 61
src/components/Dialog/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-dialog v-bind="megeProps" :fullscreen="fullscreen" class="com-dialog">
+  <el-dialog v-bind="megeProps" :fullscreen="fullscreen" :class="['com-dialog',customClass]">
     <template #header v-if="props.header !== false">
       <el-row>
         <div class="el-dialog__title zt-dialog__title">
@@ -12,10 +12,20 @@
           />
         </div>
         <el-space size="default">
-          <button type="button" class="el-dialog__headerbtn" @click="fullscreen = !fullscreen" v-if="props.showFullscreen">
+          <button
+            type="button"
+            class="el-dialog__headerbtn"
+            @click="fullscreen = !fullscreen"
+            v-if="props.showFullscreen"
+          >
             <el-icon class="el-dialog__close"><FullScreen /></el-icon>
           </button>
-          <button type="button" class="el-dialog__headerbtn" @click="dialogVisible = false" v-if="props.showClose">
+          <button
+            type="button"
+            class="el-dialog__headerbtn"
+            @click="dialogVisible = false"
+            v-if="props.showClose"
+          >
             <el-icon class="el-dialog__close"><Close /></el-icon>
           </button>
         </el-space>
@@ -49,31 +59,42 @@
   </el-dialog>
 </template>
 <script setup lang="ts">
-import { defineProps, defineSlots, computed, ref, type VNode, useAttrs,watch,nextTick   } from 'vue'
-import type { ButtonProps } from 'element-plus'
-import { DialogModalProps } from './props'
-import { Close, FullScreen } from '@element-plus/icons-vue'
-import { BasicHelp } from '@/components/helpMessage'
-import { isNumber } from '@/utils/is'
+import {
+  defineProps,
+  defineSlots,
+  computed,
+  ref,
+  type VNode,
+  useAttrs,
+  watch,
+  nextTick,
+  unref
+} from 'vue';
+import type { ButtonProps } from 'element-plus';
+import { DialogModalProps } from './props';
+import { Close, FullScreen } from '@element-plus/icons-vue';
+import { BasicHelp } from '@/components/helpMessage';
+import { isNumber } from '@/utils/is';
 
 defineOptions({
-  name: 'Dialog'
-})
+  name: 'Dialog',
+});
 
 interface Props extends DialogModalProps {
-  footer?: boolean | (() => VNode)
-  okText?: string
-  cancelText?: string
-  okButtonProps?: Partial<ButtonProps>
-  cancelButtonProps?: Partial<ButtonProps>
-  onOk?: () => void
-  onBeforeOk?: () => Promise<boolean>
-  onCancel?: () => void
-  lockScroll?: boolean
-  closeOnClickModal?: boolean
-  closeOnPressEscape?: boolean
-  modal?: boolean
-  showFullscreen?: boolean
+  footer?: boolean | (() => VNode);
+  okText?: string;
+  cancelText?: string;
+  okButtonProps?: Partial<ButtonProps>;
+  cancelButtonProps?: Partial<ButtonProps>;
+  onOk?: () => void;
+  onBeforeOk?: () => Promise<boolean>;
+  onCancel?: () => void;
+  lockScroll?: boolean;
+  closeOnClickModal?: boolean;
+  closeOnPressEscape?: boolean;
+  modal?: boolean;
+  showFullscreen?: boolean;
+  customClass?: string;
 }
 
 const props = withDefaults(defineProps<Props>(), {
@@ -85,80 +106,89 @@ const props = withDefaults(defineProps<Props>(), {
   closeOnClickModal: true,
   closeOnPressEscape: true,
   modal: true,
-  showFullscreen: true
-})
+  showFullscreen: true,
+  customClass: '', // 默认为空
+});
+
+setTimeout(() => {
+  console.log(props.modalClass);
+}, 1000);
 
-const attrs = useAttrs()
+const attrs = useAttrs();
 
 const megeProps = computed(() => {
   return {
     ...props,
-    ...attrs
-  }
-})
+    ...attrs,
+  };
+});
 
 defineSlots<{
-  title: () => VNode
-  footer: () => VNode
-  default: () => VNode
-}>()
+  title: () => VNode;
+  footer: () => VNode;
+  default: () => VNode;
+}>();
 
-const okLoading = ref(false)
-const fullscreen = ref(false)
+const okLoading = ref(false);
+const fullscreen = ref(false);
 
-const dialogHeight = ref(isNumber(props.maxHeight) ? `${props.maxHeight}px` : props.maxHeight)
+const dialogHeight = ref(
+  isNumber(props.maxHeight) ? `${props.maxHeight}px` : props.maxHeight,
+);
 
 watch(
   () => fullscreen.value,
   async (val: boolean) => {
-    await nextTick()
+    await nextTick();
     if (val) {
-      const windowHeight = document.documentElement.offsetHeight
-      dialogHeight.value = `${windowHeight - 55 - 60 - (props.footer ? 63 : 0)}px`
+      const windowHeight = document.documentElement.offsetHeight;
+      dialogHeight.value = `${windowHeight - 55 - 60 - (props.footer ? 63 : 0)}px`;
     } else {
-      dialogHeight.value = isNumber(props.maxHeight) ? `${props.maxHeight}px` : props.maxHeight
+      dialogHeight.value = isNumber(props.maxHeight)
+        ? `${props.maxHeight}px`
+        : props.maxHeight;
     }
   },
   {
-    immediate: true
-  }
-)
+    immediate: true,
+  },
+);
 
 const dialogStyle = computed(() => {
   return {
-    height: unref(dialogHeight)
-  }
-})
+    height: unref(dialogHeight),
+  };
+});
 
-const emit = defineEmits(['update:modelValue'])
+const emit = defineEmits(['update:modelValue']);
 
 const dialogVisible = defineModel('modelValue', {
   type: Boolean,
-  default: false
-})
+  default: false,
+});
 
 const handleOk = async () => {
   if (props.onBeforeOk) {
     try {
-      okLoading.value = true
-      const flag = await props.onBeforeOk()
+      okLoading.value = true;
+      const flag = await props.onBeforeOk();
       if (flag) {
-        okLoading.value = false
-        dialogVisible.value = false
+        okLoading.value = false;
+        dialogVisible.value = false;
       }
     } catch (error) {
-      okLoading.value = false
+      okLoading.value = false;
     }
   } else {
-    props.onOk?.()
-    dialogVisible.value = false
+    props.onOk?.();
+    dialogVisible.value = false;
   }
-}
+};
 
 const handleCancel = () => {
-  props.onCancel?.()
-  dialogVisible.value = false
-}
+  props.onCancel?.();
+  dialogVisible.value = false;
+};
 </script>
 <style lang="scss" scoped>
 :deep(.el-dialog__headerbtn) {
@@ -168,6 +198,7 @@ const handleCancel = () => {
 }
 
 .com-dialog {
+  
   .#{$elNamespace}-overlay-dialog {
     display: flex;
     justify-content: center;

+ 5 - 0
src/components/Dialog/props.ts

@@ -20,6 +20,8 @@ export interface DialogModalProps extends Partial<ElDialogProps> {
   //高度
   maxHeight?: string | number
 
+
+
   //是否显示滚动条
   scroll?: boolean
 
@@ -70,6 +72,9 @@ export interface DialogModalProps extends Partial<ElDialogProps> {
 
   // 帮助信息
   helpMessage?: string
+
+  // 自定义class
+  customClass?: string
 }
 
 

+ 3 - 0
src/types/components.d.ts

@@ -8,15 +8,18 @@ export {}
 /* prettier-ignore */
 declare module 'vue' {
   export interface GlobalComponents {
+    Dialog: typeof import('./../components/Dialog/index.vue')['default']
     EditorSrcEditor: typeof import('./../components/Editor/src/Editor.vue')['default']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElInput: typeof import('element-plus/es')['ElInput']
+    ElProgress: typeof import('element-plus/es')['ElProgress']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSpace: typeof import('element-plus/es')['ElSpace']
+    HelpMessageSrc: typeof import('./../components/helpMessage/src/index.vue')['default']
     Icon: typeof import('./../components/Icon/Index.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']

+ 8 - 1
src/views/home/components/nav.vue

@@ -25,7 +25,7 @@
           关于我们
         </li>
 
-        <el-button type="primary">登录</el-button>
+        <el-button type="primary" @click="handleLoginClick">登录</el-button>
       </ul>
     </div>
   </nav>
@@ -38,6 +38,8 @@ defineOptions({
   name: 'HomeNav',
 });
 
+const emit = defineEmits(['login']);
+
 const navRef = ref<HTMLElement | null>(null);
 const isScrolled = ref(false);
 const scrollThreshold = 60; // 滚动阈值,超过60px后改变样式
@@ -47,6 +49,11 @@ const handleScroll = () => {
   isScrolled.value = window.scrollY > scrollThreshold;
 };
 
+// 登录按钮点击事件
+const handleLoginClick = () => {
+  emit('login');
+};
+
 onMounted(() => {
   // 监听滚动事件
   window.addEventListener('scroll', handleScroll);

+ 12 - 22
src/views/home/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="relative w-full home-page">
     <!-- 导航栏 -->
-    <HomeNav />
+    <HomeNav @login="showLoginDialog" />
     <!-- 视差背景 -->
     <ParallaxBackground />
 
@@ -62,7 +62,7 @@ import TopAnime from './components/topAnime.vue';
 import { onMounted, onUnmounted, ref } from 'vue';
 import { useIntersectionObserver } from '@vueuse/core';
 import useDialog from '@/components/Dialog/useDialog';
-
+import { ElMessage } from 'element-plus';
 
 // 产品区域的引用
 const productSection = ref(null);
@@ -72,7 +72,6 @@ const isProductVisible = ref(false);
 // 动态导入登录页面
 const LoginView = () => import('@/views/login/index.vue');
 
-
 // 使用VueUse的useIntersectionObserver监听元素可见性
 useIntersectionObserver(
   productSection,
@@ -127,8 +126,6 @@ onMounted(() => {
   });
 });
 
-
-
 // 初始化弹窗
 const loginDialog = useDialog({
   content: LoginView,
@@ -138,30 +135,23 @@ const loginDialog = useDialog({
     showClose: true,
     closeOnClickModal: false,
     header: false,
-    footer: false
+    footer: false,
+    customClass: 'login-dialog'
   }
 });
 
 // 显示登录弹窗
 const showLoginDialog = () => {
+  // 打开登录弹窗
   loginDialog.openModal();
+  ElMessage.info('登录中,请稍候...');
+  
+  // 4秒后自动关闭
+  setTimeout(() => {
+    loginDialog.closeModal();
+    ElMessage.success('登录成功');
+  }, 4000);
 };
-
-
-showLoginDialog()
-
-
-
-
-
-
-
-
-
-
-
-
-
 </script>
 <style lang="scss" scoped>
 .home-page {

+ 42 - 27
src/views/login/index.vue

@@ -1,53 +1,59 @@
 <template>
   <div class="w-full h-full flex items-center justify-center relative">
     <!-- 背景图 -->
-    <div 
-      class="absolute inset-0 bg-cover bg-center"
-      style="background-image: url('../../assets/imgs/login.png');"
-    ></div>
-    
+    <div class="absolute inset-0 bg-cover bg-center"></div>
+
     <!-- 白色内容区域 - 增加内边距让背景更多露出 -->
     <div class="bg-white rounded-lg w-[420px] shadow-lg z-10 relative p-8">
-      <h2 class="text-2xl font-bold text-center text-gray-800 mb-8">登录魔音工坊开启创作之旅</h2>
-      
+      <h2 class="text-2xl font-bold text-center text-gray-800 mb-8">
+        登录开启创作之旅
+      </h2>
+
       <!-- 账号密码登录表单 -->
       <div class="space-y-6">
         <!-- 用户名输入框 -->
-        <el-input 
-          v-model="formData.username" 
-          placeholder="请输入用户名" 
+        <el-input
+          v-model="formData.username"
+          placeholder="请输入用户名"
           :prefix-icon="User"
           class="rounded-md"
           size="large"
         ></el-input>
-        
+
         <!-- 密码输入框 -->
-        <el-input 
-          v-model="formData.password" 
-          type="password" 
+        <el-input
+          v-model="formData.password"
+          type="password"
           placeholder="请输入密码"
-          :prefix-icon="Lock" 
+          :prefix-icon="Lock"
           show-password
           class="rounded-md"
           size="large"
         ></el-input>
-        
+
         <!-- 验证码输入框 -->
         <div class="flex gap-3">
-          <el-input 
-            v-model="formData.verificationCode" 
+          <el-input
+            v-model="formData.verificationCode"
             placeholder="请输入验证码"
             :prefix-icon="Key"
             class="flex-1 rounded-md"
             size="large"
           ></el-input>
-          <el-button type="primary" class="w-28 h-10 text-sm rounded-md">获取验证码</el-button>
+          <el-button type="primary" class="w-28 !h-10 text-sm rounded-md"
+            >获取验证码</el-button
+          >
         </div>
-        
+
         <!-- 登录按钮 -->
-        <el-button type="primary" class="w-full h-44 text-base rounded-md mt-8" @click="handleLogin">登录</el-button>
+        <el-button
+          type="primary"
+          class="w-full !h-11 text-base rounded-lg mt-8"
+          @click="handleLogin"
+          >登录</el-button
+        >
       </div>
-      
+
       <!-- 底部链接区域 -->
       <div class="mt-8 text-center">
         <!-- 注册链接 -->
@@ -55,7 +61,7 @@
           <span class="text-gray-600">还没有账号?</span>
           <a href="javascript:;" class="text-blue-500 ml-1" @click="handleRegister">立即注册</a>
         </div> -->
-        
+
         <!-- 用户协议 -->
         <div class="text-center text-xs text-gray-400 mt-4">
           <span>登录即表示已阅读并同意</span>
@@ -77,7 +83,7 @@ import { User, Lock, Key } from '@element-plus/icons-vue';
 const formData = reactive({
   username: '',
   password: '',
-  verificationCode: ''
+  verificationCode: '',
 });
 
 // 登录方法
@@ -88,12 +94,12 @@ const handleLogin = async () => {
       ElMessage.warning('请输入用户名');
       return;
     }
-    
+
     if (!formData.password) {
       ElMessage.warning('请输入密码');
       return;
     }
-    
+
     if (!formData.verificationCode) {
       ElMessage.warning('请输入验证码');
       return;
@@ -113,4 +119,13 @@ const handleRegister = () => {
   // TODO: 实现注册逻辑
   ElMessage.info('正在开发中...');
 };
-</script> 
+</script>
+<style lang="scss" >
+.login-dialog{
+  background: url('../../assets/imgs/login.png') no-repeat;
+  background-size: cover;
+  .el-dialog__close{
+    color: #333;
+  }
+}
+</style>