音乐网站的登录注册(持续更新)

一、需求文档(登陆注册)

1、用户名登录 2、注册(检测手机号是否已经注册) 3、二维码登录 4、短信登录 5、判断登录状态,(登陆了之后才可以访问收藏页面) 6、用户退出登录 7、获取登陆后用户名和头像 8、用户个人信息页 9、修改用户个人信息

二、开发文档

网易云的API文档 https://neteasecloudmusicapi.vercel.app/#/?id=_1-%e6%89%8b%e6%9c%ba%e7%99%bb%e5%bd%95

三、接口文档 数据库设计

user

user_id user_name password phone user_img

user_info

nickname img production gender birth
address id

四、进度安排

day1

1、路由注册100% 2、登录总页面100% 3、账号登录页面100%(egg后端+数据库) 4、用户注册页面实现(egg后端+数据库)100%

day2

1、实现二维码登录(网易云API)80% 2、实现短信登录(网易云API)80%

day3

1、二维码登录100% 2、短信登录100% 3、路由守卫拦截80% 4、登录成功后返回状态和信息50% 5、登录退出50%

day4

1、用户个人信息页面 2、用户信息修改(昵称,头像,手机号)

五、遇到的问题

1、路由接口的配置

alt

2、跨域处理

前端: vue.config.js

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  
  transpileDependencies: true,
    
    devServer: {
        port: 8080,
        host: 'localhost',
        // 可设置多个代理
        proxy: { //目的是解决跨域,若测试环境不需要跨域,则不需要进行该配置
            '/api': {
                target: 'http://127.0.0.1:7001/', // 目标 API 地址
                changeOrigin: true, //开启跨域
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    },
    lintOnSave: true

		  
	  
})

main.js

const http = axios.create({
  timeout: 1000 * 1000000,
  withCredentials: true,
  BASE_URL: '/api',
  headers: {
     'Content-Type': 'application/json; charset=utf-8'
   }
})

后端:cconfig.default.js

 //配置允许post请求
  config.security = {
    csrf: {
      enable: false,
      ignoreJSON: true,
    }
  }

        //配置跨域
        config.cors = {
          // origin: '*',
          origin:'http://localhost:8080',//cookie自带允许跨域
          allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH',
          credentials: true
        };
  

alt alt

3、路由拦截

alt

4、二维码传值的时候,key值传递过来后,能打印出来,但是就是用不了,用的时候就是undefined

因为我在写axios.get方法时,没写params,导致这个问题,采用打印语句,一步一步找到答案

5 通过短信发送验证码的时候,最好采用form表单,便于后面检验验证码的状态,就是需要检验按钮的状态,按钮能否被选择,还有就是要做防抖和节流

6 今天上午网易云的api突然访问不了,不知道是什么原因,后期在解决

7 采用短信登录的时候,应该是验证码输入之后,点击登录才跳转,而不是验证码一输入成功就登录成功。

8 用axios的时候最好是res返回值写在.then里面,这样更好拿后端的值

9 封装axios

1

alt

2

request.js

import axios from 'axios'

// 调用 axios.create() 函数,创建一个 axios 的实例对象,用 request 来接收
const request = axios.create({
  // 指定请求的根路径
  baseURL: 'https://netease-cloud-music-api-beta-lyart.vercel.app'
})

export default request

3 loginbyphone.js

// 通过电话号码登录相关的 API 接口
import request from '@/utils/request.js'
const qs = require('qs')

// 每次请求都带上时间戳 timestamp 参数  防止缓存
// withCredentials 请求为跨域类型时是否在请求中协带cookie
export const byPassword = function (phone, password) {
  return request.post('/login/cellphone', qs.stringify({
    phone: phone,
    password: password,
    timestamp: new Date().getTime()
  }))
}

// 发送短信验证码
export const sendCode = function (phone) {
  return request.get('/captcha/sent', {
    params: {
      phone: phone,
      timestamp: new Date().getTime()
    }
  })
}

// 验证短信验证码
export const byCode = function (phone, captcha) {
  return request.post('/captcha/verify', qs.stringify({
    phone: phone,
    captcha: captcha,
    timestamp: new Date().getTime()
  }))
}

4 loginebyphne.vue

<template>

  <div class="bbox">
    <div class="top">
      <div class="topp">
        登录
        <i class="el-icon-close"></i>
      </div>
    </div>
    <div class="mid">
        <img src="https://p6.music.126.net/obj/wo3DlcOGw6DClTvDisK1/9647707645/c8e7/4d8d/1895/6dff82b63181104bbac7cf3743c8b613.png" alt=""style="width:286px;" >
 
      <div id="form-container" style="margin:10px">
      <!-- <el-input placeholder="请输入手机号" v-model="phoneNumber" class="input-with-select">
        <i slot="prefix" class="el-input__icon el-icon-mobile-phone"></i>
      </el-input> -->
      <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="auto" class="login-ruleFrom" style="margin:0 15px">
        <el-form-item label="" prop="phoneNumber">
          <el-input v-model="ruleForm.phoneNumber" placeholder="请输入手机号">
            <i slot="prefix" class="el-input__icon el-icon-mobile-phone"></i>
          </el-input>
          <el-button size="mini" class="getCodeButton" :disabled="attcode" v-if="showBtn" @click="getCode">获取验证码</el-button>
          <el-button class="getCodeButton" plain disabled v-else >{{codeMsg}}</el-button>
        </el-form-item>
        <el-form-item label="" prop="phoneCode">
          <el-input v-model="ruleForm.phoneCode" placeholder="请输入验证码">
            <i slot="prefix" class="el-input__icon el-icon-lock"></i>
          </el-input>
        </el-form-item>
        <el-form-item label="" prop="type" style="margin-top:-10px">
          <el-switch v-model="ruleForm.autoLogin" active-text="自动登录" ></el-switch>
        </el-form-item>
        <el-form-item style="margin-bottom:-20px">
          <el-button type="primary" @click="submitForm('ruleForm')" style="width:100%;">登录</el-button>
        
        </el-form-item>
      </el-form>
    </div>
   
  </div>
  </div>
