Files
AI_OJ_FRONTEND/src/views/user/UserLoginView.vue

213 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div id="userLoginView">
<div class="login-container">
<div class="login-card">
<h2 class="login-title">欢迎登录 AI OJ</h2>
<p class="login-subtitle">AI Online Judge By MeowRain</p>
<a-form
:model="form"
:rules="rules"
@submit="handleSubmit"
layout="vertical"
class="login-form"
>
<a-form-item field="userAccount" label="账号" validate-trigger="blur">
<a-input
v-model="form.userAccount"
placeholder="请输入账号"
size="large"
allow-clear
>
<template #prefix>
<icon-user />
</template>
</a-input>
</a-form-item>
<a-form-item field="userPassword" label="密码" validate-trigger="blur">
<a-input-password
v-model="form.userPassword"
placeholder="请输入密码"
size="large"
allow-clear
>
<template #prefix>
<icon-lock />
</template>
</a-input-password>
</a-form-item>
<a-form-item>
<div class="form-actions">
<a-checkbox v-model="rememberMe">记住我</a-checkbox>
<a-link>忘记密码</a-link>
</div>
</a-form-item>
<a-form-item>
<a-button
type="primary"
html-type="submit"
long
size="large"
:loading="loading"
>
登录
</a-button>
</a-form-item>
<a-form-item>
<div class="register-link">
还没有账号
<a-link @click="goToRegister">立即注册</a-link>
</div>
</a-form-item>
</a-form>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from "vue";
import { useRouter } from "vue-router";
import { Message } from "@arco-design/web-vue";
import { IconUser, IconLock } from "@arco-design/web-vue/es/icon";
import { login } from "@/api/auth/auth";
import { setTokens } from "@/utils/token";
import { useUserStore } from "@/store/user";
import ACCESS_ENUM from "@/access/accessEnum";
import { isApiSuccess } from "@/api/response";
const router = useRouter();
const userStore = useUserStore();
const form = reactive({
userAccount: "",
userPassword: "",
});
const rules = {
userAccount: [
{ required: true, message: "请输入账号" },
{ minLength: 4, message: "账号不能少于4位" },
],
userPassword: [
{ required: true, message: "请输入密码" },
{ minLength: 8, message: "密码不能少于8位" },
],
};
const loading = ref(false);
const rememberMe = ref(false);
const handleSubmit = async (data: any) => {
if (data.errors) {
return;
}
loading.value = true;
try {
const response = await login({
userAccount: form.userAccount,
userPassword: form.userPassword,
});
if (isApiSuccess(response)) {
Message.success("登录成功!");
// 存储 token
setTokens(response.data.accessToken, response.data.refreshToken);
// 更新用户状态
userStore.updateUserLoginStatus({
userName: response.data.userAccount,
userRole: ACCESS_ENUM.USER,
});
// 跳转到首页
router.push("/home");
} else {
Message.error(response.message || "登录失败");
}
} catch (error: any) {
console.error("登录失败:", error);
Message.error(error.response?.data?.message || "登录失败,请稍后重试");
} finally {
loading.value = false;
}
};
const goToRegister = () => {
router.push("/user/register");
};
</script>
<style lang="scss" scoped>
#userLoginView {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.login-container {
width: 100%;
max-width: 420px;
}
.login-card {
background: white;
border-radius: 16px;
padding: 40px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
.login-title {
text-align: center;
font-size: 28px;
font-weight: 600;
color: #1d2129;
margin-bottom: 8px;
}
.login-subtitle {
text-align: center;
font-size: 14px;
color: #86909c;
margin-bottom: 32px;
}
.login-form {
:deep(.arco-form-item) {
margin-bottom: 20px;
}
:deep(.arco-form-item-label-col) {
margin-bottom: 8px;
}
:deep(.arco-form-item-label) {
font-weight: 500;
color: #1d2129;
}
}
.form-actions {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.register-link {
text-align: center;
color: #86909c;
font-size: 14px;
}
</style>