소스 검색

feat(登录弹窗): 重构登录弹窗组件并使用新的基础对话框组件

将原有的LoginAlert.vue组件重构,使用新创建的BlogDialog.vue作为基础对话框组件
- 提取对话框的通用逻辑和样式到BlogDialog组件
- 简化LoginAlert组件代码,专注于登录业务逻辑
- 添加登录成功后的消息提示
Sakulin 2 달 전
부모
커밋
2e67c4d081
2개의 변경된 파일155개의 추가작업 그리고 116개의 파일을 삭제
  1. 121 0
      src/layouts/BlogDialog.vue
  2. 34 116
      src/layouts/LoginAlert.vue

+ 121 - 0
src/layouts/BlogDialog.vue

@@ -0,0 +1,121 @@
+<script lang="ts" setup>
+import { defineEmits, defineProps, ref, watch } from 'vue'
+
+const props = defineProps<{
+  modelValue: boolean
+}>()
+
+const emits = defineEmits<{
+  (e: 'update:modelValue', value: boolean): void
+}>()
+
+const isVisible = ref(false)
+const displayStyle = ref({
+  display: 'none',
+})
+
+watch(
+  () => props.modelValue,
+  (newValue, oldValue) => {
+    oldValue = Boolean(oldValue)
+    if (oldValue && !newValue) {
+      isVisible.value = false
+      setTimeout(() => {
+        displayStyle.value = { display: 'none' }
+      }, 300)
+    } else if (!oldValue && newValue) {
+      displayStyle.value = { display: 'flex' }
+      setTimeout(() => {
+        isVisible.value = true
+      }, 20)
+    }
+  },
+  { immediate: true },
+)
+
+const closeDialog = () => {
+  emits('update:modelValue', false)
+}
+</script>
+
+<template>
+  <div
+    :class="isVisible ? ['visible'] : []"
+    class="overlay"
+    @mousedown="closeDialog"
+    :style="displayStyle"
+  >
+    <div class="dialog" @mousedown.stop>
+      <div class="dialog-header">
+        <div class="close-btn" @click="closeDialog" />
+      </div>
+      <div
+        class="dialog-content"
+        style="display: flex; flex-direction: column; align-items: center; justify-content: center"
+      >
+        <slot name="default" />
+      </div>
+      <div class="dialog-footer">
+        <slot name="footer" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+.overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  opacity: 0;
+  background-color: rgba(0, 0, 0, 0.5);
+  justify-content: center;
+  align-items: center;
+  z-index: 1000;
+  transition: all 0.3s;
+}
+
+.visible {
+  opacity: 100%;
+}
+
+.dialog {
+  background-color: var(--secondary-background-color);
+  border-radius: 12px;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+
+.dialog-header {
+  padding: 10px;
+  display: flex;
+  justify-content: end;
+}
+
+.close-btn {
+  width: 12px;
+  height: 12px;
+  border-radius: 6px;
+  background: var(--danger-color);
+  cursor: pointer;
+  transition: box-shadow 0.3s;
+}
+
+.close-btn:hover {
+  box-shadow: var(--danger-color) 0 0 12px;
+}
+
+.dialog-content {
+  padding: 10px;
+  width: 480px;
+  height: 100px;
+}
+
+.dialog-footer {
+  width: calc(100% - 48px);
+  padding: 12px 24px;
+  display: flex;
+  justify-content: end;
+}
+</style>

+ 34 - 116
src/layouts/LoginAlert.vue

@@ -1,135 +1,53 @@
-
-
 <script lang="ts" setup>
-import { defineProps, defineEmits, watch, ref } from 'vue'
+import { ref } from 'vue'
 import { accountIcon } from '@/assets/icons.ts'
 import { useTokenStore } from '@/stores/auth.ts'
+import { useMessagePipeStore } from '@/stores/msg.ts'
+import BlogDialog from '@/layouts/BlogDialog.vue'
 
 const props = defineProps<{
-  modelValue: boolean;
-}>();
-
-const emits = defineEmits<{
-  (e: 'update:modelValue', value: boolean): void;
-}>();
+  modelValue: boolean
+}>()
 
