最终效果

在这里插入图片描述

在这里插入图片描述

技术要点

用户协议 – 打开本地浏览器

点击后,直接打开本地浏览器浏览网页

 // 最终需修改为 《用户协议》 的网址Linking.openURL("https://www.baidu.com");

手机号输入框的 344 展示

在这里插入图片描述

onChangeText={(text: string) => {setPhone(formatPhone(text));
}}
export function formatPhone(phone: string): string {let trim: string = phone.replace(/\s+/g, "");const result = [trim.slice(0, 3), trim.slice(3, 7), trim.slice(7, 11)].filter((item) => !!item).join(" ");return result;
}

但在访问接口登录时,传参需清除空格

UserStore.requestLogin(replaceBlank(phone), pwd, (success: boolean) => {
export function replaceBlank(phone: string): string {return phone ? phone.replace(/\s+/g, "") : "";
}

代码实现

app/_layout.tsx

        <Stack>{/* 登录页 */}<Stack.Screen name="login" options={{ headerShown: false }} /><Stack.Screen name="(tabs)" options={{ headerShown: false }} /><Stack.Screen name="+not-found" /></Stack>

app/login.tsx

import UserStore from "@/stores/UserStore";
import { formatPhone, replaceBlank } from "@/utils/StringUtil";
import { Toast } from "@ant-design/react-native";
import AntDesign from "@expo/vector-icons/AntDesign";
import Entypo from "@expo/vector-icons/Entypo";
import FontAwesome from "@expo/vector-icons/FontAwesome";
import { useRouter } from "expo-router";
import { useState } from "react";
import {Image,KeyboardAvoidingView,Linking,Platform,StyleSheet,Text,TextInput,TouchableOpacity,View,
} from "react-native";
import Animated from "react-native-reanimated";
export default function LoginScreen() {const router = useRouter();const [ifRead, setIfRead] = useState(false);const [ifQuickLogin, setIfQuickLogin] = useState(false);const [phone, setPhone] = useState<string>("");const [pwd, setPwd] = useState<string>("");const [showPassword, setShowPassword] = useState(false);const canLogin = phone?.length === 13 && pwd?.length >= 6;const onLoginPress = async () => {if (!canLogin) {return;}if (!ifRead) {Toast.show({content: "请先同意并阅读用户协议",});return;}UserStore.requestLogin(replaceBlank(phone), pwd, (success: boolean) => {if (success) {Toast.success("登录成功");router.replace("/(tabs)");} else {Toast.fail("登录失败,账号/密码错误!");}});};const render_passwordLogin = () => {const passwordLogin_styles = StyleSheet.create({inputBox: {borderColor: "#ccc",borderBottomColor: "#ccc",borderBottomWidth: 1,flexDirection: "row",alignItems: "center",marginBottom: 14,height: 55,},phonePrefix: {fontSize: 20,color: "#bbb",marginRight: 8,},phoneInput: {fontSize: 24,paddingLeft: 14,textAlignVertical: "bottom",height: 75,flex: 1,},passwordInput: {fontSize: 20,textAlignVertical: "bottom",flex: 1,height: 75,},loginButton: {backgroundColor: "#ff2442",},loginButtonDisable: {backgroundColor: "#DDDDDD",},moreBox: {flexDirection: "row",justifyContent: "space-between",marginBottom: 26,},tip: {fontSize: 14,color: "#bbb",marginBottom: 20,textAlign: "center",},toCodeLoginBtn: {flexDirection: "row",alignItems: "center",},toCodeLoginBtnTxt: {marginLeft: 6,},moreBoxTxt: {color: "#303080",},});return (<View><Text style={passwordLogin_styles.tip}>未注册的手机号登录成功后将自动注册</Text><KeyboardAvoidingViewbehavior={Platform.OS === "ios" ? "padding" : "height"}keyboardVerticalOffset={Platform.OS === "ios" ? 64 : 30}><View style={passwordLogin_styles.inputBox}><Text style={passwordLogin_styles.phonePrefix}>+86</Text><AntDesign name="caretdown" size={14} color="#bbb" /><TextInputstyle={passwordLogin_styles.phoneInput}placeholder="请输入手机号"placeholderTextColor="#bbb"autoFocus={false}keyboardType="number-pad"maxLength={13}value={phone}onChangeText={(text: string) => {setPhone(formatPhone(text));}}/></View><View style={passwordLogin_styles.inputBox}><TextInputstyle={passwordLogin_styles.passwordInput}placeholder="请输入密码"placeholderTextColor="#bbb"autoFocus={false}maxLength={20}secureTextEntry={!showPassword}value={pwd}onChangeText={(text: string) => {setPwd(text);}}/><TouchableOpacityactiveOpacity={0.7}onPress={() => {setShowPassword(!showPassword);}}><Entyponame={showPassword ? "eye" : "eye-with-line"}size={28}color="#bbb"/></TouchableOpacity></View></KeyboardAvoidingView><View style={passwordLogin_styles.moreBox}><TouchableOpacitystyle={passwordLogin_styles.toCodeLoginBtn}onPress={() => {Toast.show({content: "待需要时完善",});}}><FontAwesome name="exchange" size={12} color="#303080" /><Textstyle={[passwordLogin_styles.toCodeLoginBtnTxt,passwordLogin_styles.moreBoxTxt,]}>验证码登录</Text></TouchableOpacity><TouchableOpacityonPress={() => {Toast.show({content: "待需要时完善",});}}><Text style={passwordLogin_styles.moreBoxTxt}>忘记密码?</Text></TouchableOpacity></View><TouchableOpacitystyle={[styles.btn,canLogin? passwordLogin_styles.loginButton: passwordLogin_styles.loginButtonDisable,]}activeOpacity={canLogin ? 0.7 : 1}onPress={onLoginPress}><Text style={[styles.btnTxt]}>登录</Text></TouchableOpacity></View>);};return (<View style={styles.page}><Imagesource={require("@/assets/images/icon.png")}style={{ width: 200, height: 200, marginTop: 100 }}resizeMode="cover"/><Animated.View style={styles.LoginBox}>{ifQuickLogin ? (<><TouchableOpacitystyle={[styles.btn, styles.oneKeyLoginButton]}activeOpacity={0.7}onPress={() => {Toast.show({content: "待需要时完善",});}}><Text style={[styles.btnTxt, styles.oneKeyLoginTxt]}>一键登录</Text></TouchableOpacity><TouchableOpacitystyle={[styles.btn, styles.wxLoginButton]}activeOpacity={0.7}onPress={() => {Toast.show({content: "待需要时完善",});}}><AntDesign name="wechat" size={24} color="white" /><Text style={[styles.btnTxt]}>微信登录</Text></TouchableOpacity></>) : (render_passwordLogin())}<TouchableOpacityactiveOpacity={0.7}style={styles.moreLoginWayBox}onPress={() => {setIfQuickLogin(!ifQuickLogin);}}><Text style={[styles.moreLoginWayTxt]}>{ifQuickLogin ? "其他登录方式" : "快捷登录"}</Text><Entypo name="chevron-small-right" size={20} /></TouchableOpacity><View style={styles.moreBox}><TouchableOpacityonPress={() => {setIfRead(!ifRead);}}>{ifRead ? (<AntDesignstyle={styles.moreIcon}name="checkcircle"size={14}color="#05c160"/>) : (<Entypostyle={styles.moreIcon}name="circle"size={14}color="gray"/>)}</TouchableOpacity><Text style={styles.infoTxt}>我已阅读并同意</Text><TouchableOpacityonPress={() => {// 最终需修改为 《用户协议》 的网址Linking.openURL("https://www.baidu.com");}}><Text style={styles.linkTxt}>《用户协议》</Text></TouchableOpacity><Text style={styles.infoTxt}></Text><TouchableOpacityonPress={() => {// 最终需修改为 《隐私政策》 的网址Linking.openURL("https://www.baidu.com");}}><Text style={styles.linkTxt}>《隐私政策》</Text></TouchableOpacity></View></Animated.View></View>);
}
const styles = StyleSheet.create({page: {flex: 1,alignItems: "center",justifyContent: "space-between",backgroundColor: "#e8e8e7",padding: 40,},LoginBox: {width: "100%",padding: 20,marginBottom: 100,},btn: {width: "100%",height: 56,borderRadius: 28,justifyContent: "center",alignItems: "center",flexDirection: "row",marginBottom: 20,},btnTxt: {fontSize: 18,color: "white",marginBottom: 6,marginLeft: 14,},oneKeyLoginButton: {backgroundColor: "#ff2442",},oneKeyLoginTxt: {marginLeft: 4,},wxLoginButton: {backgroundColor: "#05c160",},moreBox: {flexDirection: "row",alignItems: "center",justifyContent: "center",},moreIcon: {marginRight: 4,marginTop: 2,},moreLoginWayBox: {flexDirection: "row",alignItems: "center",justifyContent: "center",marginBottom: 60,},moreLoginWayTxt: {fontSize: 16,marginBottom: 4,},infoTxt: {fontSize: 14,color: "gray",},linkTxt: {fontSize: 14,color: "blue",},
});

utils/StringUtil.ts

export function formatPhone(phone: string): string {let trim: string = phone.replace(/\s+/g, "");const result = [trim.slice(0, 3), trim.slice(3, 7), trim.slice(7, 11)].filter((item) => !!item).join(" ");return result;
}
export function replaceBlank(phone: string): string {return phone ? phone.replace(/\s+/g, "") : "";
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/87080.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/87080.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/87080.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【赵渝强老师】OceanBase数据库从零开始:Oracle模式

这里我们来介绍一下新上线的课程《OceanBase数据库从零开始&#xff1a;Oracle模式》&#xff0c;本门课程共11章。 视频讲解如下 【赵渝强老师】OceanBase从零开始&#xff08;Oracle模式&#xff09; 下面详细介绍一下每一章的主要内容&#xff1a; 第01章-OceanBase的体系…

Flink核心功能与运行流程详解

目录 一、背景 二、图构建 三、任务执行流程&#xff08;yarn per-job模式&#xff09; 3.1 Flink组件 3.2 执行流程 四、分布式调度 4.1 TM的slot 4.2 TM的slot的CPU与内存 4.3 节点的部署 4.4 节点的状态 4.5 节点部署流程 五、数据传输 5.1 内存分配 5.2 传输…

linux 操作docker的基本命令docker仓库

基本操作命令 docker run --nametest-host -itd centos7.6 /bin/bash 通过镜像创建容器 登录容器 [rootdocker101 ~]# docker exec -it test-host /bin/bash &#xff08;exec是执行&#xff0c;i是交互式。t叫tty&#xff09; 或者container id [rootdocker101 ~]# doc…

Netty学习路线图 - 第四阶段:Netty基础应用

Netty学习路线图 - 第四阶段&#xff1a;Netty基础应用 &#x1f4da; Netty学习系列之四 本文是Netty学习路线的第四篇&#xff0c;我们将用大白话讲解Netty的基础应用&#xff0c;带你从理论走向实践。 写在前面 大家好&#xff01;在前面三篇文章中&#xff0c;我们学习了J…

开源项目推荐:MCP Registry——管理MCP服务器的利器

探索MCP Registry:未来模型上下文协议的核心注册服务 随着人工智能技术的迅速发展,机器学习模型的管理和配置变得愈发重要。今天,我们将探索一个颇具潜力的开源项目——MCP Registry。这是一个由社区驱动的注册服务,专为模型上下文协议(Model Context Protocol,简称MCP)…

Spring Boot 统一功能处理:拦截器详解

一、拦截器核心概念 作用&#xff1a;拦截器是 Spring 框架提供的核心功能&#xff0c;用于在请求处理前后执行预定义逻辑&#xff0c;实现统一处理&#xff08;如登录校验、日志记录等&#xff09;。 核心方法&#xff1a; public class LoginInterceptor implements Handl…

在docker容器中安装docker服务,基于fuse-overlayfs进行overlay挂载,而不是vfs

1、docker 安装 正常安装docker软件&#xff0c;运行docker时&#xff0c;会提示&#xff1a;No docker socket 服务 2、启动docker服务&#xff08;包含守护进程&#xff09; systemctl start docker #dockerd &if ! ps aux | grep -v grep | grep -q "dockerd&qu…

虚拟机配置注意事项

一.VM大部分产品免费&#xff0c;遇到付费的要斟酌一下 在小编之前的文章中有简单下载VM的教程VMwareWorkstPro安装-CSDN博客 二.配置过程中的设置大部分都可以在配置完成后更改 例如下图设备所涉及到的&#xff0c;都是可以更改设置的 三.电脑关机时&#xff0c;要注意先把…

openGL+QT快速学习和入门案列

openGLQT快速学习和入门案列

深度学习03 人工神经网络ANN

什么是神经网络 人工神经网络&#xff08; Artificial Neural Network&#xff0c; 简写为ANN&#xff09;也简称为神经网络&#xff08;NN&#xff09;,是一种模仿生物神经网络结构和功能的计算模型,人脑可以看做是一个生物神经网络,由众多的神经元连接而成.各个神经元传递复…

Linux中部署Jenkins保姆间教程

本文将以docker的方式&#xff0c;讲述如何部署Jenkins 一、拉取Jenkins镜像 1.1 最新版Jenkins介绍 最新版Jenkins地址&#xff1a;Download and deploy 当前最新版的如下图所示&#xff1a; 1.2 各版本支持的JDK版本 地址如下&#xff1a;Java Support Policy 如果你安装…

【软考中级·软件评测师】下午题·面向对象测试之架构考点全析:分层、分布式、微内核与事件驱动

一、分层架构&#xff1a;分层独立与质量特性的双向约束 分层架构通过“垂直分层&#xff08;表示层→服务层→业务逻辑层→数据层&#xff09;”实现职责隔离&#xff0c;是Web应用、企业级系统的主流架构模式。 1. 父类成员函数重测场景 子类继承父类时&#xff0c;若父类…

C++ 快速回顾(五)

C 快速回顾&#xff08;五&#xff09; 前言一、Dll和Lib的区别区别在开发中使用 二、封装并使用C库1.封装库2.使用库 三、封装并使用C库1.封装库2.使用库 前言 用于快速回顾之前遗漏或者补充C知识 一、Dll和Lib的区别 静态库&#xff08;LIB&#xff09;在编译时链接&#…

【ARM】解决ArmDS的工程没有生成Map文件的问题

1、 文档目标 在嵌入式开发过程中&#xff0c;使用Arm Development Studio&#xff08;简称ArmDS&#xff09;进行项目构建时&#xff0c;Map文件的生成是调试和分析代码的重要环节。Map文件不仅记录了程序中各个段&#xff08;sections&#xff09;的内存分布情况&#xff0c…

Java如何导出word(根据模板生成),通过word转成pdf,放压缩包

<!-- 导出word文档所需依赖--><dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.10.0-beta</version></dependency><dependency><groupId>org.apache.poi</gr…

【C#】 DevExpress.XtraEditors.SidePanel

DevExpress.XtraEditors.SidePanel&#xff0c; 它是 DevExpress 提供的“侧边滑出”面板&#xff08;类似于抽屉、浮动信息区&#xff09;&#xff0c;非常适合做可隐藏的参数区、帮助区、临时交互区等。 SidePanel 用法核心点 1. 基本用法 可容纳其它控件&#xff0c;就像普…

1.1_2 计算机网络的组成和功能

在这个视频中&#xff0c;我们会探讨计算机网络的组成和功能。我们会从三个视角去探讨计算机网络由哪些部分组成&#xff0c;其次&#xff0c;我们会简单的了解计算机网络的功能。 首先我们可以把计算机网络看作是由硬件、软件和协议共同组成的一个庞大复杂的系统。首先在硬件上…

Linux驱动学习day11(定时器)

定时器 定时器主要作用就是&#xff1a;设置超时时间&#xff0c;执行超时函数。 按键按下存在抖动&#xff0c;为了消除抖动可以设置定时器&#xff0c;如上图所示&#xff0c;按下一次按键会产生多次抖动&#xff0c;即会产生多次中断&#xff0c;在每次中断产生的时候&…

Java 编程之观察者模式详解

一、什么是观察者模式&#xff1f; 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;用于对象之间的一对多依赖关系&#xff1a;当被观察对象&#xff08;Subject&#xff09;状态发生变化时&#xff0c;所有依赖它的观察者&#xff08;O…

【C++】经典string类问题

目录 1. 浅拷贝 2. 深拷贝 3. string类传统写法 4. string类现代版写法 5. 自定义类实现swap成员函数 6. 标准库swap函数的调用 7. 引用计数和写时拷贝 1. 浅拷贝 若string类没有显示定义拷贝构造函数与赋值运算符重载&#xff0c;编译器会自动生成默认的&#xff0c…