首页 > 其他分享 >luffy07dsys

luffy07dsys

时间:2024-01-25 16:22:50浏览次数:24  
标签:username mobile sms color luffy07dsys login icon

前倾回顾

# 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

相关文章