-const isVisible = ref(false);
-const displayStyle = ref({
-  display: "none"
-});
+const emit = defineEmits(["update:modelValue"])
 
-watch(() => props.modelValue, (newValue, oldValue) => {
-  oldValue = Boolean(oldValue);
-  if (oldValue && !newValue) {
-    isVisible.value = false;
-    setTimeout(() => {
-      displayStyle.value = { display: "none" };
-    }, 300);
-  } else if (!oldValue && newValue) {
-    displayStyle.value = { display: "flex" };
-    setTimeout(() => {
-      isVisible.value = true;
-    }, 20);
-  }
-}, {immediate: true});
+const psw = ref('')
 
-const closeDialog = () => {
-  emits('update:modelValue', false);
-};
+const tokenStore = useTokenStore()
+const msg = useMessagePipeStore()
 
-const psw = ref("");
-
-const tokenStore = useTokenStore();
-
-const placeholder = ref("PASS TOKEN");
-const failed = ref(false);
+const placeholder = ref('PASS TOKEN')
+const failed = ref(false)
 
 const handleLogin = () => {
-  tokenStore.pushPassToken(psw.value).then(res => {
+  tokenStore.pushPassToken(psw.value).then((res) => {
     if (!res) {
-      psw.value = "";
-      placeholder.value = "WRONG TOKEN";
-      failed.value = true;
+      psw.value = ''
+      placeholder.value = 'WRONG TOKEN'
+      failed.value = true
     } else {
-      closeDialog();
+      show.value = false
+      msg.success('认证成功')
     }
-  });
+  })
 }
+
+const show = ref(false)
 </script>
 
 <template>
-  <div :class="isVisible ? ['visible'] : []" class="overlay" @mousedown="closeDialog" :style="displayStyle">
-    <div class="dialog" @mousedown.stop>
-      <div class="dialog-header">
-        <div class="close-btn" @click="closeDialog"/>
-      </div>
-      <div class="dialog-content" style="display: flex; flex-direction: column; align-items: center; justify-content: center">
-        <div style="width: 32px; height: 32px; fill: var(--text-color)" v-html="accountIcon.template"/>
-        <input :placeholder="placeholder" v-model="psw" class="p-input" :class="failed ? ['p-input-danger'] : []" type="password">
-      </div>
-      <div class="dialog-footer">
-        <div class="p-button" @click="handleLogin">LOGIN</div>
-      </div>
-    </div>
-  </div>
+  <BlogDialog :model-value="props.modelValue" @update:model-value="(e) => emit('update:modelValue', e)">
+    <div style="width: 32px; height: 32px; fill: var(--text-color)" v-html="accountIcon.template" />
+    <input
+      :placeholder="placeholder"
+      v-model="psw"
+      class="p-input"
+      :class="failed ? ['p-input-danger'] : []"
+      type="password"
+    />
+
+    <template #footer>
+      <div class="p-button" @click="handleLogin">LOGIN</div>
+    </template>
+  </BlogDialog>
 </template>
-
-<style scoped>
-
-.overlay {
-  position: fixed;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  opacity: 0;
-  background-color: rgba(0, 0, 0, 0.5);
-  justify-content: center;
-  align-items: center;
-  z-index: 1000;
-  transition: all .3s;
-}
-
-.visible {
-  opacity: 100%;
-}
-
-.dialog {
-  background-color: var(--secondary-background-color);
-  border-radius: 12px;
-  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
-}
-
-.dialog-header {
-  padding: 10px;
-  display: flex;
-  justify-content: end;
-}
-
-.close-btn {
-  width: 12px;
-  height: 12px;
-  border-radius: 6px;
-  background: var(--danger-color);
-  cursor: pointer;
-  transition: box-shadow .3s;
-}
-
-.close-btn:hover {
-  box-shadow: var(--danger-color) 0 0 12px;
-}
-
-.dialog-content {
-  padding: 10px;
-  width: 480px;
-  height: 100px;
-}
-
-.dialog-footer {
-  width: calc(100% - 48px);
-  padding: 12px 24px;
-  display: flex;
-  justify-content: end;
-}
-
-</style>