feat: 增加了登录选项

This commit is contained in:
2025-07-11 16:36:28 +08:00
parent d88c710606
commit b4bb563782
8 changed files with 790 additions and 129 deletions

View File

@@ -1,29 +1,144 @@
<template>
<div class="card card-dash h-80 w-100 shadow-xl">
<div class="card card-dash h-80 w-100 shadow-xl bg-base-100">
<div class="card-body">
<h1 class="card-title place-self-center my-3 text-2xl">User Login</h1>
<div class="flex flex-col w-full h-full">
<label class="input w-full my-3">
<img class="h-[1em] opacity-50" src="@/assets/user.svg" alt="User img" />
<input type="text" class="grow" placeholder="用户名" />
<img
class="h-[1em] opacity-50"
src="@/assets/user.svg"
alt="User img"
/>
<input
type="text"
class="grow"
placeholder="用户名"
v-model="username"
@keyup.enter="handleLogin"
/>
</label>
<label class="input w-full my-3">
<img class="h-[1em] opacity-50" src="@/assets/pwd.svg" alt="User img" />
<input type="text" class="grow" placeholder="密码" />
<img
class="h-[1em] opacity-50"
src="@/assets/pwd.svg"
alt="User img"
/>
<input
type="password"
class="grow"
placeholder="密码"
v-model="password"
@keyup.enter="handleLogin"
/>
</label>
</div>
<div>
<RouterLink class="flex justify-end mx-3" to="/">忘记密码?</RouterLink>
<div class="flex justify-end mx-3">
<RouterLink to="/">忘记密码?</RouterLink>
</div>
<div class="card-actions flex items-end my-3">
<button class="btn flex-1">注册</button>
<button class="btn btn-primary flex-3">登录</button>
<button class="btn flex-1" @click="handleRegister">注册</button>
<button
class="btn btn-primary flex-3"
@click="handleLogin"
:disabled="isLoading"
>
{{ isLoading ? "登录中..." : "登录" }}
</button>
</div>
</div>
</div>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { useRouter } from "vue-router";
import { AuthManager } from "@/utils/AuthManager";
import { useAlertStore } from "@/components/Alert";
const router = useRouter();
// 获取Alert store
const alertStore = useAlertStore();
// 响应式数据
const username = ref("");
const password = ref("");
const isLoading = ref(false);
// 登录处理函数
const handleLogin = async () => {
// 验证输入
if (!username.value.trim()) {
alertStore?.show("请输入用户名", "error");
return;
}
if (!password.value.trim()) {
alertStore?.show("请输入密码", "error");
return;
}
isLoading.value = true;
try {
// 调用AuthManager的登录函数
await AuthManager.login(username.value.trim(), password.value.trim());
// 登录成功,显示成功消息并跳转
alertStore?.show("登录成功", "success", 1000);
// 短暂延迟后跳转到project页面
setTimeout(async () => {
await router.push("/project");
}, 1000);
} catch (error: any) {
console.error("Login error:", error);
// 处理不同类型的错误
let errorMessage = "登录失败,请检查网络连接";
if (error.status === 400) {
errorMessage = "用户名或密码错误";
} else if (error.status === 401) {
errorMessage = "用户名或密码错误";
} else if (error.status === 500) {
errorMessage = "服务器错误,请稍后重试";
} else if (error.message) {
errorMessage = error.message;
}
alertStore?.show(errorMessage, "error");
} finally {
isLoading.value = false;
}
};
// 注册处理函数(可以根据需要实现)
const handleRegister = () => {
// 这里可以导航到注册页面或者打开注册模态框
console.log("Navigate to register page");
// router.push('/register')
};
// 页面初始化时检查是否已有有效token
const checkExistingToken = async () => {
try {
const isValid = await AuthManager.verifyToken();
if (isValid) {
// 如果token仍然有效直接跳转到project页面
await router.push("/project");
}
} catch (error) {
// token无效或验证失败继续显示登录页面
console.log("Token verification failed, showing login page");
}
};
// 组件挂载时检查已存在的token
onMounted(() => {
checkExistingToken();
});
</script>
<style scoped>
@import "@/assets/main.css";

