|
|
<template> <view class="login-registration-container"> <!-- 自定义导航栏 --> <view class="custom-navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }" > <view class="nav-left"> <image class="icons" @click="goToBack" src="../../../static/icons/back.png" alt="返回首页" /> </view> <view class="nav-right"> <image class="icons" @click="goToService" src="../../../static/icons/Headset.png" alt="联系客服" /> </view> </view>
<!-- Logo --> <!-- <image class="logo" src="/static/logo.png" mode="aspectFit"></image> -->
<!-- 欢迎语 --> <text class="welcome-text">找回密码</text>
<!-- 邮箱/手机号切换 --> <view v-if="!isRecovering" 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 v-else class="switch-container-occupy"> </view> <!-- 输入框 --> <view v-if="isRecovering" class="input-container"> <view> <!-- 修改邮箱输入框容器,将图标包含在内 --> <view class="input-with-icon"> <image class="input-icon" src="../../../static/icons/Unlock.png" alt="" /> <input class="input-field" :type="newPasswordLookFirst ? 'text' : 'password'" placeholder="输入新密码" v-model="newPasswordFirst" /> <image class="input-icon-eye" @click="newPasswordLookFirst = !newPasswordLookFirst" :src=" !newPasswordLookFirst ? '../../../static/icons/unlook.png' : '../../../static/icons/look.png' " alt="" /> </view> <view class="input-with-icon"> <image class="input-icon" src="../../../static/icons/Unlock.png" alt="" /> <input class="input-field" :type="newPasswordLookSecond ? 'text' : 'password'" placeholder="再次确认" v-model="newPasswordSecond" /> <image class="input-icon-eye" @click="newPasswordLookSecond = !newPasswordLookSecond" :src=" !newPasswordLookSecond ? '../../../static/icons/unlook.png' : '../../../static/icons/look.png' " alt="" /> </view> </view> </view> <view v-else class="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="verifyCode" /> </view> </view> <view v-if="switchType === 'Phone'" class="phone-input-container"> <view class="country-code-selector" @click="showCountryPicker"> <image class="country-flag-img" src="../../../static/icons/Iphone.png" 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> <button 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 > </button> </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="verifyCode" /> </view> </view>
<!-- 用户协议 --> <view @click="changeCheckbox" class="agreement-container-one"> <text class="agreement-text-one" :style="!isRecovering ? 'visibility: hidden' : 'visibility: visible'" > 密码最少8位数 </text> </view>
<!-- 注册按钮 --> <button class="register-btn" @click="register"> {{ isRecovering ? "确认" : "下一步" }} </button>
<!-- 或者 --> <text class="or-text-one" @click="goToRegistration" >如果您还没有账号,点击注册 <image class="to-icon" src="../../../static/icons/To.png"></image> </text>
<!-- 或者 --> <text class="or-text" @click="goToLogin" >已有账号? <text class="link">登录 </text> </text>
<!-- 同意弹窗 --> <uniPopup ref="agreementPopup" type="dialog"> <view class="popup-content"> <text class="popup-title">同意并继续</text> <text class="popup-message">请阅读并同意服务协议和隐私权限</text> <button class="agree-button" @click="handleAgree"> <text class="agree-text">同意</text> </button> </view> </uniPopup> <footerBar class="static-footer" :type="type"></footerBar> </view></template>
<script setup>import { ref } from "vue";// 导入完整的国家列表
import countryList from "../login/list";import footerBar from "../../../components/footerBar";import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";import { verificationPhone, verificationEmail } from "../login/verification";import { SendEmailCodeApi, SendPhoneCodeApi, verifyCodeApi, forgetApi,} from "../../../api/start/login";
const type = ref("");const email = ref("");const password = ref("");const newPasswordFirst = ref("");const newPasswordSecond = ref("");const phone = ref("");const country = ref("+86");const agreed = ref(false);const switchType = ref("Phone"); // 默认是邮箱注册
const { safeAreaInsets } = uni.getSystemInfoSync();const codeBtnText = ref("获取验证码");const isCodeBtnDisabled = ref(false); // 添加验证码按钮禁用状态
const checkboxUrl = ref("../../../static/icons/Check-one-false.png");const verifyCode = ref("");const isRecovering = ref(false);const newPasswordLookFirst = ref(false);const newPasswordLookSecond = ref(false);const account = ref("");
// 使用从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 goToBack() { // 返回上一页
uni.navigateBack(-1);}
function goToService() { // 返回上一页
uni.navigateTo({ url: "/pages/customerServicePlatform/csPlatformIndex", });}
function switchEmail() { // 切换到邮箱注册
switchType.value = "Email"; verifyCode.value = "";}
function switchPhone() { // 切换到手机注册
switchType.value = "Phone"; verifyCode.value = "";}
async function register() { if (isRecovering.value) { if (!newPasswordFirst.value || !newPasswordSecond.value) { uni.showToast({ title: "密码不能为空", icon: "none", }); return; }
if (newPasswordFirst.value !== newPasswordSecond.value) { uni.showToast({ title: "前后密码不一致", icon: "none", }); return; }
const account = changeAccount();
const res = await forgetApi({ account: account, password: newPasswordSecond.value, });
console.log("res", res);
if (res.code !== 200) { uni.showToast({ title: res.message, icon: "none", }); return; }
uni.showToast({ title: res.message, icon: "none", });
uni.navigateTo({ url: "/pages/start/login/login", });
// 密码逻辑
return; }
if (switchType.value === "Phone") { // 登录逻辑
if (!phone.value) { uni.showToast({ title: "请输入手机号码", icon: "none", }); return; }
console.log("123");
const phoneAll = `${country.value}${phone.value}`; console.log("完整手机号" + phoneAll); if (!validatePhoneNumber(country.value, phone.value)) { return; }
if (!verifyCode.value) { uni.showToast({ title: "请输入验证码", icon: "none", }); return; } }
if (switchType.value === "Email") { // 登录逻辑
if (!email.value) { uni.showToast({ title: "请输入邮箱地址", icon: "none", }); return; }
const bool = verificationEmail(email.value); console.log("验证是否成功", bool);
// 检查格式是否正确
if (!bool) { uni.showToast({ title: "邮箱格式不正确", icon: "none", }); return; }
if (!verifyCode.value) { uni.showToast({ title: "请输入验证码", icon: "none", }); return; }
// 发送登录请求
console.log("登录:", email.value); }
const account = changeAccount(); const loginType = changeLoginType();
const res = await verifyCodeApi({ loginType: loginType, //登录方式EMAIL,PHONE
account: account, //登陆账号 手机号/邮箱
verifyCode: verifyCode.value, });
if (res.code !== 200) { uni.showToast({ title: res.message, icon: "none", }); return; }
isRecovering.value = !isRecovering.value;}
// 请求账户
function changeAccount() { if (switchType.value === "User") { account.value = deepChartID.value; }
if (switchType.value === "Phone") { account.value = `${country.value}${phone.value}`; } if (switchType.value === "Email") { account.value = email.value; }
return account.value;}
// 改变请求时的type
function changeLoginType() { if (switchType.value === "User") { return "DCCODE"; }
if (switchType.value === "Phone") { return "PHONE"; } if (switchType.value === "Email") { return "EMAIL"; }}
function goToLogin() { // 跳转到登录页
uni.navigateTo({ url: "/pages/start/login/login", });}
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; }}
// 注册码码验证
function VerCodeVerfifcation() { if (switchType.value === "Phone") { if (!phone.value) { uni.showToast({ title: "请输入手机号", icon: "none", }); return false; }
const bool = verificationPhone(country.value, phone.value); console.log("验证是否成功", bool);
// 检查格式是否正确
if (!bool) { uni.showToast({ title: "手机号格式不正确", icon: "none", }); return false; } }
if (switchType.value === "Email") { if (!email.value) { uni.showToast({ title: "请输入邮箱地址", icon: "none", }); return false; } const bool = verificationEmail(email.value); console.log("验证是否成功", bool);
// 检查格式是否正确
if (!bool) { uni.showToast({ title: "邮箱格式不正确", icon: "none", }); return false; } }
return true;}
// 发送验证码
function sendCode() { if (!VerCodeVerfifcation()) { return; } // 如果按钮已禁用,则不执行后续逻辑
if (isCodeBtnDisabled.value) return;
console.log("发送验证码"); // 发送验证码
if (switchType.value === "Email") { const res = SendEmailCodeApi({ email: email.value, });
if (!res) { uni.showToast({ title: "发送失败", icon: "none", }); } } if (switchType.value === "Phone") { const phoneAll = `${country.value}${phone.value}`;
const res = SendPhoneCodeApi({ phone: phoneAll, }); if (!res) { uni.showToast({ title: "发送失败", icon: "none", }); } }
// 设置按钮为禁用状态
isCodeBtnDisabled.value = true; codeBtnText.value = "重新发送"; let time = 6; const timer = setInterval(() => { time--; codeBtnText.value = "重新发送 " + time + "s"; if (time <= 0) { clearInterval(timer); codeBtnText.value = "重新发送"; // 倒计时结束后启用按钮
isCodeBtnDisabled.value = false; } }, 1000);
return;}
function openAgreement() { // 打开用户协议
console.log("打开用户协议"); uni.navigateTo({ url: "/pages/start/agreement/agreement", });}
function openPrivacy() { // 打开隐私政策
console.log("打开隐私政策"); uni.navigateTo({ url: "/pages/start/privacy/privacy", });}
function changeCheckbox() { agreed.value = !agreed.value; checkboxUrl.value = agreed.value ? "../../../static/icons/Check-one-true.png" : "../../../static/icons/Check-one-false.png";}
// 验证手机号是否正确
function validatePhoneNumber(countryCode, phoneNumber) { // 检查是否为空
if (!phoneNumber || phoneNumber.trim() === "") { uni.showToast({ title: "手机号不能为空", icon: "none", }); return false; }
const bool = verificationPhone(countryCode, phoneNumber); console.log("验证是否成功", bool);
// 检查格式是否正确
if (!bool) { uni.showToast({ title: "手机号格式不正确", icon: "none", });
return false; }
// 去掉+号后检查长度(手机号通常在7到15位之间)
const cleanNumber = phoneNumber.replace(/^\+/, ""); if (cleanNumber.length < 7 || cleanNumber.length > 15) { uni.showToast({ title: "手机号长度不正确", icon: "none", }); return false; }
return true;}
// 添加弹窗引用
const agreementPopup = ref(null);
// 处理同意按钮点击
function handleAgree() { // 关闭弹窗
agreementPopup.value.close(); // 设置为已同意
agreed.value = true; checkboxUrl.value = "../../../static/icons/Check-one-true.png"; // 继续登录流程
}</script>
<style scoped>.login-registration-container { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 0 70rpx; 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;}.nav-left { display: flex; justify-content: flex-start;}
.icons { margin: 20rpx; width: 40rpx; height: 40rpx; /* margin-right: 10rpx; */}
.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%;}
/* 添加图标输入框样式 */.input-with-icon { display: flex; align-items: center; width: 100%; height: 80rpx; border-bottom: 2rpx solid #e5e5e5; margin-bottom: 20rpx;}
.input-icon { width: 40rpx; height: 40rpx; margin: 0 20rpx;}.input-icon-eye { width: 40rpx; height: 20rpx; margin: 0 20rpx;}
.input-field { flex: 1; height: 80rpx; padding: 15rpx 0; font-size: 28rpx; color: #333333; border: none; background-color: transparent;}
.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; border-bottom: 2rpx solid #e5e5e5; margin-bottom: 20rpx;}
.country-code-selector { display: flex; align-items: center; padding: 0 10rpx; padding-bottom: 1rpx; 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 0rpx;}
.send-code-btn { width: 200rpx; height: 60rpx; display: inline-flex; padding: 0rpx 10rpx; justify-content: center; align-items: center; gap: 10px; border-radius: 4px; 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 { background: #e6e6e6; /* 禁用状态下的灰色背景 */}
.send-code-btn-disabled-text { color: #999999 !important;}
.send-code-text { color: #fff; font-size: 28rpx;}
.agreement-container-one { display: flex; align-items: center; align-self: flex-start; margin-bottom: 80rpx;}
.agreement-container { display: flex; align-items: center; margin-bottom: 40rpx; margin-top: -75.5rpx; align-self: flex-start;}
.checkbox { width: 30rpx; height: 30rpx; margin-left: 20rpx; /* flex: content; */}
.agreement-text-one { font-size: 22rpx; color: #666666; text-align: center; margin-left: 10rpx;}
.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: #000000; color: white; font-size: 32rpx; font-weight: bold; border-radius: 40rpx; margin-bottom: 40rpx;}
.or-text { flex-direction: column; font-size: 24rpx; color: #999999; margin-top: 294rpx; margin-bottom: -22rpx;}
.to-icon { width: 10rpx; height: 16rpx;}
.or-text-one { flex-direction: column; font-size: 24rpx; color: #999999;}
.third-party-login { width: 100%; margin-bottom: 60rpx;}
.third-party-text { color: #ffffff; font-weight: bold; white-space: pre;}
.third-party-btn { width: 100%; height: 80rpx; background-color: rgb(0, 0, 0); border: 2rpx solid #e5e5e5; border-radius: 40rpx; display: flex; align-items: center; justify-content: center; margin-bottom: 20rpx; font-size: 28rpx; color: #333333;}
.google-icon,.apple-icon { width: 60rpx; height: 60rpx; 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;}
.static-footer { position: fixed; bottom: 0;}
/* 弹窗样式 */.popup-content { background-color: #ffffff; padding: 40rpx; text-align: center; border-radius: 10rpx; width: 550rpx;}
.popup-title { font-size: 36rpx; font-weight: bold; color: #333; margin-bottom: 80rpx; text-align: center; /* 水平居中 */ display: flex; /* 使用flex布局 */ justify-content: center; /* 水平居中 */ align-items: center; /* 垂直居中 */}
.popup-message { font-size: 28rpx; color: #000000; margin-bottom: 80rpx; text-align: center; /* 水平居中 */ display: flex; /* 使用flex布局 */ justify-content: center; /* 水平居中 */ align-items: center; /* 垂直居中 */}
.agree-button { width: 300rpx; height: 80rpx; background-color: #000000; border-radius: 40rpx; display: flex; /* 添加flex布局 */ align-items: center; /* 垂直居中 */ justify-content: center; /* 水平居中 */}.agree-text { color: #ffffff; font-size: 34rpx; /* 添加垂直居中相关样式 */ display: flex; align-items: center; justify-content: center; line-height: 1; /* 确保文字垂直居中 */}
.switch-container-occupy { margin-top: 100rpx;}</style>
|