topfans/frontend/pages/login/login.vue

366 lines
8.3 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>
<LoginBackground :show-logo="true">
<!-- 内容区域 -->
<view class="login-content">
<!-- 头像 -->
<view class="avatar-wrapper">
<image
class="avatar-image"
src="/static/login/portal/register-avatar.png"
mode="aspectFit"
></image>
</view>
<!-- 登录卡片 -->
<view class="login-card">
<!-- 标题 -->
<view class="card-title-wrapper">
<text class="card-title">账号密码登录</text>
</view>
<!-- 表单 -->
<view class="form-area">
<!-- 手机号 -->
<view class="input-group">
<view class="input-outer">
<view class="input-inner">
<input
class="input-field"
type="number"
v-model="form.phone"
placeholder="输入您的手机号"
placeholder-class="input-placeholder"
maxlength="11"
/>
</view>
</view>
</view>
<!-- 密码 -->
<view class="input-group">
<view class="input-outer">
<view class="input-inner">
<input
class="input-field"
:type="showPassword ? 'text' : 'password'"
v-model="form.password"
placeholder="输入您的密码"
placeholder-class="input-placeholder"
/>
</view>
</view>
</view>
<!-- 错误提示 -->
<view v-if="errorMessage" class="error-message">
<text>{{ errorMessage }}</text>
</view>
</view>
<!-- 忘记密码 -->
<view class="forgot-password-wrapper">
<text class="forgot-password" @tap="handleForgotPassword"
>忘记密码</text
>
</view>
<!-- 分割线 -->
<view class="divider"></view>
<!-- 登录按钮 -->
<view class="login-btn-wrapper">
<view class="login-btn" @tap="handleLogin">
<text class="login-btn-text">登录</text>
</view>
</view>
</view>
</view>
</LoginBackground>
</template>
<script setup>
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { useStore } from "vuex";
import LoginBackground from "@/components/LoginBackground.vue";
import { validatePhone, validatePassword } from "@/utils/validator";
import { resetAllGuides } from "@/utils/guideConfig";
const store = useStore();
// 响应式数据
const form = ref({
phone: "",
password: "",
});
const showPassword = ref(false);
const errorMessage = ref("");
// 获取页面参数(用于显示错误信息)
const getPageParams = () => {
const pages = getCurrentPages();
if (pages.length > 0) {
const currentPage = pages[pages.length - 1];
if (currentPage.options && currentPage.options.error) {
errorMessage.value = decodeURIComponent(currentPage.options.error);
}
}
};
// 页面加载时获取错误信息
onLoad(() => {
getPageParams();
});
// 切换密码显示/隐藏
const togglePassword = () => {
showPassword.value = !showPassword.value;
};
// 跳转到注册页面
const goToRegister = () => {
resetAllGuides();
uni.removeStorageSync("is_new_user");
uni.removeStorageSync("has_seen_welcome");
uni.reLaunch({ url: "/pages/register/register" });
};
// 忘记密码
const handleForgotPassword = () => {
uni.showToast({ title: "忘记密码功能开发中", icon: "none" });
};
// 登录
const handleLogin = async () => {
const phoneValidation = validatePhone(form.value.phone);
if (!phoneValidation.valid) {
errorMessage.value = phoneValidation.message;
return;
}
const passwordValidation = validatePassword(form.value.password);
if (!passwordValidation.valid) {
errorMessage.value = passwordValidation.message;
return;
}
errorMessage.value = "";
try {
uni.showLoading({ title: "登录中...", mask: true });
await store.dispatch("user/login", {
mobile: form.value.phone,
password: form.value.password,
});
// 任意登录方式都标记 needs_welcome=true让 TopfansWelcome 在登出后再登录也能展示一次
uni.setStorageSync("needs_welcome", true);
uni.hideLoading();
uni.reLaunch({ url: "/pages/square/square" });
} catch (error) {
uni.hideLoading();
errorMessage.value = error.message || "登录失败,请重试";
uni.showToast({
title: errorMessage.value,
icon: "none",
duration: 2000,
});
}
};
</script>
<style scoped>
.login-content {
position: relative;
z-index: 10;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 80rpx;
}
/* 头像 */
.avatar-wrapper {
width: 296rpx;
height: 274rpx;
margin-top: 130rpx;
filter: drop-shadow(2rpx 4rpx 98rpx rgba(0, 0, 0, 0.94));
z-index: 11;
}
.avatar-image {
width: 100%;
height: 100%;
}
/* 卡片 */
.login-card {
width: 710rpx;
margin-top: -104rpx;
padding: 30rpx 104rpx 30rpx;
box-sizing: border-box;
border-radius: 56rpx;
border: 1px solid rgba(255, 255, 255, 0.15);
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(64rpx);
-webkit-backdrop-filter: blur(64rpx);
box-shadow: 0 0 20.5px 0 rgba(0, 0, 0, 0.31);
display: flex;
flex-direction: column;
align-items: center;
z-index: 12;
}
/* 标题 */
.card-title-wrapper {
position: relative;
width: 324rpx;
height: 84rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 56rpx;
background:
linear-gradient(240deg, #cdaffa 9.77%, rgba(205, 175, 250, 0) 62.44%),
linear-gradient(108deg, #f7cbbf 13.91%, rgba(247, 203, 191, 0) 51.34%),
linear-gradient(297deg, #81a9f8 31.28%, rgba(129, 169, 248, 0) 90.74%),
linear-gradient(80deg, #69f4e9 39.86%, rgba(164, 252, 245, 0) 66.88%);
border-radius: 84rpx;
}
.card-title {
position: relative;
z-index: 1;
font-size: 44rpx;
color: #fff9e7;
text-shadow: -2rpx 2rpx 8rpx rgba(0, 0, 0, 0.84);
font-family: "Abhaya Libre Medium", sans-serif;
}
/* 表单 */
.form-area {
width: 100%;
display: flex;
flex-direction: column;
gap: 32rpx;
padding: 0 14rpx;
}
.input-group {
width: 100%;
}
.input-outer {
width: 100%;
height: 74rpx;
border-radius: 58rpx;
background: linear-gradient(
90deg,
rgba(255, 222, 8, 0.06) 0%,
rgba(252, 100, 102, 0.12) 64%,
rgba(244, 88, 104, 0.12) 100%
);
box-shadow: 4rpx 4rpx 8rpx 0 rgba(242, 21, 21, 0.47);
display: flex;
align-items: center;
padding: 4rpx;
box-sizing: border-box;
}
.input-inner {
width: 100%;
height: 60rpx;
border-radius: 58rpx;
background: rgba(255, 255, 255, 0.65);
display: flex;
align-items: center;
padding: 0 24rpx;
box-sizing: border-box;
}
.input-field {
width: 100%;
height: 100%;
font-size: 30rpx;
color: #333;
}
.input-placeholder {
font-size: 30rpx;
color: #565656;
font-family: "Abhaya Libre Medium", sans-serif;
}
/* 错误提示 */
.error-message {
width: 100%;
padding-left: 24rpx;
}
.error-message text {
font-size: 24rpx;
color: #ff6b6b;
}
/* 忘记密码 */
.forgot-password-wrapper {
width: 100%;
display: flex;
justify-content: center;
/* padding: 0 18rpx; */
margin-top: 48rpx;
margin-bottom: 24rpx;
}
.forgot-password {
font-size: 30rpx;
color: #fff9e7;
text-shadow: -2rpx 2rpx 8rpx rgba(0, 0, 0, 0.84);
font-family: "Abhaya Libre Medium", sans-serif;
}
/* 分割线 */
.divider {
width: 612rpx;
height: 4rpx;
background: rgba(255, 255, 255, 0.3);
border-radius: 100rpx;
margin: 28rpx 0 24rpx;
}
/* 登录按钮 */
.login-btn-wrapper {
width: 100%;
display: flex;
justify-content: center;
padding: 64rpx 0;
}
.login-btn {
width: 270rpx;
height: 90rpx;
border-radius: 58rpx;
background: linear-gradient(
90deg,
rgba(255, 222, 8, 0.28) 0%,
rgba(252, 100, 102, 0.58) 64%,
rgba(244, 88, 104, 0.58) 100%
);
box-shadow: 4rpx 4rpx 8rpx 0 rgba(242, 21, 21, 0.47);
display: flex;
align-items: center;
justify-content: center;
opacity: 0.96;
}
.login-btn-text {
font-size: 36rpx;
color: #fff9e7;
text-shadow: -2rpx 2rpx 8rpx rgba(0, 0, 0, 0.84);
font-family: "Abhaya Libre Medium", sans-serif;
}
</style>