View File

@@ -7,20 +7,7 @@
role="button"
class="btn btn-ghost hover:bg-primary hover:bg-opacity-20 transition-all duration-300"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 6h16M4 12h8m-8 6h16"
/>
</svg>
<MenuIcon />
</div>
<ul
tabindex="0"
@@ -79,12 +66,58 @@
</router-link>
</div>
<div class="navbar-end">
<router-link
to="/login"
class="btn btn-primary text-base-100 transition-all duration-300 hover:scale-105 hover:shadow-lg mr-3"
>
登录
</router-link>
<!-- 未登录状态 -->
<template v-if="!isLoggedIn">
<router-link
to="/login"
class="btn btn-primary text-base-100 transition-all duration-300 hover:scale-105 hover:shadow-lg mr-3"
>
登录
</router-link>
</template>
<!-- 已登录状态 -->
<template v-else>
<div class="dropdown dropdown-end mr-3">
<div
tabindex="0"
role="button"
class="btn btn-ghost hover:bg-primary hover:bg-opacity-20 transition-all duration-300 flex items-center gap-2"
@click="isUserMenuOpen = !isUserMenuOpen"
>
<User class="h-5 w-5" />
<span class="font-medium">{{ userName }}</span>
<ChevronDownIcon
class="icon"
:class="{ 'rotate-180': isUserMenuOpen }"
/>
</div>
<ul
tabindex="0"
class="menu menu-sm dropdown-content bg-base-200 rounded-lg z-50 mt-3 w-48 p-2 shadow-lg transition-all duration-300 ease-in-out"
>
<li class="my-1 hover:translate-x-1 transition-all duration-300">
<router-link
to="/user"
class="text-base font-medium flex items-center gap-2"
>
<User class="icon" />
用户中心
</router-link>
</li>
<li class="my-1 hover:translate-x-1 transition-all duration-300">
<button
@click="handleLogout"
class="text-base font-medium flex items-center gap-2 w-full text-left hover:bg-error hover:text-error-content"
>
<LogOutIcon class="icon" />
退出登录
</button>
</li>
</ul>
</div>
</template>
<div class="ml-2 transition-all duration-500 hover:rotate-12">
<ThemeControlButton />
</div>
@@ -93,17 +126,68 @@
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { onBeforeRouteUpdate, useRouter } from "vue-router";
import ThemeControlButton from "./ThemeControlButton.vue";
import {
SquareActivity,
MenuIcon,
FileText,
BookOpenText,
Video,
FlaskConical,
House,
User,
PencilRuler,
LogOutIcon,
ChevronDownIcon,
} from "lucide-vue-next";
import { AuthManager } from "@/utils/AuthManager";
const router = useRouter();
// 响应式数据
const userName = ref<string>("");
const isUserMenuOpen = ref<boolean>(false);
const isLoggedIn = ref<boolean>(false); // 改为响应式变量
// 方法
const loadUserInfo = async () => {
try {
const authenticated = await AuthManager.isAuthenticated();
if (authenticated) {
const client = AuthManager.createAuthenticatedClient();
const userInfo = await client.getUserInfo();
userName.value = userInfo.name;
isLoggedIn.value = true;
} else {
userName.value = "";
isLoggedIn.value = false;
}
} catch (error) {
console.error("Failed to load user info:", error);
// 如果获取用户信息失败清除token
AuthManager.clearToken();
userName.value = "";
isLoggedIn.value = false;
}
};
const handleLogout = () => {
AuthManager.logout();
userName.value = "";
isLoggedIn.value = false;
router.push("/");
};
// 生命周期钩子
onMounted(() => {
loadUserInfo();
// 监听路由变化
router.afterEach(() => {
console.log("Route is changing, reloading user info...");
loadUserInfo();
});
});
</script>
<style scoped>