</template>

<script>
import { byCode, sendCode } from '@/api/LoginAndRegister/loginByPhone.js'


export default {
  data () {
    return {
      // 获取验证码按钮是否禁用
      attcode: true,
      // 获取验证码按钮是否展示
      showBtn: true,
      codeMsg: '获取验证码',
      // 倒计时
      codeSec: 60,
      ruleForm: {
        phoneNumber: '',
        phoneCode: '',
        autoLogin: false
      },
      rules: {
        phoneNumber: [
          { required: true, message: '请输入手机号', trigger: 'blur' },
          { pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/, message: '请正确填写您的手机号码', trigger: 'blur' }
        ],
        phoneCode: [
          { required: true, message: '请输入验证码', trigger: 'blur' },
          { pattern: /^[0-9]{4}$/, message: '请填写有效的验证码', trigger: 'blur' }
        ]
      }
    }
  },
  watch: {
    // 监听手机号 改变获取验证码按钮状态
    'ruleForm.phoneNumber': function (value) {
      const reg = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
      const val = reg.test(value)
      if (val) {
        this.attcode = false
      } else {
        this.attcode = true
      }
    },
    'ruleForm.phoneCode': async function (code) {
      if (code.length === 4) {
        // 自动请求并且登录
        const { data: byCodeData } = await byCode(this.ruleForm.phoneNumber, this.ruleForm.phoneCode)
        console.log(byCodeData)
        if (byCodeData.code === 200) {
          this.successLoginMsg()
             sessionStorage.setItem("user", true);
          this.$router.push("/");
          // 保存信息到 Vuex 跳转页面
        }
      }
    }
  },
  methods: {
    // 错误提示信息
    errorMsg () {
      this.$message({
        showClose: true,
        message: '电话或验证码错误!',
        type: 'error'
      })
    },
    // 短信发送成功提示信息
    successSendMsg () {
      this.$message({
        showClose: true,
        message: '短信发送成功!',
        type: 'success'
      })
    },
    // 登录成功提示信息
    successLoginMsg () {
      this.$message({
        showClose: true,
        message: '登录成功!',
        type: 'success'
      })
      console.log();
    },
    // 提交登录表单
    async submitForm (formName) {
      console.log(this.ruleForm.phoneNumber, this.ruleForm.phonePassword, this.ruleForm.autoLogin)
      this.$refs[formName].validate(async (valid) => {
        if (valid) {
          // 发送请求
          const byCodeData = await byCode(this.ruleForm.phoneNumber, this.ruleForm.phoneCode)
          if (byCodeData.code === 200) {
            // this.successLoginMsg()
              sessionStorage.setItem("user", true);
              this.$router.push("/");
            // 保存信息到 Vuex 跳转页面
          } else {
            this.errorMsg()
          }
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    // 发送验证码
    async getCode () {
      // 调用 sendCode 发送验证码
      const sendCodeData = await sendCode(this.ruleForm.phoneNumber)
      if (sendCodeData.code !== 200) this.successSendMsg()
      // 修改页面样式
      const timer = setInterval(() => {
        this.codeSec = this.codeSec - 1
        this.codeMsg = this.codeSec + 's后重试'
        this.showBtn = false
        if (this.codeSec === 0) {
          clearInterval(timer)
          this.codeSec = 60
          this.showBtn = true
        }
      }, 1000)
    }
  }
};
</script>

<style lang="scss" scoped>
.bbox {
  margin: auto;
  position: relative;
  width: 700px;
  // height: 370px;
  background-color: #fff;
  border: #333 solid 1px;
}
.top {
  width: 700px;
  height: 50px;
  background-color: rgb(49, 35, 35);
  color: white;
}
.topp {
  font-weight: bold;
  margin-left: 18px;
  margin-right: 18px;
  padding-top: 16px;
  display: flex;
  justify-content: space-between;
}
.mid{
    margin-top: 8px;
    // margin-left: 52px;
   padding-left: 93px;
    padding-top: 21px;
    padding-bottom: 10px;
    margin: auto;
    width: 400px;
    display: flex;
    flex-wrap:wrap;
     align-items:center;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);


}

.mima{
    margin-top: 20px;
}
.login{
    background-color: rgb(49, 125, 200);
    color: #fff;
   margin-top: 10px;}
   .mid img{
       margin-bottom:10px ;
   }
   .send{
    background-color: rgb(49, 125, 200);
    color: #fff;
   height: 29px;
    margin-top: 19px;

   }
   .huoqu{
   display: flex;
   justify-content: space-between;
   }

</style>

10 组长更换了服务器,采用部署的服务器,启动项目的时候,先将vue.config.js里面的devserver注释,启动之后在注释回来

alt

11 template中有两个及以上的跟标签就会导致编译不通过卡死

alt

12 background-image的用法

alt

全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务