前倾回顾
# 1 用户板块相关接口 - 验证手机号是否存在 - 多方式登录接口 - 发送短信接口(发送登录和发送注册短信使用同一个接口) - 短信登录接口 - 短信注册接口 # 2 验证手机号是否存在 -请求地址,编码格式,携带的数据---》后端写接口人定的 -地址:/api/v1/user/mobile/check_mobile/ -post请求 -请求体:{mobile:手机号} -自动生成路由---》视图类--》 def mobile(self, request) -@action(methods=['post'], detail=False, url_path='check_mobile') # 3 多方式登录 -请求地址,编码格式,携带的数据---》后端写接口人定的 -地址:/api/v1/user/login/mul_login/ -请求方式:post -编码格式:json -请求体:{username:用户名/手机号/邮箱,password:} -自动生成路由: router.register('login', UserLoginView, 'login') -写了个视图类: class UserLoginView(GenericViewSet): @action(methods=['POST'], detail=False) def mul_login(self,request): # ser=MulLoginSerializer(data=request.data) ser = self.get_serializer(data=request.data, context={'request': request}) ser.is_valid(raise_exception=True) # 字段自己[继承ModelSerializer,没有重写username],局部钩子[没有],全局钩子[重点写的] token username ser.context.get('username') icon return 给前端 - 序列化类:只做 校验 class MulLoginSerializer(serializer.Serializer): username = serializers.CharField() password = serializers.CharField() def validate(self, attrs): user = self._get_user(attrs) token = self._get_token(user) self._set_context(token, user) return attrs # 4 发送短信接口 -第三方发送短信:腾讯云短信 -发短信:直接复制---》测试 -封装:以后任意项目直接把包复制过去,导入就能使用 -settings.py # 配置信息---》在项目的配置文件中配置 -__init__.py # 注册了一下 想给外部用的函数 -sms.py # 获取随机验证码 发送短信 -发送短信接口: get:/api/v1/user/mobile/send_sms/?mobile=ssss # 5 短信登录接口 -{mobile ,code } -视图类,跟之前一模一样 -序列化类中:只有校验用户不一样 签发token,放context都是一样 # 6 注册接口 -{mobile,code,password} -注册接口不带密码---》也能注册成功---》发个短信--》让它及时修改密码 -生成默认密码---》第一次不允许登录 -手机号+验证码 如果注册过就登录,如果没注册过,就注册并且登录成功--》作业
前端注册页面分析
# 登录,注册,都写成组件----》在任意页面中,都能点击显示登录模态框 # 写好的组件,应该放在那个组件中----》不是【页面组件】(小组件) 如果我们想写简单---》登录注册做成页面组件--》点击路由跳转即可 放在Header.vue中,以后任意页面组件都会引入Header---》都会有登录注册的按钮 # 点击登录按钮,把Login.vue 通过定位,占满全屏,透明度设为 0.5 ,纯黑色背景,覆盖在组件上 # 在Login.vue点关闭,要把Login.vue隐藏起来,父子通信之子传父,自定义事件
Header.vue
## 页面中 <span @click="go_login">登录</span> <Login v-if="login_show" @close_login="close_login"></Login> ## data login_show: false ### methods go_login() { this.login_show = true }, close_login() { this.login_show = false }
Login.vue
<template> <div class="login"> <span @click="close">X</span> </div> </template> <script> export default { name: "Login", methods: { close() { this.$emit('close_login') } } } </script> <style scoped> .login { width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; z-index: 10; background-color: rgba(0, 0, 0, 0.5); } </style>
登录前端
Login.vue
<template> <div class="login"> <div class="box"> <i class="el-icon-close" @click="close_login"></i> <div class="content"> <div class="nav"> <span :class="{active: login_method === 'is_pwd'}" @click="change_login_method('is_pwd')">密码登录</span> <span :class="{active: login_method === 'is_sms'}" @click="change_login_method('is_sms')">短信登录</span> </div> <el-form v-if="login_method === 'is_pwd'"> <el-input placeholder="用户名/手机号/邮箱" prefix-icon="el-icon-user" v-model="username" clearable> </el-input> <el-input placeholder="密码" prefix-icon="el-icon-key" v-model="password" clearable show-password> </el-input> <el-button type="primary" @click="login">登录</el-button> </el-form> <el-form v-if="login_method === 'is_sms'"> <el-input placeholder="手机号" prefix-icon="el-icon-phone-outline" v-model="mobile" clearable @blur="check_mobile"> </el-input> <el-input placeholder="验证码" prefix-icon="el-icon-chat-line-round" v-model="sms" clearable> <template slot="append"> <span class="sms" @click="send_sms">{{ sms_interval }}</span> </template> </el-input> <el-button @click="mobile_login" type="primary">登录</el-button> </el-form> <div class="foot"> <span @click="go_register">立即注册</span> </div> </div> </div> </div> </template> <script> export default { name: "Login", data() { return { username: '', password: '', mobile: '', sms: '', // 验证码 login_method: 'is_pwd', sms_interval: '获取验证码', is_send: false, } }, methods: { close_login() { this.$emit('close') }, go_register() { this.$emit('go') }, change_login_method(method) { this.login_method = method; }, check_mobile() { if (!this.mobile) return; // js正则:/正则语法/ // '字符串'.match(/正则语法/) if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) { this.$message({ message: '手机号有误', type: 'warning', duration: 1000, onClose: () => { this.mobile = ''; } }); return false; } // 后台校验手机号是否已存在 this.$axios({ url: this.$settings.base_url + '/user/mobile/', method: 'post', data: { mobile: this.mobile } }).then(response => { let result = response.data.result; if (result) { this.$message({ message: '账号正常', type: 'success', duration: 1000, }); // 发生验证码按钮才可以被点击 this.is_send = true; } else { this.$message({ message: '账号不存在', type: 'warning', duration: 1000, onClose: () => { this.mobile = ''; } }) } }).catch(() => { }); }, send_sms() { // this.is_send必须允许发生验证码,才可以往下执行逻辑 if (!this.is_send) return; // 按钮点一次立即禁用 this.is_send = false; let sms_interval_time = 60; this.sms_interval = "发送中..."; // 定时器: setInterval(fn, time, args) // 往后台发送验证码 this.$axios({ url: this.$settings.base_url + '/user/sms/', method: 'get', params: { mobile: this.mobile } }).then(response => { let result = response.data.result; if (result) { // 发送成功 let timer = setInterval(() => { if (sms_interval_time <= 1) { clearInterval(timer); this.sms_interval = "获取验证码"; this.is_send = true; // 重新回复点击发送功能的条件 } else { sms_interval_time -= 1; this.sms_interval = `${sms_interval_time}秒后再发`; } }, 1000); } else { // 发送失败 this.sms_interval = "重新获取"; this.is_send = true; this.$message({ message: '短信发送失败', type: 'warning', duration: 3000 }); } }).catch(() => { this.sms_interval = "频率过快"; this.is_send = true; }) }, login() { // 用户名密码不能为空 if (!(this.username && this.password)) { this.$message({ message: '请填好账号密码', type: 'warning', duration: 1500 }); return false // 直接结束逻辑 } // 发送ajax请求登录 this.$axios.post('/user/login/mul_login/', { username: this.username, password: this.password }).then(res => { // 取出用户名,token和 icon,存到 cookie中 this.$cookies.set('token', res.token,'7d') this.$cookies.set('username', res.username,'7d') this.$cookies.set('icon', res.icon,'7d') //模态框关掉 this.$emit('close') }).catch(res => { // console.log(res) this.$message.error(res); }) }, mobile_login() { if (!(this.mobile && this.sms)) { this.$message({ message: '请填好手机与验证码', type: 'warning', duration: 1500 }); return false // 直接结束逻辑 } this.$axios({ url: this.$settings.base_url + '/user/mobile/login/', method: 'post', data: { mobile: this.mobile, code: this.sms, } }).then(response => { let username = response.data.result.username; let token = response.data.result.token; let user_id = response.data.result.id; this.$cookies.set('username', username, '7d'); this.$cookies.set('token', token, '7d'); this.$cookies.set('user_id', user_id, '7d'); this.$emit('success', response.data.result); }).catch(error => { console.log(error.response.data) }) } } } </script> <style scoped> .login { width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; z-index: 10; background-color: rgba(0, 0, 0, 0.3); } .box { width: 400px; height: 420px; background-color: white; border-radius: 10px; position: relative; top: calc(50vh - 210px); left: calc(50vw - 200px); } .el-icon-close { position: absolute; font-weight: bold; font-size: 20px; top: 10px; right: 10px; cursor: pointer; } .el-icon-close:hover { color: darkred; } .content { position: absolute; top: 40px; width: 280px; left: 60px; } .nav { font-size: 20px; height: 38px; border-bottom: 2px solid darkgrey; } .nav > span { margin: 0 20px 0 35px; color: darkgrey; user-select: none; cursor: pointer; padding-bottom: 10px; border-bottom: 2px solid darkgrey; } .nav > span.active { color: black; border-bottom: 3px solid black; padding-bottom: 9px; } .el-input, .el-button { margin-top: 40px; } .el-button { width: 100%; font-size: 18px; } .foot > span { float: right; margin-top: 20px; color: orange; cursor: pointer; } .sms { color: orange; cursor: pointer; display: inline-block; width: 70px; text-align: center; user-select: none; } </style>
Header.vue
<template> <div class="header"> <div class="slogan"> <p>老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活</p> </div> <div class="nav"> <ul class="left-part"> <li class="logo"> <router-link to="/"> <img src="../assets/img/head-logo.svg" alt=""> </router-link> </li> <li class="ele"> <span @click="goPage('/free-course')" :class="{active: url_path === '/free-course'}">免费课</span> </li> <li class="ele"> <span @click="goPage('/actual-course')" :class="{active: url_path === '/actual-course'}">实战课</span> </li> <li class="ele"> <span @click="goPage('/light-course')" :class="{active: url_path === '/light-course'}">轻课</span> </li> </ul> <div class="right-part"> <div v-if="username && username.length>0"> <span>{{ username }}</span> <span class="line">|</span> <span @click="logout">退出</span> </div> <div v-else> <span @click="go_login">登录</span> <span class="line">|</span> <span>注册</span> </div> </div> <Login v-if="login_show" @close="close_login"></Login> </div> </div> </template> <script> import Login from "@/components/Login"; export default { name: "Header", data() { return { url_path: sessionStorage.url_path || '/', login_show: false, // 控制Login.vue 是否显示 username: '', icon: '' } }, methods: { logout() { console.log('sdsafss') // 清除cookie this.$cookies.set('username', '') this.$cookies.set('icon', '') this.$cookies.set('token', '') // this.username和this.icon 值为空 this.username = '' this.icon = '' }, go_login() { // Header 组件中按钮点击触发 this.login_show = true }, close_login() { // 子[Login.vue] 传父[Header.vue]-->控制不显示 this.login_show = false // 取一下cookie中有没有用户名,如果有,说明用户登录了,就显示用户名 this.username = this.$cookies.get('username') this.icon = this.$cookies.get('icon') }, goPage(url_path) { if (this.url_path !== url_path) { this.$router.push(url_path); } sessionStorage.url_path = url_path; }, }, created() { sessionStorage.url_path = this.$route.path; this.url_path = this.$route.path; this.username = this.$cookies.get('username') this.icon = this.$cookies.get('icon') }, components: { Login } } </script> <style scoped> .header { background-color: white; box-shadow: 0 0 5px 0 #aaa; } .header:after { content: ""; display: block; clear: both; } .slogan { background-color: #eee; height: 40px; } .slogan p { width: 1200px; margin: 0 auto; color: #aaa; font-size: 13px; line-height: 40px; } .nav { background-color: white; user-select: none; width: 1200px; margin: 0 auto; display: block; } .nav ul { padding: 15px 0; float: left; } .nav ul:after { clear: both; content: ''; display: block; } .nav ul li { float: left; } .logo { margin-right: 20px; } .ele { margin: 0 20px; } .ele span { display: block; font: 15px/36px '微软雅黑'; border-bottom: 2px solid transparent; cursor: pointer; } .ele span:hover { border-bottom-color: orange; } .ele span.active { color: orange; border-bottom-color: orange; } .right-part { float: right; } .right-part .line { margin: 0 10px; } .right-part span { line-height: 68px; cursor: pointer; } .search { float: right; position: relative; margin-top: 22px; margin-right: 10px; } .search input, .search button { border: none; outline: none; background-color: white; } .search input { border-bottom: 1px solid #eeeeee; } .search input:focus { border-bottom-color: orange; } .search input:focus + button { color: orange; } .search .tips { position: absolute; bottom: 3px; left: 0; } .search .tips span { border-radius: 11px; background-color: #eee; line-height: 22px; display: inline-block; padding: 0 7px; margin-right: 3px; cursor: pointer; color: #aaa; font-size: 14px; } .search .tips span:hover { color: orange; } </style>
注册前端
Register.vue
<template> <div class="register"> <div class="box"> <i class="el-icon-close" @click="close_register"></i> <div class="content"> <div class="nav"> <span class="active">新用户注册</span> </div> <el-form> <el-input placeholder="手机号" prefix-icon="el-icon-phone-outline" v-model="mobile" clearable @blur="check_mobile"> </el-input> <el-input placeholder="密码" prefix-icon="el-icon-key" v-model="password" clearable show-password> </el-input> <el-input placeholder="验证码" prefix-icon="el-icon-chat-line-round" v-model="sms" clearable> <template slot="append"> <span class="sms" @click="send_sms">{{ sms_interval }}</span> </template> </el-input> <el-button @click="register" type="primary">注册</el-button> </el-form> <div class="foot"> <span @click="go_login">立即登录</span> </div> </div> </div> </div> </template> <script> export default { name: "Register", data() { return { mobile: '', password: '', sms: '', sms_interval: '获取验证码', is_send: false, } }, methods: { close_register() { this.$emit('close') }, go_login() { this.$emit('go') }, check_mobile() { if (!this.mobile) return; // js正则:/正则语法/ // '字符串'.match(/正则语法/) if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) { this.$message({ message: '手机号有误', type: 'warning', duration: 1000, onClose: () => { this.mobile = ''; } }); return false; } // 后台校验手机号是否已存在 this.$axios.post('/user/mobile/check_mobile/', { mobile: this.mobile }).then(res => { this.$message.info('您已经注册过,直接登录即可') this.$emit('go') }).catch(res => { this.$message.success('改手机号可以正常注册') this.is_send = true }) }, send_sms() { // this.is_send必须允许发生验证码,才可以往下执行逻辑 if (!this.is_send) return; // 按钮点一次立即禁用 this.is_send = false; let sms_interval_time = 60; this.sms_interval = "发送中..."; // 定时器: setInterval(fn, time, args) setInterval(() => { this.sms_interval = sms_interval_time - 1 sms_interval_time = this.sms_interval if (this.sms_interval == 1) { this.sms_interval = '发送验证码' this.is_send = true; } }, 1000) // 往后台发送验证码 this.$axios.get('/user/mobile/send_sms/?mobile=' + this.mobile).then(res => { this.$message.success(res.msg) }).catch(res => { this.$message.error('发送失败') }) }, register() { if (!(this.mobile && this.sms && this.password)) { this.$message({ message: '请填好手机、密码与验证码', type: 'warning', duration: 1500 }); return false // 直接结束逻辑 } this.$axios.post('/user/register/', { mobile: this.mobile, code: this.sms, password: this.password }).then(res => { this.$emit('go') }).catch(res => { this.$message.error('注册失败') }) } } } </script> <style scoped> .register { width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; z-index: 10; background-color: rgba(0, 0, 0, 0.3); } .box { width: 400px; height: 480px; background-color: white; border-radius: 10px; position: relative; top: calc(50vh - 240px); left: calc(50vw - 200px); } .el-icon-close { position: absolute; font-weight: bold; font-size: 20px; top: 10px; right: 10px; cursor: pointer; } .el-icon-close:hover { color: darkred; } .content { position: absolute; top: 40px; width: 280px; left: 60px; } .nav { font-size: 20px; height: 38px; border-bottom: 2px solid darkgrey; } .nav > span { margin-left: 90px; color: darkgrey; user-select: none; cursor: pointer; padding-bottom: 10px; border-bottom: 2px solid darkgrey; } .nav > span.active { color: black; border-bottom: 3px solid black; padding-bottom: 9px; } .el-input, .el-button { margin-top: 40px; } .el-button { width: 100%; font-size: 18px; } .foot > span { float: right; margin-top: 20px; color: orange; cursor: pointer; } .sms { color: orange; cursor: pointer; display: inline-block; width: 70px; text-align: center; user-select: none; } </style>
Header.vue
<template> <div class="header"> <div class="slogan"> <p>老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活</p> </div> <div class="nav"> <ul class="left-part"> <li class="logo"> <router-link to="/"> <img src="../assets/img/head-logo.svg" alt=""> </router-link> </li> <li class="ele"> <span @click="goPage('/free-course')" :class="{active: url_path === '/free-course'}">免费课</span> </li> <li class="ele"> <span @click="goPage('/actual-course')" :class="{active: url_path === '/actual-course'}">实战课</span> </li> <li class="ele"> <span @click="goPage('/light-course')" :class="{active: url_path === '/light-course'}">轻课</span> </li> </ul> <div class="right-part"> <div v-if="username && username.length>0"> <span>{{ username }}</span> <span class="line">|</span> <span @click="logout">退出</span> </div> <div v-else> <span @click="go_login">登录</span> <span class="line">|</span> <span @click="go_register">注册</span> </div> </div> <Login v-if="login_show" @close="close_login" @go="put_register"/> <Register v-if="is_register" @close="close_register" @go="put_login"/> </div> </div> </template> <script> import Login from "@/components/Login"; import Register from "@/components/Register"; export default { name: "Header", data() { return { url_path: sessionStorage.url_path || '/', login_show: false, // 控制Login.vue 是否显示 is_register: false, // 控制Register.vue 是否显示 username: '', icon: '' } }, methods: { logout() { console.log('sdsafss') // 清除cookie this.$cookies.set('username', '') this.$cookies.set('icon', '') this.$cookies.set('token', '') // this.username和this.icon 值为空 this.username = '' this.icon = '' }, go_login() { // Header 组件中按钮点击触发 this.login_show = true }, close_login() { // 子[Login.vue] 传父[Header.vue]-->控制不显示 this.login_show = false // 取一下cookie中有没有用户名,如果有,说明用户登录了,就显示用户名 this.username = this.$cookies.get('username') this.icon = this.$cookies.get('icon') }, close_register() { this.is_register = false }, go_register() { this.is_register = true }, put_register() { this.login_show = false this.is_register = true }, put_login() { this.login_show = true this.is_register = false }, goPage(url_path) { if (this.url_path !== url_path) { this.$router.push(url_path); } sessionStorage.url_path = url_path; }, }, created() { sessionStorage.url_path = this.$route.path; this.url_path = this.$route.path; this.username = this.$cookies.get('username') this.icon = this.$cookies.get('icon') }, components: { Login, Register } } </script> <style scoped> .header { background-color: white; box-shadow: 0 0 5px 0 #aaa; } .header:after { content: ""; display: block; clear: both; } .slogan { background-color: #eee; height: 40px; } .slogan p { width: 1200px; margin: 0 auto; color: #aaa; font-size: 13px; line-height: 40px; } .nav { background-color: white; user-select: none; width: 1200px; margin: 0 auto; display: block; } .nav ul { padding: 15px 0; float: left; } .nav ul:after { clear: both; content: ''; display: block; } .nav ul li { float: left; } .logo { margin-right: 20px; } .ele { margin: 0 20px; } .ele span { display: block; font: 15px/36px '微软雅黑'; border-bottom: 2px solid transparent; cursor: pointer; } .ele span:hover { border-bottom-color: orange; } .ele span.active { color: orange; border-bottom-color: orange; } .right-part { float: right; } .right-part .line { margin: 0 10px; } .right-part span { line-height: 68px; cursor: pointer; } .search { float: right; position: relative; margin-top: 22px; margin-right: 10px; } .search input, .search button { border: none; outline: none; background-color: white; } .search input { border-bottom: 1px solid #eeeeee; } .search input:focus { border-bottom-color: orange; } .search input:focus + button { color: orange; } .search .tips { position: absolute; bottom: 3px; left: 0; } .search .tips span { border-radius: 11px; background-color: #eee; line-height: 22px; display: inline-block; padding: 0 7px; margin-right: 3px; cursor: pointer; color: #aaa; font-size: 14px; } .search .tips span:hover { color: orange; } </style>
多方式登录前端
1 <template> 2 <div class="login"> 3 <div class="box"> 4 <i class="el-icon-close" @click="close_login"></i> 5 <div class="content"> 6 <div class="nav"> 7 <span :class="{active: login_method === 'is_pwd'}" 8 @click="change_login_method('is_pwd')">密码登录</span> 9 <span :class="{active: login_method === 'is_sms'}" 10 @click="change_login_method('is_sms')">短信登录</span> 11 </div> 12 13 <el-form v-if="login_method === 'is_pwd'"> 14 <el-input 15 placeholder="用户名/手机号/邮箱" 16 prefix-icon="el-icon-user" 17 v-model="username" 18 clearable> 19 </el-input> 20 <el-input 21 placeholder="密码" 22 prefix-icon="el-icon-key" 23 v-model="password" 24 clearable 25 show-password> 26 </el-input> 27 <el-button type="primary" @click="login">登录</el-button> 28 </el-form> 29 30 <el-form v-if="login_method === 'is_sms'"> 31 <el-input 32 placeholder="手机号" 33 prefix-icon="el-icon-phone-outline" 34 v-model="mobile" 35 clearable 36 @blur="check_mobile"> 37 </el-input> 38 <el-input 39 placeholder="验证码" 40 prefix-icon="el-icon-chat-line-round" 41 v-model="sms" 42 clearable> 43 <template slot="append"> 44 <span class="sms" @click="send_sms">{{ sms_interval }}</span> 45 </template> 46 </el-input> 47 <el-button @click="mobile_login" type="primary">登录</el-button> 48 </el-form> 49 50 <div class="foot"> 51 <span @click="go_register">立即注册</span> 52 </div> 53 </div> 54 </div> 55 </div> 56 </template> 57 58 <script> 59 export default { 60 name: "Login", 61 data() { 62 return { 63 username: '', 64 password: '', 65 mobile: '', 66 sms: '', // 验证码 67 login_method: 'is_pwd', 68 sms_interval: '获取验证码', 69 is_send: false, 70 } 71 }, 72 methods: { 73 close_login() { 74 this.$emit('close') 75 }, 76 go_register() { 77 this.$emit('go') 78 }, 79 change_login_method(method) { 80 this.login_method = method; 81 }, 82 check_mobile() { 83 if (!this.mobile) return; 84 // js正则:/正则语法/ 85 // '字符串'.match(/正则语法/) 86 if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) { 87 this.$message({ 88 message: '手机号有误', 89 type: 'warning', 90 duration: 1000, 91 onClose: () => { 92 this.mobile = ''; 93 } 94 }); 95 return false; 96 } 97 // 后台校验手机号是否已存在 98 99 this.$axios({ 100 url: 'user/mobile/check_mobile/', 101 method: 'post', 102 data: { 103 mobile: this.mobile 104 } 105 }).then(res => { 106 // 发生验证码按钮才可以被点击 107 this.is_send = true; 108 }).catch(() => { 109 this.$message({ 110 type: "error", 111 message: '您还没注册呢,请先注册', 112 onClose: () => { 113 this.mobile = '' 114 this.$emit('go') 115 } 116 117 }) 118 }); 119 }, 120 send_sms() { 121 // this.is_send必须允许发生验证码,才可以往下执行逻辑 122 if (!this.is_send) return; 123 // 按钮点一次立即禁用 124 this.is_send = false; 125 126 let sms_interval_time = 60; 127 this.sms_interval = "发送中..."; 128 129 // 定时器: setInterval(fn, time, args) 130 131 // 往后台发送验证码 132 this.$axios({ 133 url: '/user/mobile/send_sms/', 134 method: 'get', 135 params: { 136 mobile: this.mobile 137 } 138 }).then(res => { 139 let timer = setInterval(() => { 140 if (sms_interval_time <= 1) { 141 clearInterval(timer); 142 this.sms_interval = "获取验证码"; 143 this.is_send = true; // 重新回复点击发送功能的条件 144 } else { 145 sms_interval_time -= 1; 146 this.sms_interval = `${sms_interval_time}秒后再发`; 147 } 148 }, 1000); 149 150 }).catch(() => { 151 this.sms_interval = "频率过快"; 152 this.is_send = true; 153 }) 154 155 156 }, 157 login() { 158 // 用户名密码不能为空 159 if (!(this.username && this.password)) { 160 this.$message({ 161 message: '请填好账号密码', 162 type: 'warning', 163 duration: 1500 164 }); 165 return false // 直接结束逻辑 166 } 167 // 发送ajax请求登录 168 this.$axios.post('/user/login/mul_login/', { 169 username: this.username, 170 password: this.password 171 }).then(res => { 172 // 取出用户名,token和 icon,存到 cookie中 173 this.$cookies.set('token', res.token, '7d') 174 this.$cookies.set('username', res.username, '7d') 175 this.$cookies.set('icon', res.icon, '7d') 176 //模态框关掉 177 this.$emit('close') 178 }).catch(res => { 179 // console.log(res) 180 this.$message.error(res); 181 }) 182 183 }, 184 mobile_login() { 185 if (!(this.mobile && this.sms)) { 186 this.$message({ 187 message: '请填好手机与验证码', 188 type: 'warning', 189 duration: 1500 190 }); 191 return false // 直接结束逻辑 192 } 193 194 this.$axios({ 195 url: '/user/login/sms_login/', 196 method: 'post', 197 data: { 198 mobile: this.mobile, 199 code: this.sms, 200 } 201 }).then(res => { 202 this.$cookies.set('username', res.username, '7d'); 203 this.$cookies.set('token', res.token, '7d'); 204 this.$cookies.set('icon', res.icon, '7d'); 205 this.$emit('close'); 206 }).catch(error => { 207 console.log(error.response.data) 208 }) 209 } 210 } 211 } 212 </script> 213 214 <style scoped> 215 .login { 216 width: 100vw; 217 height: 100vh; 218 position: fixed; 219 top: 0; 220 left: 0; 221 z-index: 10; 222 background-color: rgba(0, 0, 0, 0.3); 223 } 224 225 .box { 226 width: 400px; 227 height: 420px; 228 background-color: white; 229 border-radius: 10px; 230 position: relative; 231 top: calc(50vh - 210px); 232 left: calc(50vw - 200px); 233 } 234 235 .el-icon-close { 236 position: absolute; 237 font-weight: bold; 238 font-size: 20px; 239 top: 10px; 240 right: 10px; 241 cursor: pointer; 242 } 243 244 .el-icon-close:hover { 245 color: darkred; 246 } 247 248 .content { 249 position: absolute; 250 top: 40px; 251 width: 280px; 252 left: 60px; 253 } 254 255 .nav { 256 font-size: 20px; 257 height: 38px; 258 border-bottom: 2px solid darkgrey; 259 } 260 261 .nav > span { 262 margin: 0 20px 0 35px; 263 color: darkgrey; 264 user-select: none; 265 cursor: pointer; 266 padding-bottom: 10px; 267 border-bottom: 2px solid darkgrey; 268 } 269 270 .nav > span.active { 271 color: black; 272 border-bottom: 3px solid black; 273 padding-bottom: 9px; 274 } 275 276 .el-input, .el-button { 277 margin-top: 40px; 278 } 279 280 .el-button { 281 width: 100%; 282 font-size: 18px; 283 } 284 285 .foot > span { 286 float: right; 287 margin-top: 20px; 288 color: orange; 289 cursor: pointer; 290 } 291 292 .sms { 293 color: orange; 294 cursor: pointer; 295 display: inline-block; 296 width: 70px; 297 text-align: center; 298 user-select: none; 299 } 300 </style>
redis介绍和安装
# redis 是什么? -非关系型数据库:redis,mongodb,es,clickhouse,influxDB no sql: not only sql -关系型数据库:mysql,oracle,postgrasql,sqlserver,sqlite -去IOE ,国产化 IBM:服务器 Oracle:数据库 达梦 EMC:存储 -redis 到底是什么? redis是一个key-value存储系统【软件】,用c语言写的,c/s架构的软件,纯内存存储,可以持久化【断电数据可以恢复】 value:有5钟数据类型 string:字符串 hash:字典 list:列表 set:集合 zset:有序集合 # redis为什么这么快? - qps :10w 6w左右 -1 纯内存操作,避免了io -2 使用了io多路复用的网络模型--(epoll) -3 数据操作是单线程单进程---【没有锁操作,没有线程间切换】 # 安装redis -redis开源项目,社区不支持win -使用的epoll模式,不能再win上运行的 -微软团队---》基于人家源码,修改+编译---》安装包--》可以装在win上 -最新:最新7.x # win平台最新只有 -最新5.x版本 https://github.com/tporadowski/redis/releases/ -最新3.x版本 https://github.com/microsoftarchive/redis/releases # 下载:Redis-x64-5.0.14.1.msi,一路下一步 # 启动redis服务端 -在服务中,启动redis即可 # 客户端安装 -cmd窗口 -redis-cli -h 127.0.0.1 -p 6379 -redis-cli -resp -安装链接 -Navicate 16 链接即可 -.....
标签:username,mobile,sms,color,luffy07dsys,login,icon From: https://www.cnblogs.com/wzh366/p/17987412