You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
509 lines
9.9 KiB
509 lines
9.9 KiB
<template>
|
|
<view class="login-registration-container">
|
|
<!-- 自定义导航栏 -->
|
|
<view
|
|
class="custom-navbar"
|
|
:style="{ paddingTop: safeAreaInsets?.top + 'px' }"
|
|
>
|
|
<view class="nav-left">
|
|
<text class="back-btn" @click="goToIndex"><</text>
|
|
</view>
|
|
<view class="nav-right">
|
|
<text class="headphone-btn">🎧</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- Logo -->
|
|
<!-- <image class="logo" src="/static/logo.png" mode="aspectFit"></image> -->
|
|
|
|
<!-- 欢迎语 -->
|
|
<text class="welcome-text">登录DeepChart</text>
|
|
|
|
<!-- 邮箱/手机号切换 -->
|
|
<view class="switch-container">
|
|
<text
|
|
class="switch-item"
|
|
:class="{ active: switchType === 'Email' }"
|
|
@click="switchEmail"
|
|
>邮箱/用户名</text
|
|
>
|
|
<text
|
|
class="switch-item"
|
|
:class="{ active: switchType === 'Phone' }"
|
|
@click="switchPhone"
|
|
>手机号</text
|
|
>
|
|
</view>
|
|
<!-- 输入框 -->
|
|
<view class="input-container">
|
|
<input
|
|
v-if="switchType === 'Email'"
|
|
class="input-field"
|
|
type="text"
|
|
placeholder="输入邮箱/用户名"
|
|
v-model="email"
|
|
/>
|
|
<view v-else class="phone-input-container">
|
|
<view class="country-code-selector" @click="showCountryPicker">
|
|
<image
|
|
class="country-flag-img"
|
|
:src="selectedCountry.flag"
|
|
mode="aspectFit"
|
|
></image>
|
|
<text class="country-code">{{ selectedCountry.code }}</text>
|
|
<text class="arrow-down">▼</text>
|
|
</view>
|
|
<input
|
|
class="input-field phone-input"
|
|
type="number"
|
|
placeholder="输入手机号"
|
|
v-model="phone"
|
|
@input="onPhoneInput"
|
|
/>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 注册按钮 -->
|
|
<button class="register-btn" @click="register">下一步</button>
|
|
|
|
<!-- 或者 -->
|
|
<text class="or-text">或者</text>
|
|
|
|
<!-- 第三方登录 -->
|
|
<view class="third-party-login">
|
|
<view class="third-party-btn" @click="loginWithApple">
|
|
<image
|
|
class="apple-icon"
|
|
src="/static/apple-icon.png"
|
|
mode="aspectFit"
|
|
></image>
|
|
<text class="third-party-text">通过 Apple 继续</text>
|
|
</view>
|
|
|
|
<view class="third-party-btn" @click="loginWithGoogle">
|
|
<image
|
|
class="google-icon"
|
|
src="/static/google-icon.png"
|
|
mode="aspectFit"
|
|
></image>
|
|
<text class="third-party-text">通过 Google 继续</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 已有账号 -->
|
|
<view class="existing-account">
|
|
<text class="account-text">未注册账号?</text>
|
|
<text class="login-link" @click="goToRegistration">注册</text>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from "vue";
|
|
// 导入完整的国家列表
|
|
import countryList from "./list.js";
|
|
|
|
const email = ref("");
|
|
const phone = ref("");
|
|
const agreed = ref(false);
|
|
const switchType = ref("Email"); // 默认是邮箱注册
|
|
const { safeAreaInsets } = uni.getSystemInfoSync();
|
|
|
|
// 使用从list.js导入的完整国家列表数据
|
|
const countries = ref(
|
|
countryList.list.map((item) => ({
|
|
name: item.name,
|
|
code: `+${item.tel}`,
|
|
flag: item.flag,
|
|
short: item.short,
|
|
en: item.en,
|
|
}))
|
|
);
|
|
|
|
// 默认选中的国家(中国)
|
|
const selectedCountry = ref(
|
|
countries.value.find((country) => country.short === "CN") ||
|
|
countries.value[0]
|
|
);
|
|
|
|
// 显示国家选择器
|
|
function showCountryPicker() {
|
|
uni.showActionSheet({
|
|
itemList: countries.value.map(
|
|
(country) => `${country.name} ${country.code}`
|
|
),
|
|
success: function (res) {
|
|
selectedCountry.value = countries.value[res.tapIndex];
|
|
},
|
|
});
|
|
}
|
|
|
|
function goToIndex() {
|
|
// 返回上一页
|
|
uni.navigateTo({ url: "/pages/start/index/index" });
|
|
}
|
|
|
|
function switchEmail() {
|
|
// 切换到邮箱注册
|
|
switchType.value = "Email";
|
|
}
|
|
|
|
function switchPhone() {
|
|
// 切换到手机注册
|
|
switchType.value = "Phone";
|
|
}
|
|
|
|
function register() {
|
|
if (switchType.value === "Email") {
|
|
// 登录逻辑
|
|
if (!email.value) {
|
|
uni.showToast({
|
|
title: "请输入邮箱地址",
|
|
icon: "none",
|
|
});
|
|
return;
|
|
}
|
|
|
|
// 发送登录请求
|
|
console.log("登录:", email.value);
|
|
}
|
|
|
|
if (switchType.value === "Phone") {
|
|
// 登录逻辑
|
|
if (!phone.value) {
|
|
uni.showToast({
|
|
title: "请输入手机号码",
|
|
icon: "none",
|
|
});
|
|
return;
|
|
}
|
|
|
|
// 发送登录请求
|
|
console.log("登录:", phone.value);
|
|
}
|
|
}
|
|
|
|
function loginWithApple() {
|
|
// Apple登录逻辑
|
|
console.log("通过Apple登录");
|
|
uni.login({
|
|
provider: "apple",
|
|
success: function (loginRes) {
|
|
// 登录成功
|
|
uni.getUserInfo({
|
|
provider: "apple",
|
|
success: function (info) {
|
|
// 获取用户信息成功, info.authResult中保存登录认证数据
|
|
console.log(info);
|
|
},
|
|
});
|
|
},
|
|
fail: function (err) {
|
|
// 登录授权失败
|
|
// err.code错误码参考`授权失败错误码(code)说明`
|
|
console.log(err);
|
|
|
|
},
|
|
});
|
|
}
|
|
|
|
function loginWithGoogle() {
|
|
// Google登录逻辑
|
|
console.log("通过Google登录");
|
|
uni.login({
|
|
provider: "google",
|
|
success: function (loginRes) {
|
|
// 登录成功
|
|
uni.getUserInfo({
|
|
provider: "google",
|
|
success: function (info) {
|
|
// 获取用户信息成功, info.authResult保存用户信息
|
|
console.log(info);
|
|
},
|
|
});
|
|
},
|
|
fail: function (err) {
|
|
// 登录授权失败
|
|
// err.code是错误码
|
|
console.log(err);
|
|
},
|
|
});
|
|
}
|
|
|
|
function goToRegistration() {
|
|
// 跳转到登录页
|
|
uni.navigateTo({
|
|
url: "/pages/start/Registration/Registration",
|
|
});
|
|
}
|
|
|
|
function onPhoneInput(e) {
|
|
// 确保只允许输入数字
|
|
const value = e.detail.value;
|
|
// 使用 isNaN 检查是否为有效数字
|
|
if (isNaN(value)) {
|
|
phone.value = "";
|
|
} else {
|
|
phone.value = value;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.login-registration-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 0 40rpx;
|
|
height: 100vh;
|
|
background-color: #ffffff;
|
|
}
|
|
|
|
/* 自定义导航栏样式 */
|
|
.custom-navbar {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
/* z-index: 999; */
|
|
width: 90%;
|
|
height: 80rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 10rpx 40rpx;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.nav-left,
|
|
.nav-right {
|
|
flex: 1;
|
|
}
|
|
|
|
.nav-right {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.back-btn,
|
|
.headphone-btn {
|
|
font-size: 36rpx;
|
|
font-weight: bold;
|
|
color: #333333;
|
|
padding: 10rpx;
|
|
}
|
|
|
|
.logo {
|
|
width: 120rpx;
|
|
height: 120rpx;
|
|
margin-bottom: 60rpx;
|
|
border-radius: 20%;
|
|
}
|
|
|
|
.welcome-text {
|
|
font-size: 48rpx;
|
|
font-weight: bold;
|
|
color: #333333;
|
|
margin-bottom: 60rpx;
|
|
/* text-align: left; */
|
|
/* align-self: flex-start; */
|
|
}
|
|
.switch-container {
|
|
display: flex;
|
|
margin-bottom: 40rpx;
|
|
align-self: flex-start;
|
|
}
|
|
|
|
.switch-item {
|
|
font-size: 28rpx;
|
|
color: #999999;
|
|
padding: 10rpx 20rpx;
|
|
position: relative;
|
|
}
|
|
|
|
.switch-item::after {
|
|
content: "";
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 60%; /* 控制边框宽度 */
|
|
height: 2rpx;
|
|
background-color: transparent;
|
|
}
|
|
|
|
.switch-item.active {
|
|
color: #333333;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.switch-item.active::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 60rpx;
|
|
bottom: 0;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 30%; /* 控制边框宽度 */
|
|
height: 7rpx;
|
|
background-color: #333333;
|
|
}
|
|
|
|
.input-container {
|
|
width: 100%;
|
|
margin-bottom: 40rpx;
|
|
}
|
|
|
|
.input-field {
|
|
width: 90%;
|
|
height: 80rpx;
|
|
border-radius: 20rpx;
|
|
border: 2rpx solid #e5e5e5;
|
|
padding: 0 30rpx;
|
|
font-size: 28rpx;
|
|
color: #333333;
|
|
background-color: #f5f5f5;
|
|
}
|
|
|
|
.phone-input-container {
|
|
display: flex;
|
|
align-items: center;
|
|
width: 95.8%;
|
|
height: 80rpx;
|
|
border-radius: 20rpx;
|
|
border: 2rpx solid #e5e5e5;
|
|
background-color: #f5f5f5;
|
|
padding: 0 10rpx;
|
|
}
|
|
|
|
.country-code-selector {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 0 20rpx;
|
|
height: 100%;
|
|
border-right: 2rpx solid #e5e5e5;
|
|
background-color: #f5f5f5;
|
|
border-radius: 20rpx 0 0 20rpx;
|
|
}
|
|
|
|
.country-code {
|
|
font-size: 28rpx;
|
|
color: #333333;
|
|
margin-right: 10rpx;
|
|
}
|
|
|
|
.country-flag-img {
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
margin-right: 10rpx;
|
|
}
|
|
|
|
.arrow-down {
|
|
font-size: 20rpx;
|
|
color: #999999;
|
|
}
|
|
|
|
.phone-input {
|
|
flex: 1;
|
|
width: auto;
|
|
height: 100%;
|
|
border: none;
|
|
background-color: transparent;
|
|
padding: 0 20rpx;
|
|
}
|
|
|
|
.agreement-container {
|
|
/* display: flex; */
|
|
align-items: center;
|
|
margin-bottom: 40rpx;
|
|
align-self: flex-start;
|
|
}
|
|
|
|
.checkbox {
|
|
width: 10rpx;
|
|
height: 10rpx;
|
|
margin-right: 30rpx;
|
|
/* flex: content; */
|
|
}
|
|
|
|
.agreement-text {
|
|
margin-left: 20rpx;
|
|
font-size: 24rpx;
|
|
color: #666666;
|
|
}
|
|
|
|
.link {
|
|
color: #333333;
|
|
font-weight: bold;
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.register-btn {
|
|
width: 100%;
|
|
height: 80rpx;
|
|
background-color: #333333;
|
|
color: white;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
border-radius: 40rpx;
|
|
margin-bottom: 40rpx;
|
|
}
|
|
|
|
.or-text {
|
|
font-size: 24rpx;
|
|
color: #999999;
|
|
margin-bottom: 40rpx;
|
|
}
|
|
|
|
.third-party-login {
|
|
width: 100%;
|
|
margin-bottom: 60rpx;
|
|
}
|
|
.third-party-text {
|
|
font-weight: bold;
|
|
}
|
|
|
|
.third-party-btn {
|
|
width: 100%;
|
|
height: 80rpx;
|
|
background-color: white;
|
|
border: 2rpx solid #e5e5e5;
|
|
border-radius: 40rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-bottom: 20rpx;
|
|
font-size: 28rpx;
|
|
color: #333333;
|
|
}
|
|
|
|
.apple-icon {
|
|
width: 30rpx;
|
|
height: 30rpx;
|
|
margin-right: 20rpx;
|
|
}
|
|
|
|
.google-icon {
|
|
width: 30rpx;
|
|
height: 30rpx;
|
|
margin-right: 20rpx;
|
|
}
|
|
|
|
.existing-account {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.account-text {
|
|
font-size: 24rpx;
|
|
color: #666666;
|
|
}
|
|
|
|
.login-link {
|
|
font-size: 24rpx;
|
|
font-weight: bold;
|
|
color: #333333;
|
|
margin-left: 10rpx;
|
|
text-decoration: underline;
|
|
}
|
|
</style>
|