Browse Source

完成登录界面

wangyi/feature-20251022162725-启动页登录注册
Ethereal 1 month ago
parent
commit
216e8a469e
  1. 134
      pages/start/components/login-prompt/login-prompt.vue
  2. 286
      pages/start/login/login.vue
  3. BIN
      static/icons/Check-one-false.png
  4. BIN
      static/icons/Check-one-true.png

134
pages/start/components/login-prompt/login-prompt.vue

@ -1,134 +0,0 @@
<template>
<view class="login-prompt" v-if="showPrompt">
<view class="mask" :class="{ 'mask-show': showAnimation }" @click="hide"></view>
<view class="prompt-content" :class="{ 'slide-up': showAnimation }">
<text class="prompt-title">登录以获得更好的体验</text>
<button class="login-btn" @click="goLogin">登录(推荐)</button>
<button class="visitor-btn" @click="continueAsVisitor">以访客身份继续</button>
</view>
</view>
</template>
<script setup>
import { ref, nextTick } from 'vue';
//
const showPrompt = ref(false);
const showAnimation = ref(false);
//
const show = () => {
showPrompt.value = true;
//
nextTick(() => {
setTimeout(() => {
showAnimation.value = true;
}, 10);
});
};
//
const hide = () => {
showAnimation.value = false;
//
setTimeout(() => {
showPrompt.value = false;
}, 300);
};
//
const goLogin = () => {
uni.navigateTo({
url: '/pages/login/login'
});
hide();
};
// 访
const continueAsVisitor = () => {
// 访
uni.setStorageSync('visitorMode', true);
hide();
};
// 使
defineExpose({
show,
hide
});
</script>
<style scoped>
.login-prompt {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999;
}
.mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
opacity: 0;
transition: opacity 0.3s ease;
}
.mask.mask-show {
opacity: 1;
}
.prompt-content {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 300rpx;
border-radius: 20rpx 20rpx 0 0;
background-color: white;
padding: 20rpx 30rpx;
transform: translateY(100%);
transition: transform 0.3s ease;
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.3);
}
.prompt-content.slide-up {
transform: translateY(0);
}
.prompt-title {
display: block;
text-align: left;
font-size: 28rpx;
font-weight: 700;
color: #333;
margin-top: 10rpx;
margin-bottom: 30rpx;
}
.login-btn {
width: 100%;
height: 80rpx;
background-color:rgb(35, 84, 230);
color: white;
font-size: 32rpx;
line-height: 80rpx;
border-radius: 40rpx;
margin-bottom: 20rpx;
}
.visitor-btn {
width: 100%;
height: 80rpx;
background-color: #f5f5f5;
color: #333;
font-size: 32rpx;
line-height: 80rpx;
border-radius: 40rpx;
}
</style>

286
pages/start/login/login.vue

