<template>
<div class="login_container">
<!-- 登录盒子 -->
<div class="login-box">
<h2 class="title">欢迎回来</h2>
<p class="subtitle">请登录您的账户以继续</p>
<!-- 登录表单 -->
<el-form
ref="loginForm"
:model="form"
:rules="rules"
label-width="0px"
class="login-form"
>
<!-- 用户名 -->
<el-form-item prop="username">
<el-input
v-model="form.username"
prefix-icon="el-icon-user"
placeholder="用户名 / 邮箱"
clearable
@keydown.enter.native="login"
/>
</el-form-item>
<!-- 密码 -->
<el-form-item prop="password">
<el-input
v-model="form.password"
prefix-icon="el-icon-lock"
placeholder="请输入密码"
type="password"
clearable
@keydown.enter.native="login"
/>
</el-form-item>
<!-- 验证码 -->
<el-form-item prop="validCode">
<div class="captcha-container">
<el-input
v-model="form.validCode"
prefix-icon="el-icon-key"
placeholder="验证码"
@keydown.enter.native="login"
style="flex: 1; margin-right: 10px"
/>
<ValidCode @input="getValidCode" ref="child" class="unselectable" />
</div>
</el-form-item>
<!-- 按钮组 -->
<el-form-item class="btn-group">
<el-button
type="primary"
class="btn login-btn"
@click="login"
:loading="loading"
:disabled="loading"
>
{{ loading ? "登录中..." : "登 录" }}
</el-button>
<el-button
type="info"
class="btn register-btn"
@click="$router.push('/register')"
>
注 册
</el-button>
<div class="admin-entries">
<el-button size="small" @click="jumpManage">管理员入口</el-button>
<el-button size="small" @click="jumpAdense">站长入口</el-button>
</div>
</el-form-item>
</el-form>
<!-- 渐隐提示 -->
<p class="footer-tip">游客体验:guest / 123456</p>
</div>
</div>
</template>
<script>
import ValidCode from "@/components/ValidCode.vue";
import request from "@/utils/request";
export default {
name: "Login",
components: { ValidCode },
created() {
document.title = "团购商城 - 登录";
},
data() {
return {
form: {
username: "",
password: "",
validCode: "",
},
validCode: "",
loading: false,
rules: {
username: [
{ required: true, message: "请输入用户名!", trigger: "blur" },
{
min: 2,
max: 25,
message: "长度在 2 到 25 个字符",
trigger: "blur",
},
],
password: [
{ required: true, message: "请输入密码!", trigger: "blur" },
{
min: 6,
max: 15,
message: "建议密码长度为 6-15 位",
trigger: "blur",
},
],
validCode: [
{ required: true, message: "请输入验证码!", trigger: "blur" },
],
},
};
},
methods: {
getValidCode(data) {
this.validCode = data;
},
login() {
this.$refs.loginForm.validate((valid) => {
if (!valid) return;
if (
this.form.validCode.toLowerCase() !== this.validCode.toLowerCase()
) {
this.$message.error("验证码错误");
this.$refs.child.refreshCode();
return;
}
this.loading = true;
request
.post("/user/login", this.form)
.then((res) => {
if (res.code === "0") {
this.$message.success("登录成功!");
sessionStorage.setItem("user", JSON.stringify(res.data));
this.$router.push("/shop");
} else {
this.$message.error(res.msg || "登录失败");
this.$refs.child.refreshCode();
}
})
.catch(() => {
this.$message.error("网络异常,请稍后重试");
})
.finally(() => {
this.loading = false;
});
});
},
jumpManage() {
this.$router.push("/manageLogin");
},
jumpAdense() {
this.$router.push("/adenseLogin");
},
},
};
</script>
<style lang="less" scoped>
// 超美动态渐变背景 + SVG 光点纹理
.login_container {
height: 100vh;
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 50%, #0dcaf0 100%);
background-size: 400% 400%;
animation: gradientBG 18s ease infinite;
display: flex;
justify-content: center;
align-items: center;
font-family: "Segoe UI", "Helvetica Neue", "Microsoft YaHei", sans-serif;
position: relative;
overflow: hidden;
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: url("data:image/svg+xml,%3Csvg width='40' height='40' viewBox='0 0 40 40' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23ffffff' fill-opacity='0.08' fill-rule='evenodd'%3E%3Ccircle cx='2' cy='2' r='2'/%3E%3C/g%3E%3C/svg%3E");
pointer-events: none;
opacity: 0.5;
z-index: 1;
}
&::after {
content: "";
position: absolute;
top: -50%;
left: -50%;
right: -50%;
bottom: -50%;
background: radial-gradient(circle, rgba(255,255,255,0.2) 0%, transparent 70%);
z-index: 2;
transform: rotate(45deg);
animation: shimmer 8s linear infinite;
}
}
@keyframes gradientBG {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
@keyframes shimmer {
0% {
transform: rotate(45deg) translate(-100%, -100%);
}
100% {
transform: rotate(45deg) translate(100%, 100%);
}
}
// 登录框:现代毛玻璃设计
.login-box {
width: 420px;
padding: 60px 50px 50px;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(24px);
border-radius: 28px;
box-shadow:
0 24px 60px rgba(0, 0, 0, 0.16),
0 1px 12px rgba(255, 255, 255, 0.7) inset;
border: 1px solid rgba(255, 255, 255, 0.5);
text-align: center;
z-index: 10;
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
&:hover {
transform: translateY(-6px);
box-shadow:
0 32px 80px rgba(0, 0, 0, 0.2),
0 2px 16px rgba(255, 255, 255, 0.8) inset;
}
.title {
color: #2c3e50;
font-size: 34px;
margin-bottom: 12px;
font-weight: 800;
letter-spacing: 1.2px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
.subtitle {
color: #7f8c8d;
font-size: 15px;
margin-bottom: 40px;
font-weight: 400;
}
}
// 表单样式统一优化
.login-form {
/deep/ .el-input__inner {
height: 56px !important;
line-height: 56px !important;
border-radius: 18px;
border: 1px solid #e1e5eb;
background-color: rgba(255, 255, 255, 0.95);
color: #2c3e50;
font-size: 16px;
padding-left: 50px;
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
&:focus {
border-color: #6a11cb;
box-shadow: 0 0 0 6px rgba(106, 17, 203, 0.18);
transform: scale(1.02);
}
}
/deep/ .el-input__prefix {
display: flex;
align-items: center;
margin-left: 14px;
color: #95a5a6;
font-size: 20px;
}
/deep/ .el-form-item {
margin-bottom: 24px;
}
}
.captcha-container {
display: flex;
align-items: center;
gap: 12px;
}
.btn-group {
margin-top: 20px !important;
.btn {
width: 100%;
height: 56px;
border-radius: 18px;
font-size: 17px;
font-weight: 600;
letter-spacing: 1px;
transition: all 0.3s ease;
&:hover {
transform: translateY(-3px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.18);
}
&:active {
transform: translateY(0);
}
}
.login-btn {
background: linear-gradient(to right, #6a11cb, #2575fc);
border: none;
color: white;
box-shadow: 0 8px 20px rgba(106, 17, 203, 0.4);
}
.register-btn {
background: rgba(255, 255, 255, 0.9);
border: 1px solid #ddd;
color: #555;
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.06);
}
.link-btn {
margin: 10px 0;
color: #6a11cb;
font-size: 14px;
padding: 0;
text-decoration: underline;
&:hover {
color: #2575fc;
}
}
.admin-entries {
display: flex;
justify-content: space-between;
margin-top: 10px;
/deep/ .el-button--small {
padding: 10px 16px;
font-size: 13px;
border-radius: 10px;
background: linear-gradient(to right, #f79533, #f37055);
color: white;
border: none;
}
}
}
.footer-tip {
margin-top: 30px;
font-size: 13px;
color: rgba(0, 0, 0, 0.4);
font-style: italic;
opacity: 0.7;
transition: opacity 0.3s;
}
</style>
美化一下
最新发布