mrr.sj.front/pages/blogPopup/blogPopup.vue

1029 lines
29 KiB
Vue
Raw Permalink 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>
<!-- 底部弹窗蒙层 -->
<view class="login-mask" :style="{background:maskShow?`rgba(0, 0, 0, 0.5)`:`transparent`}" @tap="closeWindow">
<!-- 底部弹窗内容 -->
<view class="login-popup" @tap.stop.prevent v-show="maskShow">
<!-- 弹窗头部标题+关闭按钮 -->
<view class="popup-header">
<text class="popup-title">登录享更多服务</text>
</view>
<image class="popup-close" src="/static/images/icons/close.png" @click="closeWindow" />
<!-- 登录选项卡 -->
<view class="login-tabs">
<view class="tab-item" :class="{active: loginType === 'code'}" @click="loginType = 'code'">验证码</view>
<view class="tab-line"></view>
<view class="tab-item" :class="{active: loginType === 'account'}" @click="loginType = 'account'">账号密码
</view>
<view class="tab-line"></view>
<view class="tab-item" :class="{active: loginType === 'onekey'}" @click="handleOnekeyTab">一键登录</view>
</view>
<!-- 输入区域根据选项卡切换 -->
<view class="input-area">
<!-- 验证码登录 -->
<template v-if="loginType === 'code'">
<view class="input-item">
<uv-album></uv-album>
<image class="input-icon-phone" mode="widthFix" src="/static/images/icons/log_phone.png" />
<input type="number" v-model="phone" placeholder="请输入手机号码" :adjust-position="false"
class="input-text" @input="handlePhoneInput" />
</view>
<!-- 手机号错误提示 -->
<text class="input-error" v-if="phoneError">{{phoneError}}</text>
<view class="input-item">
<image class="input-icon-password" mode="widthFix"
src="/static/images/icons/log_password.png" />
<input type="number" v-model="code" placeholder="请输入验证码" :adjust-position="false"
class="input-text" maxlength="6" />
<uv-code keepRunning :seconds="seconds" @end="end" @start="start" ref="code"
@change="codeChange"></uv-code>
<text class="get-code-btn" :class="{running:runningCode,noPhone:!phone}"
@tap="getCode">{{tips}}</text>
</view>
</template>
<!-- 账号密码登录 -->
<template v-else-if="loginType === 'account'">
<view class="input-item">
<image class="input-icon-phone" mode="widthFix" src="/static/images/icons/log_phone.png" />
<input v-model="phone" placeholder="请输入账号" class="input-text" :adjust-position="false"
@input="handlePhoneInput" />
</view>
<!-- 手机号错误提示 -->
<text class="input-error" v-if="phoneError">请输入正确的账号</text>
<view class="input-item">
<image class="input-icon-password" mode="widthFix"
src="/static/images/icons/log_password.png" />
<input type="text" v-model="password" placeholder="请输入密码" :adjust-position="false"
:password="!showPassword" class="input-text" />
<image src="/static/images/icons/noLook.png" mode="widthFix" class="look-icon"
v-if="!showPassword" @click.stop="showPassword = true"></image>
<image src="/static/images//icons/look.png" mode="widthFix" class="look-icon"
@click.stop="showPassword = false" v-else></image>
</view>
</template>
</view>
<!-- 登录按钮(根据选项卡/输入状态切换样式) -->
<view class="login-btn" :class="{active: canLogin}" @click="handleLogin">
立即登录
</view>
<!-- 协议勾选 -->
<view class="agree">
<agree-radio :isAgree="isAgree" @change-agree="changeAgree" class="agree-btn"></agree-radio>
<view class="agree-card">
<text class="agree-text">未注册手机号登录后将自动生成账号,且代表您已阅读并同意,</text>
<text class="agreement" @click="goAgreement(28)">《用户注册协议》</text>
<text class="agreement" @click="goAgreement(26)">《隐私政策》</text>
</view>
</view>
</view>
</view>
</template>
<script>
import {
isNotificationsEnabled,
permissions,
registPush
} from '@/utils/AS-NotifyTheAuthority.js'
import AgreeRadio from '@/components/agree-radio/agree-radio.vue'
import request from '@/utils/request';
import uiConfig from "@/utils/ui-config.js"
const aLiSDKModule = uni.requireNativePlugin('AliCloud-NirvanaPns');
export default {
components: {
AgreeRadio
},
data() {
return {
isFirst:false,//是否第一次打开
showPassword: false, // 是否展示密码
maskShow: true,
loginType: 'code', // 当前选项卡code/account/onekey
phone: '', // 验证码-手机号
code: '', // 验证码-验证码
password: '', // 账号密码-密码
account: '', // 账号密码-账号
isAgree: false, // 协议勾选状态
tips: '',
seconds: 60,
phoneError: '', // 手机号错误提示
runningCode: false, //是否在倒计时
}
},
onLoad() {
// this.checkAndroidPermission()
this.isFirst = true
this.handleOnekeyTab()
},
computed: {
// 判断是否可登录(匹配示例按钮状态)
canLogin() {
if (this.loginType === 'code') {
return this.isAgree && this.phone && this.code && this.code.length >= 4 && !this.phoneError;
} else if (this.loginType === 'account') {
return this.isAgree && this.phone && this.password && !this.phoneError;
} else if (this.loginType === 'onekey') {
return this.isAgree;
}
return false;
}
},
methods: {
/**
* 检查安卓系统权限(设备信息/短信)
*/
checkAndroidPermission() {
// #ifdef APP-PLUS
const permissions = [
'android.permission.READ_PHONE_STATE'
];
plus.android.requestPermissions(permissions, (result) => {
const { granted, neverDenied } = result;
console.log(11111111,result)
if (neverDenied.length > 0) {
// 永久拒绝:引导用户去系统设置页开启
uni.showModal({
title: '权限提示',
content: '需要您开启设备信息和短信权限才能使用一键登录',
success: (res) => {
if (res.confirm) {
plus.android.openSettings(); // 打开安卓设置页
}
}
});
} else if (granted.length === permissions.length) {
// 已授权:继续运营商一键登录
this.checkOperatorAuth();
}
}, (err) => {
console.error('申请权限失败:', err);
});
// #endif
},
// 是否同意修改
changeAgree(value) {
this.isAgree = value;
},
goAgreement(type) {
uni.navigateTo({
url: "/pages/agreement/agreement?type=" + type
})
},
codeChange(text) {
this.tips = text;
},
/**
* 获取手机号今日获取验证码的次数
* @param {String} phone - 手机号
* @returns {Number} 今日获取次数
*/
getPhoneCodeCount(phone) {
// 生成今日日期YYYY-MM-DD作为本地存储key的一部分确保按自然日统计
const today = new Date().toISOString().split('T')[0];
// 定义本地存储的keycode_count_手机号_日期
const storageKey = `code_count_${phone}_${today}`;
// 从本地存储获取次数默认0
const count = uni.getStorageSync(storageKey) || 0;
return Number(count);
},
/**
* 更新手机号今日获取验证码的次数(+1
* @param {String} phone - 手机号
*/
updatePhoneCodeCount(phone) {
const today = new Date().toISOString().split('T')[0];
const storageKey = `code_count_${phone}_${today}`;
const count = this.getPhoneCodeCount(phone);
// 存储新的次数(+1
uni.setStorageSync(storageKey, count + 1);
},
getCode() {
let that = this
// 验证手机号(双重校验,确保接口请求时手机号合法)
if (this.phoneError) {
uni.showToast({
title: this.phoneError,
icon: 'none'
})
return
}
if (!this.phone) {
uni.showToast({
title: "请输入手机号",
icon: 'none'
})
return
}
// ------ 单日单手机号最多获取10次开始 ------
const codeCount = this.getPhoneCodeCount(this.phone);
if (codeCount >= 10) {
uni.showToast({
title: '今日获取验证码次数已达上限,请明日再试',
icon: 'none',
duration: 2000
});
return;
}
// ------ 单日单手机号最多获取10次结束 ------
if (this.$refs.code.canGetCode) {
uni.showLoading({
title: '正在获取验证码'
})
// 请求获取验证码接口
request.post('/user/sendcode', {
account: that.phone,
type: 2
}).then(result => {
uni.hideLoading();
if (result.state == 1) {
uni.showToast({
title: result.msg,
icon: 'none'
})
this.$refs.code.start();
// 更新手机号今日获取次数(仅当接口请求成功时计数)
this.updatePhoneCodeCount(this.phone);
} else {
uni.showToast({
title: result.msg,
icon: 'none'
})
}
}).catch(err => {
uni.hideLoading();
uni.showToast({
title: err.msg,
icon: 'none'
})
})
} else {
uni.$uv.toast('倒计时结束后再发送');
}
},
end() {
this.runningCode = false
},
start() {
this.runningCode = true
},
// 关闭弹窗
closeWindow() {
uni.navigateBack({
delta: 1
});
},
// 点击“一键登录”选项卡:直接唤起原生弹窗(不处理类型切换)
handleOnekeyTab() {
// this.loginType = 'onekey';
// 延迟100ms确保选项卡切换完成后调用
try {
// 加速登录页加载
aLiSDKModule.accelerateLoginPage(5000, (result) => {
console.log('加速授权页结果:', JSON.stringify(result));
if (result.resultCode === '600000') {
console.log("加速授权页拉起成功");
// 延迟执行,确保配置构建完成
setTimeout(() => {
try {
// 额外的try/catch防止配置构建或登录控制器调用出错
const config = uiConfig.buildSheet();
this._presentLoginController(config);
} catch (innerError) {
this.maskShow = true
console.error("构建登录配置或调用登录控制器失败:", innerError);
// 这里可以添加配置构建失败后的备用操作
}
}, 100);
} else {
if(!this.isFirst){
if(result.resultCode == 600004 || result.resultCode ==600008){
uni.showToast({
title: "蜂窝网络未开启",
icon: 'none'
});
}else if(result.resultCode == 600007 || result.resultCode ==600009){
uni.showToast({
title: "未检测到sim卡",
icon: 'none'
});
}else{
uni.showToast({
title: "唤起授权页失败",
icon: 'none'
});
}
}
this.maskShow = true
this.isFirst = false
console.error("授权页加速拉起失败:", result);
}
});
} catch (error) {
// 捕获aLiSDKModule未定义或其他执行错误
this.maskShow = true
console.error("跳转到登录页时发生错误:", error);
}
// aLiSDKModule.accelerateLoginPage(5000, result => {
// console.log(JSON.stringify(result));
// if ('600000' == result.resultCode) {
// console.log("加速授权页拉起成功");
// setTimeout(() => {
// const config = uiConfig.buildSheet();
// this._presentLoginController(config);
// }, 200);
// } else {
// console.log("授权页加速拉起失败," + result.msg);
// }
// });
},
/**
* 密码登录辅助方法:获取账号密码错误次数
* @param {String} account - 登录账号(手机号)
* @returns {Number} 错误次数默认0
*/
getPwdErrorCount(account) {
const storageKey = `pwd_error_count_${account}`;
return Number(uni.getStorageSync(storageKey)) || 0;
},
/**
* 密码登录辅助方法:更新账号密码错误次数
* @param {String} account - 登录账号(手机号)
* @param {Number} count - 最新错误次数
*/
updatePwdErrorCount(account, count) {
const storageKey = `pwd_error_count_${account}`;
uni.setStorageSync(storageKey, count);
},
/**
* 密码登录辅助方法:获取账号锁定时间戳
* @param {String} account - 登录账号(手机号)
* @returns {Number} 锁定时间戳毫秒默认0
*/
getPwdLockTime(account) {
const storageKey = `pwd_lock_time_${account}`;
return Number(uni.getStorageSync(storageKey)) || 0;
},
/**
* 密码登录辅助方法:设置账号锁定(记录锁定时间戳)
* @param {String} account - 登录账号(手机号)
*/
setPwdLock(account) {
const storageKey = `pwd_lock_time_${account}`;
uni.setStorageSync(storageKey, Date.now()); // 存储当前时间戳
},
/**
* 密码登录辅助方法:清除账号锁定缓存(错误次数+锁定时间)
* @param {String} account - 登录账号(手机号)
*/
clearPwdLockCache(account) {
uni.removeStorageSync(`pwd_error_count_${account}`);
uni.removeStorageSync(`pwd_lock_time_${account}`);
},
/**
* 密码登录辅助方法:检查账号是否被锁定
* @param {String} account - 登录账号(手机号)
* @returns {Object} { isLocked: Boolean, remainingTime: Number }
* remainingTime: 剩余锁定时间0表示未锁定
*/
checkAccountLocked(account) {
const lockTime = this.getPwdLockTime(account);
if (!lockTime) return {
isLocked: false,
remainingTime: 0
};
const now = Date.now();
const lockDuration = 3600 * 1000; // 1小时毫秒
const remainingTime = Math.ceil((lockTime + lockDuration - now) / 1000); // 剩余锁定时间(秒)
if (remainingTime > 0) {
return {
isLocked: true,
remainingTime
};
} else {
// 锁定时间已过,自动清除缓存
this.clearPwdLockCache(account);
return {
isLocked: false,
remainingTime: 0
};
}
},
// 执行登录
handleLogin() {
let that = this;
// 手机号错误时直接返回
if (this.phoneError) {
uni.showToast({
title: this.phoneError,
icon: 'none'
})
return
}
if (this.loginType === 'code') {
// 验证码登录:调用后端接口(示例)
if (!this.phone) {
uni.showToast({
title: "请输入手机号",
icon: 'none'
})
return
} else if (!that.code) {
uni.showToast({
title: '请输入验证码',
icon: 'none'
});
return false;
} else if (this.code.length < 4) { // 修复逻辑:原代码是>=4时提示错误改为<4
uni.showToast({
title: '请输入正确验证码',
icon: 'none'
});
return false;
} else if (!that.isAgree) {
uni.showToast({
title: '请先阅读并同意《用户注册协议》与《隐私政策》',
icon: 'none'
});
return false;
} else {
request.post('/sj/codelogin', {
account: that.phone,
code: that.code,
deviceid: getApp().globalData.deviceid
}).then(result => {
if (result.code == 200) {
uni.setStorageSync('accessToken', result.data.access_token);
uni.setStorageSync('refreshToken', result.data.refresh_token);
uni.setStorageSync('refresh_token_expries', result.data.refresh_token_expries);
uni.setStorageSync('loginAccount', that.phone); // 保存登录的手机号
registPush();
this.messageUpudateNum()
this.closeWindow();
} else {
uni.showToast({
title: result.msg,
icon: 'none'
})
}
}).catch(err => {
uni.showToast({
title: err.msg,
icon: 'none'
})
})
}
} else if (this.loginType === 'account') {
// 账号密码登录:先检查账号是否锁定
const {
isLocked,
remainingTime
} = this.checkAccountLocked(this.phone);
if (isLocked) {
// 计算小时、分钟、秒,优化提示文案
const hours = Math.floor(remainingTime / 3600);
const minutes = Math.floor((remainingTime % 3600) / 60);
const seconds = remainingTime % 60;
let lockTip = '';
if (hours > 0) {
lockTip = `该账号因多次密码错误已锁定,请${hours}小时${minutes}分钟后重试`;
} else if (minutes > 0) {
lockTip = `该账号因多次密码错误已锁定,请${minutes}分钟${seconds}秒后重试`;
} else {
lockTip = `该账号因多次密码错误已锁定,请${seconds}秒后重试或找回密码`;
}
uni.showToast({
title: lockTip,
icon: 'none',
duration: 3000
});
return false;
}
// 密码格式校验
let reg = that.validatePassword(that.password);
if (!this.phone) {
uni.showToast({
title: "请输入手机号",
icon: 'none'
})
return
} else if (!that.password) {
uni.showToast({
title: '请输入密码',
icon: 'none'
});
return false;
} else if (!reg) {
uni.showToast({
title: '请输入正确的密码6-20位字母 + 数字/符号组合)',
icon: 'none'
});
return false;
} else if (!that.isAgree) {
uni.showToast({
title: '请先阅读并同意《用户注册协议》与《隐私政策》',
icon: 'none'
});
return false;
} else {
request.post('/sj/accountlogin', {
account: that.phone,
password: that.password,
deviceid: getApp().globalData.deviceid
}).then(result => {
console.log(result)
if (result.code == 200) {
// 登录成功:清除该账号的密码错误次数和锁定缓存
that.clearPwdLockCache(that.phone);
uni.setStorageSync('accessToken', result.data.access_token);
uni.setStorageSync('refreshToken', result.data.refresh_token);
uni.setStorageSync('refresh_token_expries', result.data.refresh_token_expries);
uni.setStorageSync('loginAccount', that.phone); // 保存登录的手机号
registPush();
that.messageUpudateNum()
that.closeWindow();
} else {
// 登录失败判断是否为密码错误假设后端返回msg包含“密码错误”关键词可根据实际接口调整
if (result.code === 502) {
const currentErrorCount = that.getPwdErrorCount(that.phone);
const maxErrorCount = 5;
const remainingCount = maxErrorCount - currentErrorCount - 1;
if (remainingCount > 0) {
// 未达最大错误次数:更新错误次数,提示剩余次数
that.updatePwdErrorCount(that.phone, currentErrorCount + 1);
uni.showToast({
title: `密码错误,还有${remainingCount}次机会`,
icon: 'none',
duration: 2000
});
} else {
// 达最大错误次数:锁定账号,提示锁定信息
that.updatePwdErrorCount(that.phone, maxErrorCount);
that.setPwdLock(that.phone);
uni.showToast({
title: '该账号因多次密码错误已锁定请1小时后重试或找回密码',
icon: 'none',
duration: 3000
});
}
} else {
// 其他错误(如账号不存在等),直接提示
uni.showToast({
title: result.msg,
icon: 'none'
});
}
}
}).catch(err => {
uni.showToast({
title: err.msg,
icon: 'none'
})
})
}
}
},
// 密码格式校验
validatePassword(password) {
// 正则说明:
// (?=.*[A-Za-z]):必须包含至少一个字母
// (?=.*\d):必须包含至少一个数字
// [\w\W]{6,20}匹配任意字符字母、数字、符号、中文等长度6-20位
// 若想限制仅允许常见符号(排除中文),可改用:/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d!@#$%^&*()_+\-=\[\]{}|;':",./<>?]{6,20}$/
const reg = /^(?=.*[A-Za-z])(?=.*\d)[\w\W]{6,20}$/;
return reg.test(password);
},
quitLoginPage() {
aLiSDKModule.quitLoginPage();
this.maskShow = true
},
// 阿里云一键登录原生弹窗逻辑
_presentLoginController(config) {
let that = this
uni.showLoading({
mask: true,
});
// 调用该接口首先会弹起授权页点击授权页的登录按钮获取Token
aLiSDKModule.getLoginToken(
5000,
config,
tokenResult => {
uni.hideLoading();
console.log("tokenResult:", JSON.stringify(tokenResult));
if ("600001" == tokenResult.resultCode) {
console.log("授权页拉起成功");
this.maskShow = false
aLiSDKModule.setCheckboxIsChecked(false);
} else if ("600000" == tokenResult.resultCode) {
console.log("获取Token成功接下来拿着结果里面的Token去服务端换取手机号码SDK服务到此结束");
request.post('/sj/phoneLogin', {
token: tokenResult.token,
}).then(result => {
if (result.code == 200) {
// 登录成功:
uni.setStorageSync('accessToken', result.data.access_token);
uni.setStorageSync('refreshToken', result.data.refresh_token);
uni.setStorageSync('refresh_token_expries', result.data
.refresh_token_expries);
uni.setStorageSync('loginAccount', result.data.account); // 保存登录的手机号
registPush();
that.messageUpudateNum()
that.closeWindow();
} else {
uni.showToast({
title: result.msg,
icon: 'none'
});
}
}).catch(err => {
uni.showToast({
title: err.msg,
icon: 'none'
})
}).finally(() => {
//手动关闭授权页
this.quitLoginPage();
})
} else {
if (tokenResult.msg) {
//手动关闭授权页
if(!this.isFirst){
uni.showToast({
title: tokenResult.msg,
icon: 'none'
})
}
}
this.maskShow = true
this.quitLoginPage();
}
this.isFirst = false
},
clickResult => {
console.log(JSON.stringify(clickResult));
switch (clickResult.resultCode) {
case "700000":
this.closeWindow()
this.quitLoginPage();
console.log("用户点击了返回");
break
case "700001":
this.quitLoginPage();
console.log("用户切换其他登录方式");
break
case "700002":
console.log("用户点击登录按钮");
if (!clickResult.result.isChecked) {
if (!config.uiConfig.setPrivacyAlertIsNeedShow) {
plus.nativeUI.toast("请同意服务条款");
}
}
break;
case "700003":
console.log("用户点击checkBox");
break
case "700004":
console.log("用户点击协议");
break
case "700010":
this.closeWindow()
console.log("用户点击返回按钮Android专用");
this.quitLoginPage();
break
case "700011":
this.closeWindow()
console.log("用户使用物理返回键Android专用");
this.quitLoginPage();
break
case "700006":
console.log("弹出二次授权弹窗");
break
case "700007":
console.log("关闭二次授权弹窗");
break
case "700008":
console.log("点击二次授权弹窗确认按钮");
break
case "700009":
console.log("点击二次授权弹窗协议");
break
}
},
customUiResult => {
console.log("点击了自定义控件 " + JSON.stringify(customUiResult));
if ("close" == customUiResult.widgetId) {
aLiSDKModule.quitLoginPage();
} else if ("closePrivacyAlert" == customUiResult.widgetId) {
aLiSDKModule.closePrivactAlertView();
} else {
plus.nativeUI.toast("点击了自定义按钮widgetId" + customUiResult.widgetId);
}
});
},
/**
* 手机号输入实时校验
* 1. 过滤非数字字符兼容部分设备type="number"仍可输入非数字的情况)
* 2. 实时校验11位数字非11位显示错误提示
*/
handlePhoneInput() {
// 过滤非数字字符(账号密码登录时账号可能为手机号,统一过滤)
this.phone = this.phone.replace(/\D/g, '');
if (this.loginType === 'code' && this.phone.length > 0 && !uni.$uv.test.mobile(this.phone)) {
this.phoneError = '请输入正确的手机号';
} else if (this.loginType === 'account' && this.phone.length > 0 && this.phone.length < 6) {
this.phoneError = '请输入正确的账号';
} else {
this.phoneError = '';
}
}
}
}
</script>
<style lang="scss">
/* 蒙层全屏半透明底部对齐弹窗 */
page {
width: 100%;
height: 100%;
background: transparent;
}
.login-mask {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
// width: 100%;
// height: 100%;
// position: relative;
// width: 100vw;
// height: 100vh;
background: transparent;
// display: flex;
// flex-direction: column;
// justify-content: flex-end;
z-index: 999;
overflow: hidden;
}
/* 底部弹窗宽度100%顶部圆角 */
.login-popup {
position: absolute;
left: 0;
right: 0;
bottom: 0;
// width: 100%;
background: #fff;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
padding: 42rpx 66rpx 100rpx 66rpx;
box-sizing: border-box;
// position: relative;
}
/* 弹窗头部标题+关闭按钮 */
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 55rpx;
.popup-title {
width: 100%;
font-weight: 500;
font-size: 30rpx;
color: #333333;
line-height: 42rpx;
text-align: center;
font-style: normal;
}
}
.popup-close {
width: 40rpx;
height: 40rpx;
position: absolute;
top: 37rpx;
right: 40rpx;
}
/* 登录选项卡 */
.login-tabs {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 55rpx;
padding: 0 96rpx;
.tab-line {
width: 2rpx;
height: 20rpx;
background: #D8D8D8;
border-radius: 1rpx;
}
.tab-item {
font-weight: 400;
font-size: 26rpx;
color: #333333;
line-height: 37rpx;
text-align: center;
font-style: normal;
position: relative;
padding-bottom: 6rpx;
&.active {
color: #f00;
&::after {
content: '';
position: absolute;
bottom: 0rpx;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
border-radius: 2rpx;
height: 4rpx;
background: #f00;
}
}
}
}
/* 输入区域 */
.input-area {
margin-bottom: 80rpx;
.input-item {
display: flex;
align-items: center;
box-sizing: border-box;
width: 618rpx;
height: 98rpx;
background: #F5F5F5;
border-radius: 49rpx;
padding: 28rpx 24rpx 28rpx 30rpx;
margin-bottom: 30rpx;
position: relative;
.look-icon {
width: 37rpx;
position: absolute;
top: 50%;
right: 30rpx;
transform: translateY(-50%);
}
.input-icon-phone {
width: 30rpx;
height: 32rpx;
margin-right: 19rpx;
}
.input-icon-password {
width: 32rpx;
height: 38rpx;
margin-right: 19rpx;
}
.input-text {
flex: 1;
font-size: 30rpx;
height: 40rpx;
color: #333;
}
.get-code-btn {
font-weight: 400;
font-size: 30rpx;
color: #E8101E;
line-height: 42rpx;
text-align: center;
font-style: normal;
}
.running {
color: #999999;
}
.noPhone {
color: #999999;
}
.eye-icon {
font-size: 30rpx;
color: #666;
margin-left: 15rpx;
}
}
// 错误提示样式
.input-error {
display: block;
font-size: 24rpx;
color: #e8101e;
margin-left: 30rpx;
margin-top: -20rpx;
margin-bottom: 20rpx;
line-height: 1.2;
}
}
/* 登录按钮匹配示例的粉/红切换 */
.login-btn {
width: 590rpx;
height: 98rpx;
background: rgba(232, 16, 30, 0.4);
border-radius: 50rpx;
font-weight: 500;
font-size: 30rpx;
color: #FFFFFF;
text-align: center;
font-style: normal;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 30rpx;
&.active {
background: rgba(232, 16, 30, 1);
}
}
.agree {
display: flex;
flex-flow: row nowrap;
flex-direction: row;
align-items: flex-start;
.agree-btn {
transform: translateY(4rpx);
margin-right: 8rpx;
}
.agree-card {
.agreement {
font-weight: 400;
font-size: 26rpx;
color: rgba(232, 16, 30, 1);
line-height: 37rpx;
margin: 0 10rpx;
}
.agree-text {
font-weight: 400;
font-size: 26rpx;
color: #898989;
line-height: 37rpx;
}
}
}
.uni-input-placeholder{
font-weight: 400;
font-size: 30rpx;
color: #BCC0C0;
line-height: 42rpx;
text-align: left;
font-style: normal;
}
</style>