写一个uniapp的登录注册页面

news/2024/10/19 5:30:59/

目录

一、效果图

二、代码

1、登录

(1)页面布局代码

(2)逻辑实现代码

(3)css样式

2、注册

(1)页面布局代码

(2)逻辑实现代码

(3)css样式

3、接口(所有用到的js)

(1)login.js

(2)request.js

(3)auth.js

(4)common.js

(5)crpto.js

(6)jsencrypt.js

(7)errorCode.js

(8)config.js


一、效果图

二、代码

1、登录
(1)页面布局代码
<template><view class="normal-login-container"><view class="logo-content align-center justify-center flex"><image class="img-a" src="/static/images/b-1.png"></image><image class="img-b" src="/static/images/b-2.png"></image><!-- 标题 --><view class="text"><view class="t-b">{{ title }}</view><view class="t-b2">{{ subTitle }}</view></view></view><view class="login-form-content"><view class="input-item flex align-center"><view class="iconfont icon-user icon"></view><input v-model="loginForm.username" class="input" type="text" placeholder="请输入账号" maxlength="30" /></view><view class="input-item flex align-center"><view class="iconfont icon-password icon"></view><input v-model="loginForm.password" type="password" class="input" placeholder="请输入密码" maxlength="20" /></view><view class="input-item flex align-center" style="width: 60%;margin: 0px;" v-if="captchaEnabled"><view class="iconfont icon-code icon"></view><input v-model="loginForm.code" type="number" class="input" placeholder="请输入验证码" maxlength="4" /><view class="login-code"> <image :src="codeUrl" @click="getCode" class="login-code-img"></image></view></view><view class="action-btn"><button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">登录</button></view><view class="reg text-center" v-if="register"><text class="text-grey1">没有账号?</text><text @click="handleUserRegister" class="text-blue">立即注册</text></view><view class="xieyi text-center"><!-- <text class="text-grey1">登录即代表同意</text><text @click="handleUserAgrement" class="text-blue">《用户协议》</text><text @click="handlePrivacy" class="text-blue">《隐私协议》</text> --></view></view></view>
</template>
(2)逻辑实现代码
<script>import { getCodeImg } from '@/api/login'export default {data() {return {title: '管理平台',subTitle: '欢迎回来,开始工作吧!',codeUrl: "",captchaEnabled: true,// 用户注册开关register: true,globalConfig: getApp().globalData.config,loginForm: {username: "admin",password: "admin123",code: "",uuid: ''}}},created() {this.getCode()},methods: {// 用户注册handleUserRegister() {this.$tab.redirectTo(`/pages/register`)},// 隐私协议// handlePrivacy() {//   let site = this.globalConfig.appInfo.agreements[0]//   this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)// },// // 用户协议// handleUserAgrement() {//   let site = this.globalConfig.appInfo.agreements[1]//   this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)// },// 获取图形验证码getCode() {getCodeImg().then(res => {res=res.datathis.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabledif (this.captchaEnabled) {this.codeUrl = 'data:image/gif;base64,' + res.imgthis.loginForm.uuid = res.uuid}})},// 登录方法async handleLogin() {if (this.loginForm.username === "") {this.$modal.msgError("请输入您的账号")} else if (this.loginForm.password === "") {this.$modal.msgError("请输入您的密码")} else if (this.loginForm.code === "" && this.captchaEnabled) {this.$modal.msgError("请输入验证码")} else {this.$modal.loading("登录中,请耐心等待...")this.pwdLogin()}},// 密码登录async pwdLogin() {this.$store.dispatch('Login', this.loginForm).then(() => {// console.log(document.response);this.$modal.closeLoading()this.loginSuccess()}).catch(() => {if (this.captchaEnabled) {this.getCode()}})},// 登录成功后,处理函数loginSuccess(result) {// 设置用户信息this.$store.dispatch('GetInfo').then(res => {this.$tab.reLaunch('/pages/index')})}}}
</script>

(3)css样式
<style lang="scss">page {background-color: #ffffff;}.normal-login-container {width: 100%;.logo-content {width: 100%;font-size: 21px;text-align: center;padding-top: 15%;image {border-radius: 4px;}.title {margin-left: 10px;}}.login-form-content {text-align: center;margin: 20px auto;// margin-top: 3%;width: 80%;.input-item {margin: 20px auto;background-color: #f5f6f7;height: 45px;border-radius: 20px;.icon {font-size: 38rpx;margin-left: 10px;color: #999;}.input {width: 100%;font-size: 14px;line-height: 20px;text-align: left;padding-left: 15px;}}.login-btn {margin-top: 40px;height: 45px;}.reg {margin-top: 15px;}.xieyi {color: #333;margin-top: 20px;}.login-code {height: 38px;float: right;.login-code-img {height: 38px;position: absolute;margin-left: 10px;width: 200rpx;}}}}
.img-a {position: absolute;width: 100%;top: -74px;right: 0;z-index: 100;
}
.img-b {position: absolute;width: 50%;bottom: 0;left: -50rpx;z-index: 100;
}
.text{margin-left: -111px;margin-top: 28px;
}
.t-b {text-align: left;font-size: 29px;color: #000;padding: 60px 0 10px 0;font-weight: bold;
}
.t-b2 {text-align: left;font-size: 32rpx;color: #aaaaaa;padding: 0rpx 0 60rpx 0;
}</style>
2、注册
(1)页面布局代码
<template><view class="normal-login-container"><view class="logo-content align-center justify-center flex"><!-- <image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix"></image> --><image class="img-a" src="/static/images/b-1.png"></image><image class="img-b" src="/static/images/b-2.png"></image><text class="title">绣创科技移动端注册</text></view><view class="login-form-content"><view class="input-item flex align-center"><view class="iconfont icon-user icon"></view><input v-model="registerForm.username" class="input" type="text" placeholder="请输入账号" maxlength="30" /></view><view class="input-item flex align-center"><view class="iconfont icon-password icon"></view><input v-model="registerForm.password" type="password" class="input" placeholder="请输入密码" maxlength="20" /></view><view class="input-item flex align-center"><view class="iconfont icon-password icon"></view><input v-model="registerForm.confirmPassword" type="password" class="input" placeholder="请输入重复密码" maxlength="20" /></view><view class="input-item flex align-center" style="width: 60%;margin: 0px;" v-if="captchaEnabled"><view class="iconfont icon-code icon"></view><input v-model="registerForm.code" type="number" class="input" placeholder="请输入验证码" maxlength="4" /><view class="login-code"> <image :src="codeUrl" @click="getCode" class="login-code-img"></image></view></view><view class="action-btn"><button @click="handleRegister()" class="register-btn cu-btn block bg-blue lg round">注册</button></view></view><view class="xieyi text-center"><text @click="handleUserLogin" class="text-blue">使用已有账号登录</text></view></view>
</template>
(2)逻辑实现代码
<script>import { getCodeImg, register } from '@/api/login'export default {data() {return {codeUrl: "",captchaEnabled: true,globalConfig: getApp().globalData.config,registerForm: {username: "",password: "",confirmPassword: "",code: "",uuid: '',userType:"app_user"}}},created() {this.getCode()},methods: {// 用户登录handleUserLogin() {this.$tab.navigateTo(`/pages/login`)},// 获取图形验证码getCode() {getCodeImg().then(res => {this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabledif (this.captchaEnabled) {this.codeUrl = 'data:image/gif;base64,' + res.data.imgthis.registerForm.uuid = res.data.uuid}})},// 注册方法async handleRegister() {if (this.registerForm.username === "") {this.$modal.msgError("请输入您的账号")} else if (this.registerForm.password === "") {this.$modal.msgError("请输入您的密码")} else if (this.registerForm.confirmPassword === "") {this.$modal.msgError("请再次输入您的密码")} else if (this.registerForm.password !== this.registerForm.confirmPassword) {this.$modal.msgError("两次输入的密码不一致")} else if (this.registerForm.code === "" && this.captchaEnabled) {this.$modal.msgError("请输入验证码")} else {this.$modal.loading("注册中,请耐心等待...")this.register()}},// 用户注册async register() {register(this.registerForm).then(res => {this.$modal.closeLoading()uni.showModal({title: "系统提示",content: "恭喜你,您的账号 " + this.registerForm.username + " 注册成功!",success: function (res) {if (res.confirm) {uni.redirectTo({ url: `/pages/login` });}}})}).catch(() => {if (this.captchaEnabled) {this.getCode()}})},// 注册成功后,处理函数registerSuccess(result) {// 设置用户信息this.$store.dispatch('GetInfo').then(res => {this.$tab.reLaunch('/pages/index')})}}}
</script>
(3)css样式
<style lang="scss">page {background-color: #ffffff;}.normal-login-container {width: 100%;.logo-content {width: 100%;font-size: 21px;text-align: center;padding-top: 15%;image {border-radius: 4px;}.title {margin-left: 10px;position: absolute;z-index: 100;}}.login-form-content {text-align: center;margin: 20px auto;margin-top: 30%;width: 80%;.input-item {margin: 20px auto;background-color: #f5f6f7;height: 45px;border-radius: 20px;.icon {font-size: 38rpx;margin-left: 10px;color: #999;}.input {width: 100%;font-size: 14px;line-height: 20px;text-align: left;padding-left: 15px;}}.register-btn {margin-top: 40px;height: 45px;}.xieyi {color: #333;margin-top: 20px;}.login-code {height: 38px;float: right;.login-code-img {height: 38px;position: absolute;margin-left: 10px;width: 200rpx;}}}}
.img-a {position: absolute;width: 100%;top: -74px;right: 0;z-index: 100;
}
.img-b {position: absolute;width: 50%;bottom: 0;left: -50rpx;z-index: 100;
}
</style>
3、接口(所有用到的js)
(1)login.js
import request from '@/utils/request'// 登录方法
export function login(username, password, code, uuid) {const data = {username,password,code,uuid}return request({'url': '/login',headers: {isToken: false},'method': 'post','data': data})
}// 注册方法
export function register(data) {return request({url: '/register',headers: {isToken: false},method: 'post',data: data})
}// 获取用户详细信息
export function getInfo() {return request({'url': '/getInfo','method': 'get'})
}// 退出方法
export function logout() {return request({'url': '/logout','method': 'post'})
}// 获取验证码
export function getCodeImg() {return request({'url': '/captchaImage',headers: {isToken: false},method: 'get',timeout: 20000})
}
(2)request.js
import store from '@/store'
import config from '@/config'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { toast, showConfirm, tansParams } from '@/utils/common'
import { encryptBase64, encryptWithAes, generateAesKey } from '@/utils/crypto';
import { encrypt } from '@/utils/jsencrypt';let timeout = 10000
const baseUrl = config.baseUrl
const clientId = config.clientIdconst request = config => {// 是否需要设置 tokenconst isToken = (config.headers || {}).isToken === falseconfig.header = config.header || {}if (getToken() && !isToken) {config.header['Authorization'] = 'Bearer ' + getToken()}config.header['clientid']=clientId// get请求映射params参数if (config.params) {let url = config.url + '?' + tansParams(config.params)url = url.slice(0, -1)config.url = url}// 是否需要加密const isEncrypt = (config.headers || {}).isEncrypt === true;// 当开启参数加密if (isEncrypt && (config.method === 'post' || config.method === 'put')) {// 生成一个 AES 密钥const aesKey = generateAesKey();config.header['encrypt-key'] = encrypt(encryptBase64(aesKey));config.data = typeof config.params === 'object' ? encryptWithAes(JSON.stringify(config.params), aesKey) : encryptWithAes(config.params, aesKey);}return new Promise((resolve, reject) => {uni.request({method: config.method || 'get',timeout: config.timeout ||  timeout,url: config.baseUrl || baseUrl + config.url,data: config.data,header: config.header,dataType: 'json'}).then(response => {let [error, res] = responseif (error) {toast('后端接口连接异常')reject('后端接口连接异常')return}const code = res.data.code || 200const msg = errorCode[code] || res.data.msg || errorCode['default']if (code === 401) {showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => {if (res.confirm) {store.dispatch('LogOut').then(res => {uni.reLaunch({ url: '/pages/login' })})}})reject('无效的会话,或者会话已过期,请重新登录。')} else if (code === 500) {toast(msg)reject('500')} else if (code !== 200) {toast(msg)reject(code)}resolve(res.data)}).catch(error => {let { message } = errorif (message === 'Network Error') {message = '后端接口连接异常'} else if (message.includes('timeout')) {message = '系统接口请求超时'} else if (message.includes('Request failed with status code')) {message = '系统接口' + message.substr(message.length - 3) + '异常'}toast(message)reject(error)})})
}export default request
(3)auth.js
const TokenKey = 'App-Token'export function getToken() {return uni.getStorageSync(TokenKey)
}export function setToken(token) {return uni.setStorageSync(TokenKey, token)
}export function removeToken() {return uni.removeStorageSync(TokenKey)
}
(4)common.js
/**
* 显示消息提示框
* @param content 提示的标题
*/
export function toast(content) {uni.showToast({icon: 'none',title: content})
}/**
* 显示模态弹窗
* @param content 提示的标题
*/
export function showConfirm(content) {return new Promise((resolve, reject) => {uni.showModal({title: '提示',content: content,cancelText: '取消',confirmText: '确定',success: function(res) {resolve(res)}})})
}/**
* 参数处理
* @param params 参数
*/
export function tansParams(params) {let result = ''for (const propName of Object.keys(params)) {const value = params[propName]var part = encodeURIComponent(propName) + "="if (value !== null && value !== "" && typeof (value) !== "undefined") {if (typeof value === 'object') {for (const key of Object.keys(value)) {if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {let params = propName + '[' + key + ']'var subPart = encodeURIComponent(params) + "="result += subPart + encodeURIComponent(value[key]) + "&"}}} else {result += part + encodeURIComponent(value) + "&"}}}return result
}
(5)crpto.js
import CryptoJS from 'crypto-js';/*** 随机生成32位的字符串* @returns {string}*/
export function generateRandomString(){const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';let result = '';const charactersLength = characters.lengthfor (let i = 0; i < 32; i++) {result += characters.charAt(Math.floor(Math.random() * charactersLength));}return result
}/*** 随机生成aes 密钥* @returns {string}*/
export function generateAesKey(){return CryptoJS.enc.Utf8.parse(generateRandomString());
}/*** 加密base64* @returns {string}*/
export function encryptBase64(str){return CryptoJS.enc.Base64.stringify(str);
}/*** 使用密钥对数据进行加密* @param message* @param aesKey* @returns {string}*/
export function encryptWithAes(message, aesKey){const encrypted = CryptoJS.AES.encrypt(message, aesKey, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});return encrypted.toString();
}
(6)jsencrypt.js
import JSEncrypt from 'jsencrypt';
// 密钥对生成 http://web.chacuo.net/netrsakeypairconst publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==';// 前端不建议存放私钥 不建议解密数据 因为都是透明的意义不大
const privateKey = '**********';// 加密
export function encrypt(txt){const encryptor = new JSEncrypt();encryptor.setPublicKey(publicKey); // 设置公钥return encryptor.encrypt(txt); // 对数据进行加密
};// 解密
export function decrypt(txt){const encryptor = new JSEncrypt();encryptor.setPrivateKey(privateKey); // 设置私钥return encryptor.decrypt(txt); // 对数据进行解密
};
(7)errorCode.js
export default {'401': '认证失败,无法访问系统资源','403': '当前操作没有权限','404': '访问资源不存在','default': '系统未知错误,请反馈给管理员'
}
(8)config.js
// 应用全局配置
module.exports = {baseUrl: 'http://localhost:8080',//根据实际更换//客户端idclientId:'...............',//授权模式grantType:'password',//租户idtenantId: '000000',//记住我模式rememberMe: false,// 应用信息appInfo: {// 应用名称name: "...",// 应用版本version: "1.1.0",// 应用logologo: "/static/logo.png",// 官方网站site_url: "...",// 政策协议agreements: [{title: "隐私政策",url: "..."},{title: "用户服务协议",url: "..."}]}
}


http://www.ppmy.cn/news/1427589.html

相关文章

Flutter 像素编辑器#03 | 像素图层

theme: cyanosis 本系列&#xff0c;将通过 Flutter 实现一个全平台的像素编辑器应用。源码见开源项目 【pix_editor】 《Flutter 像素编辑器#01 | 像素网格》《Flutter 像素编辑器#02 | 配置编辑》《Flutter 像素编辑器#03 | 像素图层》 上一篇我们实现了编辑配置&#xff0c;…

Redis:报错Creating Server TCP listening socket *:6379: bind: No error

错误&#xff1a; window下启动redis服务报错&#xff1a; Creating Server TCP listening socket *:6379: bind: No error 原因&#xff1a; 端口6379已被绑定&#xff0c;应该是因为上次未关闭服务 解决&#xff1a; ①依次输入命令&#xff1a; redis-cli.exe &#xff08…

从0到1实现RPC | 接入Apollo配置中心

一、代码实现 添加依赖 添加apollo客户端的依赖和spring配置相关依赖 添加监听器 通过实现ApplicationContextAware接口&#xff0c;获取Spring上下文。 使用ApolloConfigChangeListener注解监听命名空间rpc-demo-provider.yaml和默认的application.properties。 监听逻辑…

Flask + Bootstrap vs Flask + React/Vue:初学者指南

好的&#xff0c;让我为你提供一个初学者指南&#xff0c;并附上一些示例代码来说明 Flask Bootstrap 和 Flask React/Vue 的使用。 Flask Bootstrap&#xff1a; 安装 Flask 和 Bootstrap&#xff1a; 首先&#xff0c;确保你已经安装了 Python 和 pip。然后可以使用 pip …

【深度学习】AI修图——DragGAN原理解析

1、前言 上一篇&#xff0c;我们讲述了StyleGAN2。这一篇&#xff0c;我们就来讲一个把StyleGAN2作为基底架构的DragGAN。DragGAN的作用主要是对图片进行编辑&#xff0c;说厉害点&#xff0c;可能和AI修图差不多。这篇论文比较新&#xff0c;发表自2023年 原论文&#xff1a…

K8S之Resource Quotas

参考文档&#xff1a;资源配额 | Kubernetes 1.Resource Quotas&#xff1a;资源配额管理 当多个用户或团队共享具有固定节点数目的集群时&#xff0c;人们会担心有人使用超过其基于公平原则所分配到的资源量。 资源配额是帮助管理员解决这一问题的工具。 资源配额&#xff0c…

Linux编辑器gcc/g++的使用以及Makefile的用法

gcc如何完成 格式 gcc [选项] 要编译的文件 [选项] [目标文件] gcc对code.c编译形成可执行文件mybin&#xff0c;十分推荐直接这样写&#xff0c;下面会有拆分写法&#xff08;不推荐&#xff09; gcc与我们使用过的编辑器无二&#xff0c;都需要经过 1. 预处理&#xff08;…

【Day 3】Ajax + Vue 项目、路由 + Nginx

1 Ajax Asynchronous JavaScript And XML 异步的 JavaScript 和 XML 作用&#xff1a; 数据交换 通过 Ajax 可以给服务器发送请求&#xff0c;并获取服务器响应的数据 异步交互 可以在不重新加载整个页面的情况下&#xff0c;与服务器交换数据并更新部分网页的技术&#xf…