@ -9,12 +9,16 @@
<text class="back-btn" @click="goToIndex"></text> <text class="back-btn" @click="goToIndex"></text>
</view> --> </view> -->
<view class="nav-right"> <view class="nav-right">
<image class="icons" src="../../../static/icons/Headset.png" alt="" />
<image
class="icons"
src="../../../static/icons/Headset.png"
alt="联系客服"
/>
<image <image
class="icons" class="icons"
@click="goToIndex" @click="goToIndex"
src="../../../static/icons/Frame.png" src="../../../static/icons/Frame.png"
alt=""
alt="返回首页"
/> />
</view> </view>
</view> </view>
@ -29,32 +33,45 @@
<view class="switch-container"> <view class="switch-container">
<text <text
class="switch-item" class="switch-item"
:class="{ active: switchType === 'Email' }"
@click="switchEmail"
>邮箱/用户名</text
:class="{ active: switchType === 'User' }"
@click="switchUser"
>用户名</text
> >
<text <text
class="switch-item" class="switch-item"
:class="{ active: switchType === 'Phone' }" :class="{ active: switchType === 'Phone' }"
@click="switchPhone" @click="switchPhone"
>手机号</text >手机号</text
><text
class="switch-item"
:class="{ active: switchType === 'Email' }"
@click="switchEmail"
>邮箱</text
> >
</view> </view>
<!-- 输入框 --> <!-- 输入框 -->
<view class="input-container"> <view class="input-container">
<view v-if="switchType === 'Email'">
<view v-if="switchType === 'User'">
<!-- 修改邮箱输入框容器将图标包含在内 --> <!-- 修改邮箱输入框容器将图标包含在内 -->
<view class="input-with-icon"> <view class="input-with-icon">
<image class="input-icon" src="../../../static/icons/People-safe.png" alt="" />
<image
class="input-icon"
src="../../../static/icons/People-safe.png"
alt=""
/>
<input <input
class="input-field" class="input-field"
type="text" type="text"
placeholder="请输入邮箱/DeepChart ID"
placeholder="请输入DeepChart ID"
v-model="email" v-model="email"
/> />
</view> </view>
<view class="input-with-icon"> <view class="input-with-icon">
<image class="input-icon" src="../../../static/icons/Unlock.png" alt="" />
<image
class="input-icon"
src="../../../static/icons/Unlock.png"
alt=""
/>
<input <input
class="input-field" class="input-field"
type="text" type="text"
@ -63,7 +80,51 @@
/> />
</view> </view>
</view> </view>
<view v-else class="phone-input-container">
<view v-if="switchType === 'Email'">
<!-- 修改邮箱输入框容器将图标包含在内 -->
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Mail.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入邮箱"
v-model="email"
/>
<view>
<button
class="send-code-btn-email"
:disabled="isCodeBtnDisabled"
:class="{ 'send-code-btn-disabled': isCodeBtnDisabled }"
@click="sendCode"
>
<text
class="send-code-text"
:class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
>{{ codeBtnText }}</text
>
</button>
</view>
</view>
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Text-recognition.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入验证码"
v-model="password"
/>
</view>
</view>
<view v-if="switchType === 'Phone'" class="phone-input-container">
<view class="country-code-selector" @click="showCountryPicker"> <view class="country-code-selector" @click="showCountryPicker">
<image <image
class="country-flag-img" class="country-flag-img"
@ -81,33 +142,59 @@
@input="onPhoneInput" @input="onPhoneInput"
/> />
<view> <view>
<button
class="send-code-btn"
:disabled="isCodeBtnDisabled"
<button
class="send-code-btn"
:disabled="isCodeBtnDisabled"
:class="{ 'send-code-btn-disabled': isCodeBtnDisabled }" :class="{ 'send-code-btn-disabled': isCodeBtnDisabled }"
@click="sendCode">
<text class="send-code-text"
:class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
>{{ codeBtnText }}</text>
@click="sendCode"
>
<text
class="send-code-text"
:class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
>{{ codeBtnText }}</text
>
</button> </button>
</view> </view>
</view> </view>
<view v-if="switchType === 'Phone'" class="input-with-icon">
<image class="input-icon" src="../../../static/icons/Text-recognition.png" alt="" />
<input
class="input-field"
type="text"
placeholder="请输入密码"
v-model="password"
/>
</view>
<view v-if="switchType === 'Phone'" class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Text-recognition.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入验证码"
v-model="password"
/>
</view>
</view>
<!-- 用户协议 -->
<view @click="changeCheckbox" class="agreement-container-one">
<image
class="checkbox"
:src="checkboxUrl"
></image>
<text class="agreement-text-one"
>接受 <text class="link" @click="openAgreement">用户协议</text>
<text class="link" @click="openPrivacy">隐私政策</text></text
>
</view>
<view v-if="switchType === 'User'" class="agreement-container">
<text class="agreement-text"
><text @click="recoverPassword">忘记ID/密码</text>
</text>
</view> </view>
<!-- 注册按钮 --> <!-- 注册按钮 -->
<button class="register-btn" @click="register">下一步</button>
<button class="register-btn" @click="register">登录</button>
<!-- 或者 --> <!-- 或者 -->
<text class="or-text">或者</text>
<text class="or-text" @click="goToRegistration"
>如果您还没有账号点击注册 >
</text>
<!-- 第三方登录 --> <!-- 第三方登录 -->
<view class="third-party-login"> <view class="third-party-login">
@ -117,7 +204,7 @@
src="../../../static/icons/appleIcons.png" src="../../../static/icons/appleIcons.png"
mode="aspectFit" mode="aspectFit"
></image> ></image>
<text class="third-party-text">通过 Apple 继续</text>
<text class="third-party-text">通过 Apple 登录 </text>
</view> </view>
<view class="third-party-btn" @click="loginWithGoogle"> <view class="third-party-btn" @click="loginWithGoogle">
@ -126,15 +213,9 @@
src="../../../static/icons/GoogleIcons.png" src="../../../static/icons/GoogleIcons.png"
mode="aspectFit" mode="aspectFit"
></image> ></image>
<text class="third-party-text">通过 Google 继续</text>
<text class="third-party-text">通过 Google 登录</text>
</view> </view>
</view> </view>
<!-- 已有账号 -->
<view class="existing-account">
<text class="account-text">未注册账号</text>
<text class="login-link" @click="goToRegistration">注册</text>
</view>
</view> </view>
</template> </template>
@ -151,6 +232,9 @@ const switchType = ref("Email"); // 默认是邮箱注册
const { safeAreaInsets } = uni.getSystemInfoSync(); const { safeAreaInsets } = uni.getSystemInfoSync();
const codeBtnText = ref("获取验证码"); const codeBtnText = ref("获取验证码");
const isCodeBtnDisabled = ref(false); // const isCodeBtnDisabled = ref(false); //
const checkboxUrl = ref("../../../static/icons/Check-one-false.png");
// 使list.js // 使list.js
const countries = ref( const countries = ref(
@ -183,7 +267,14 @@ function showCountryPicker() {
function goToIndex() { function goToIndex() {
// //
uni.navigateTo({ url: "/pages/start/index/index" });
uni.navigateTo({
url: "/pages/start/index/index",
});
}
function switchUser() {
//
switchType.value = "User";
} }
function switchEmail() { function switchEmail() {
@ -236,7 +327,6 @@ function loginWithApple() {
uni.getUserInfo({ uni.getUserInfo({
provider: "apple", provider: "apple",
success: function (info) { success: function (info) {
// , info.authResult
console.log(info); console.log(info);
}, },
}); });
@ -259,7 +349,6 @@ function loginWithGoogle() {
uni.getUserInfo({ uni.getUserInfo({
provider: "google", provider: "google",
success: function (info) { success: function (info) {
// , info.authResult
console.log(info); console.log(info);
}, },
}); });
@ -290,27 +379,53 @@ function onPhoneInput(e) {
} }
} }
function sendCode(){
function sendCode() {
// //
if (isCodeBtnDisabled.value) return; if (isCodeBtnDisabled.value) return;
// //
isCodeBtnDisabled.value = true; isCodeBtnDisabled.value = true;
codeBtnText.value = "重新发送"
let time = 6
codeBtnText.value = "重新发送";
let time = 6;
const timer = setInterval(() => { const timer = setInterval(() => {
time--
codeBtnText.value = "重新发送 " + time + "s"
time--;
codeBtnText.value = "重新发送 " + time + "s";
if (time <= 0) { if (time <= 0) {
clearInterval(timer)
codeBtnText.value = "重新发送"
clearInterval(timer);
codeBtnText.value = "重新发送";
// //
isCodeBtnDisabled.value = false; isCodeBtnDisabled.value = false;
} }
}, 1000)
}, 1000);
return;
}
function openAgreement() {
//
console.log("打开用户协议");
uni.navigateTo({
url: "/pages/start/agreement/agreement",
});
}
function openPrivacy() {
//
console.log("打开隐私政策");
uni.navigateTo({
url: "/pages/start/privacy/privacy",
});
}
return
function recoverPassword() {
//
console.log("忘记密码");
}
function changeCheckbox(){
agreed.value = !agreed.value;
checkboxUrl.value = agreed.value ? "../../../static/icons/Check-one-true.png" : "../../../static/icons/Check-one-false.png";
} }
</script> </script>
@ -320,7 +435,7 @@ function sendCode(){
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 0 40rpx;
padding: 0 70rpx;
height: 100vh; height: 100vh;
background-color: #ffffff; background-color: #ffffff;
} }
@ -356,6 +471,7 @@ function sendCode(){
height: 40rpx; height: 40rpx;
/* margin-right: 10rpx; */ /* margin-right: 10rpx; */
} }
.back-btn, .back-btn,
.headphone-btn { .headphone-btn {
font-size: 36rpx; font-size: 36rpx;
@ -379,6 +495,7 @@ function sendCode(){
/* text-align: left; */ /* text-align: left; */
/* align-self: flex-start; */ /* align-self: flex-start; */
} }
.switch-container { .switch-container {
display: flex; display: flex;
margin-bottom: 40rpx; margin-bottom: 40rpx;
@ -398,7 +515,8 @@ function sendCode(){
bottom: 0; bottom: 0;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
width: 60%; /* 控制边框宽度 */
width: 60%;
/* 控制边框宽度 */
height: 2rpx; height: 2rpx;
background-color: transparent; background-color: transparent;
} }
@ -415,14 +533,14 @@ function sendCode(){
bottom: 0; bottom: 0;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
width: 30%; /* 控制边框宽度 */
width: 30%;
/* 控制边框宽度 */
height: 7rpx; height: 7rpx;
background-color: #333333; background-color: #333333;
} }
.input-container { .input-container {
width: 100%; width: 100%;
margin-bottom: 40rpx;
} }
/* 添加图标输入框样式 */ /* 添加图标输入框样式 */
@ -498,7 +616,7 @@ function sendCode(){
height: 100%; height: 100%;
border: none; border: none;
background-color: transparent; background-color: transparent;
padding: 0 20rpx;
padding: 0 0rpx;
} }
.send-code-btn { .send-code-btn {
@ -512,34 +630,62 @@ function sendCode(){
border-radius: 4px; border-radius: 4px;
background: #000; background: #000;
} }
.send-code-btn-email {
width: 200rpx;
height: 60rpx;
display: inline-flex;
padding: 0rpx 10rpx;
justify-content: center;
align-items: center;
gap: 10px;
border-radius: 4px;
background: #000;
margin-right: 15rpx;
}
.send-code-btn-disabled { .send-code-btn-disabled {
background: #E6E6E6; /* 禁用状态下的灰色背景 */
background: #e6e6e6;
/* 禁用状态下的灰色背景 */
} }
.send-code-btn-disabled-text { .send-code-btn-disabled-text {
color: #999999 !important; color: #999999 !important;
} }
.send-code-text{
.send-code-text {
color: #fff; color: #fff;
font-size: 28rpx; font-size: 28rpx;
} }
.agreement-container-one {
display: flex;
align-items: center;
align-self: flex-start;
margin-bottom: 80rpx;
}
.agreement-container { .agreement-container {
/* display: flex; */
display: flex;
align-items: center; align-items: center;
margin-bottom: 40rpx; margin-bottom: 40rpx;
margin-top: -75.5rpx;
align-self: flex-start; align-self: flex-start;
} }
.checkbox { .checkbox {
width: 10rpx;
height: 10rpx;
margin-right: 30rpx;
width: 30rpx;
height: 30rpx;
margin-left: 20rpx;
/* flex: content; */ /* flex: content; */
} }
.agreement-text-one {
font-size: 22rpx;
color: #666666;
text-align: center;
margin-left: 10rpx;
}
.agreement-text { .agreement-text {
margin-left: 20rpx; margin-left: 20rpx;
font-size: 24rpx; font-size: 24rpx;
@ -573,14 +719,17 @@ function sendCode(){
width: 100%; width: 100%;
margin-bottom: 60rpx; margin-bottom: 60rpx;
} }
.third-party-text { .third-party-text {
color: #ffffff;
font-weight: bold; font-weight: bold;
white-space: pre;
} }
.third-party-btn { .third-party-btn {
width: 100%; width: 100%;
height: 80rpx; height: 80rpx;
background-color: white;
background-color: rgb(0, 0, 0);
border: 2rpx solid #e5e5e5; border: 2rpx solid #e5e5e5;
border-radius: 40rpx; border-radius: 40rpx;
display: flex; display: flex;
@ -591,15 +740,10 @@ function sendCode(){
color: #333333; color: #333333;
} }
.google-icon,
.apple-icon { .apple-icon {
width: 30rpx;
height: 30rpx;
margin-right: 20rpx;
}
.google-icon {
width: 30rpx;
height: 30rpx;
width: 60rpx;
height: 60rpx;
margin-right: 20rpx; margin-right: 20rpx;
} }

BIN
static/icons/Check-one-false.png

After

Width: 32  |  Height: 32  |  Size: 1.1 KiB

BIN
static/icons/Check-one-true.png

After

Width: 32  |  Height: 32  |  Size: 1.4 KiB

Loading…
Cancel
Save