| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- <template>
- <div
- v-if="modelValue"
- class="fixed inset-0 z-50 flex items-center justify-center p-4"
- >
- <!-- 背景遮罩 -->
- <div
- class="absolute inset-0 bg-black/70 backdrop-blur-sm"
- @click="closeDialog"
- ></div>
- <!-- 登录卡片 -->
- <div
- class="relative w-full max-w-md rounded-2xl bg-surface border border-white/10 p-6 shadow-xl"
- >
- <button
- @click="closeDialog"
- class="absolute right-4 top-4 h-8 w-8 rounded-full grid place-items-center text-white/60 hover:bg-white/10 hover:text-white transition"
- >
- <svg
- viewBox="0 0 24 24"
- width="20"
- height="20"
- fill="none"
- stroke="currentColor"
- stroke-width="2"
- >
- <path d="M18 6 6 18M6 6l12 12" />
- </svg>
- </button>
- <div class="text-center mb-6">
- <h2 class="text-xl font-bold text-white/90">
- {{ isRegister ? "注册账户" : "登录账户" }}
- </h2>
- <p class="text-white/60 mt-1">
- {{ isRegister ? "注册后即可使用全部功能" : "登录后即可使用全部功能" }}
- </p>
- </div>
- <div class="space-y-4">
- <!-- 登录时显示用户名字段 -->
- <div v-if="!isRegister">
- <label for="username" class="block text-sm text-white/70 mb-1.5"
- >用户名</label
- >
- <input
- type="text"
- id="username"
- v-model="username"
- class="w-full px-4 py-2.5 rounded-lg bg-white/5 border border-white/10 text-white/90 focus:outline-none focus:ring-2 focus:ring-brand/50"
- placeholder="请输入用户名"
- />
- </div>
- <!-- 注册时显示邮箱字段 -->
- <div v-if="isRegister">
- <label for="email" class="block text-sm text-white/70 mb-1.5"
- >邮箱</label
- >
- <input
- type="email"
- id="email"
- v-model="email"
- class="w-full px-4 py-2.5 rounded-lg bg-white/5 border border-white/10 text-white/90 focus:outline-none focus:ring-2 focus:ring-brand/50"
- placeholder="请输入邮箱"
- />
- </div>
-
- <div>
- <label for="password" class="block text-sm text-white/70 mb-1.5"
- >密码</label
- >
- <input
- type="password"
- id="password"
- v-model="password"
- class="w-full px-4 py-2.5 rounded-lg bg-white/5 border border-white/10 text-white/90 focus:outline-none focus:ring-2 focus:ring-brand/50"
- placeholder="请输入密码"
- />
- </div>
- <div v-if="error" class="text-red-400 text-sm py-1">
- {{ error }}
- </div>
- <button
- @click="handleButtonClick"
- :disabled="isLoading"
- class="w-full py-2.5 rounded-lg bg-brand text-slate-900 font-medium hover:bg-brand/90 transition disabled:opacity-70"
- >
- {{
- isLoading
- ? isRegister
- ? "注册中..."
- : "登录中..."
- : isRegister
- ? "注册"
- : "登录"
- }}
- </button>
- <div class="text-center text-sm text-white/60">
- <p v-if="!isRegister">
- 还没有账户?
- <a
- href="#"
- @click.prevent="toggleMode"
- class="text-brand hover:underline"
- >注册新账户</a
- >
- </p>
- <p v-else>
- 已有账户?
- <a
- href="#"
- @click.prevent="toggleMode"
- class="text-brand hover:underline"
- >立即登录</a
- >
- </p>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, watch } from "vue";
- import { useUserStore } from "@/store/user";
- const props = defineProps<{
- modelValue: boolean;
- }>();
- const emit = defineEmits<{
- (e: "update:modelValue", value: boolean): void;
- (e: "login-success"): void;
- }>();
- const username = ref("");
- const password = ref("");
- const email = ref("");
- const error = ref("");
- const isLoading = ref(false);
- const isRegister = ref(false);
- const userStore = useUserStore();
- const closeDialog = () => {
- emit("update:modelValue", false);
- };
- const toggleMode = () => {
- isRegister.value = !isRegister.value;
- error.value = "";
- };
- const handleButtonClick = () => {
- if (isRegister.value) {
- handleRegister();
- } else {
- handleLogin();
- }
- };
- const handleLogin = async () => {
- // 简单的表单验证
- if (!username.value || !password.value) {
- error.value = "用户名和密码不能为空";
- return;
- }
- try {
- error.value = "";
- isLoading.value = true;
- await userStore.login(username.value, password.value);
- emit("login-success");
- closeDialog();
- } catch (err: any) {
- error.value = err.message || "登录失败,请检查用户名和密码";
- } finally {
- isLoading.value = false;
- }
- };
- const handleRegister = async () => {
- // 注册表单验证
- if (!email.value || !password.value) {
- error.value = "邮箱和密码不能为空";
- return;
- }
- // 使用邮箱作为用户名
- const finalUsername = email.value;
- try {
- error.value = "";
- isLoading.value = true;
- await userStore.register(
- finalUsername,
- password.value,
- email.value
- );
- emit("login-success");
- closeDialog();
- } catch (err: any) {
- error.value = err.message || "注册失败,请检查输入信息";
- } finally {
- isLoading.value = false;
- }
- };
- // 当弹窗关闭时重置表单
- watch(
- () => props.modelValue,
- (newVal) => {
- if (!newVal) {
- username.value = "";
- password.value = "";
- email.value = "";
- error.value = "";
- isLoading.value = false;
- isRegister.value = false;
- }
- }
- );
- </script>
|