366 lines
8.3 KiB
Vue
366 lines
8.3 KiB
Vue
<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>
|