Vue.js + Element UI 实现多方式登录功能(账号/手机号验证码登录)

news2024/10/18 21:17:20
 引言

       在现代Web应用中,提供多种登录方式已成为一种标准做法,这不仅能提升用户体验,还能满足不同用户的需求。本文将详细介绍如何使用Vue.js框架结合Element UI组件库,实现一个包含账号登录和手机号验证码登录两种方式的登录页面。通过本文,你将能够掌握如何根据用户选择动态切换登录表单、如何进行表单验证以及如何实现验证码的发送和倒计时功能。

功能需求
  1. 账号登录:用户通过输入用户名和密码进行登录。
  2. 验证码登录:用户通过输入手机号码并接收验证码进行登录。
效果图

1. 登录页面设计

src/components目录下创建一个名为Login.vue的文件,用于实现登录页面。

1.1 模板部分(Template)

使用Element UI的el-form组件构建登录表单,通过v-if指令根据flag变量的值动态显示不同的登录方式(账号登录或手机号验证码登录)

<template>
  <div class="login">
    <el-form
      ref="loginForm"
      :model="loginForm"
      :rules="loginRules"
      class="login-form"
      :inline="true"
    >
      <!-- 标题部分 -->
      <div class="title">
        <div
          @click="showPhone"
          v-if="flag == 'verificationCode'"
          class="title-back"
        >
          <i class="el-icon-arrow-left"></i>返回
        </div>
        <div class="title-span">{{ formTitle }}</div>
      </div>

      <!-- 账号登录表单 -->
      <div class="formCont" v-if="flag == 'account'">
        <el-form-item prop="username" label="用户名:">
          <el-input
            v-model="loginForm.username"
            type="text"
            auto-complete="off"
            placeholder="用户名"
          >
          </el-input>
        </el-form-item>
        <el-form-item prop="password" label="密码:">
          <el-input
            v-model="loginForm.password"
            type="password"
            auto-complete="off"
            placeholder="密码"
            show-password
            @keyup.enter.native="handleLogin"
          >
          </el-input>
        </el-form-item>
        <div class="button">
          <el-form-item style="width: 100%">
            <el-button
              size="medium"
              type="primary"
              style="width: 100%"
              @click.native.prevent="handleLogin"
            >
              登 录
            </el-button>
          </el-form-item>
        </div>
      </div>

      <!-- 手机号码登录表单 -->
      <div class="formCont phone-cont" v-if="flag == 'phone'">
        <el-form-item prop="phoneNumber">
          <div class="text">请使用人事处登记手机号进行登录</div>
          <el-input
            v-model="loginForm.phoneNumber"
            type="text"
            auto-complete="off"
            placeholder="请输入手机号码"
          >
          </el-input>
        </el-form-item>
        <div class="button">
          <el-form-item style="width: 100%">
            <el-button
              size="medium"
              type="primary"
              style="width: 100%"
              @click.native.prevent="handlePhoneNumber"
            >
              验证手机号码
            </el-button>
          </el-form-item>
        </div>
      </div>

      <!-- 验证码输入部分 -->
      <div v-if="flag == 'verificationCode'" class="verification-code">
        <div class="tx">输入验证码</div>
        <div class="tx">我们已向{{ phoneNumber }} 发送验证码</div>
        <div class="tx">请查看短信并输入验证码</div>
        <div class="six-digit-wrapper">
          <input
            v-for="(item, index) in digits"
            :key="index"
            :ref="`ref${index}`"
            class="input"
            v-model="item.value"
            type="text"
            oninput="value=value.replace(/[^\d]/g,'')"
            @input="onInput(index)"
            @keyup.delete="onDelete(index)"
            maxlength="1"
          />
        </div>
        <div
          class="anew-verification-code anew-verification-code-send"
          v-if="show"
          @click="handleGetCode"
        >
          重新获取验证码
        </div>
        <div class="anew-verification-code" v-else>
          {{ count }}秒后重新获取短信
        </div>
      </div>

      <!-- 切换登录方式按钮 -->
      <div class="btn-cont" @click="showPhone" v-if="flag == 'account'">
        验证码登录
      </div>
      <div class="btn-cont" @click="showAccount" v-if="flag == 'phone'">
        账号字码登录
      </div>
    </el-form>
  </div>
</template>
1.2 脚本部分(Script)

在脚本部分,定义登录表单的数据模型、验证规则以及方法。

<script>
export default {
  name: "Login",
  components: {},
  data() {
    return {
      loginForm: {
        username: "",
        password: "",
        phoneNumber: "",
      },
      loginRules: {
        username: [
          { required: true, trigger: "blur", message: "请输入您的账号" },
        ],
        password: [
          { required: true, trigger: "blur", message: "请输入您的密码" },
        ],
        phoneNumber: [
          { required: true, message: "手机号码不能为空", trigger: "blur" },
          {
            pattern: /^1(3|4|5|6|7|8|9)\d{9}$/,
            message: "手机号码格式错误",
            trigger: "blur",
          },
        ],
      },
      formTitle: "管理员账号登录",
      flag: "account",
      phoneNumber: "",
      show: true, // 控制倒计时状态
      count: 60, // 倒计时秒数
      timer: null, //计时器
      digits: [
        {
          value: "",
        },
        {
          value: "",
        },
        {
          value: "",
        },
        {
          value: "",
        },
        {
          value: "",
        },
        {
          value: "",
        },
      ],
    };
  },
  // 省略了部分代码,完整代码见下文
};
</script>
2. 功能实现
2.1 账号登录

用户选择账号登录时,表单显示用户名和密码输入框。通过Element UI的el-form组件的validate方法进行表单验证,验证通过后调用登录接口。

 //管理员账号登录
    handleLogin() {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          //你的调用登录接口的代码
        }
      });
    },
2.2 手机号验证码登录

用户选择手机号验证码登录时,表单显示手机号输入框。用户输入手机号后,点击“验证手机号码”按钮,调用发送验证码接口,并启动倒计时。

// 验证手机号码
    handlePhoneNumber() {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          this.formTitle = "验证手机号码";
          this.phoneNumber = this.loginForm.phoneNumber;
          this.flag = "verificationCode";
          this.handleGetCode();
        }
      });
    },
    // 获取短信验证码
    handleGetCode() {
      // 验证码倒计时
      if (!this.timer) {
        //调取你的发送验证码的接口
        sendCode({ phone: this.phoneNumber }).then((res) => {
          // 处理发送验证码的响应
        });

        this.count = 60;
        this.show = false;
        this.timer = setInterval(() => {
          if (this.count > 0 && this.count <= 60) {
            this.count--;
          } else {
            this.show = true;
            clearInterval(this.timer);
            this.timer = null;
          }
        }, 1000);
      }
    },

在验证码输入框中,通过监听inputkeyup.delete事件,实现光标的自动移动和删除功能。

// 输入验证码时的处理
    onInput(index) {
      // index < 5 ,如果是第6格,不触发光标移动至下一个输入框。
      if (this.digits[index].value && index < 5) {
        this.$refs["ref" + (index + 1)][0].focus();
      } else {
        let resultString = this.digits.map((obj) => obj.value).join("");
        if (resultString.length == 6) {
          let data = { phone: this.phoneNumber, code: resultString };
          //调取你的验证码登录接口
          mwlogin(data).then((res) => {
            // 处理验证码登录的响应
          });
        }
      }
    },
    // 删除验证码时的处理
    onDelete(index) {
      // 如果是第1格,不触发光标移动至上一个输入框
      if (index > 0) {
        this.$refs["ref" + (index - 1)][0].focus();
      }
    },
3. 样式调整

根据需要调整样式,确保表单在不同设备上的显示效果。

4. 测试与优化
  • 测试:确保在不同情况下(如输入错误、验证码发送失败等)都有相应的提示和处理。
  • 优化:根据实际需求优化用户体验,如添加加载动画、错误提示等。
完整代码
<template>
  <div class="login">
    <el-form
      ref="loginForm"
      :model="loginForm"
      :rules="loginRules"
      class="login-form"
      :inline="true"
    >
      <!-- 标题部分 -->
      <div class="title">
        <div
          @click="showPhone"
          v-if="flag == 'verificationCode'"
          class="title-back"
        >
          <i class="el-icon-arrow-left"></i>返回
        </div>
        <div class="title-span">{{ formTitle }}</div>
      </div>

      <!-- 账号登录表单 -->
      <div class="formCont" v-if="flag == 'account'">
        <el-form-item prop="username" label="用户名:">
          <el-input
            v-model="loginForm.username"
            type="text"
            auto-complete="off"
            placeholder="用户名"
          >
          </el-input>
        </el-form-item>
        <el-form-item prop="password" label="密码:">
          <el-input
            v-model="loginForm.password"
            type="password"
            auto-complete="off"
            placeholder="密码"
            show-password
            @keyup.enter.native="handleLogin"
          >
          </el-input>
        </el-form-item>
        <div class="button">
          <el-form-item style="width: 100%">
            <el-button
              size="medium"
              type="primary"
              style="width: 100%"
              @click.native.prevent="handleLogin"
            >
              登 录
            </el-button>
          </el-form-item>
        </div>
      </div>

      <!-- 手机号码登录表单 -->
      <div class="formCont phone-cont" v-if="flag == 'phone'">
        <el-form-item prop="phoneNumber">
          <div class="text">请使用人事处登记手机号进行登录</div>
          <el-input
            v-model="loginForm.phoneNumber"
            type="text"
            auto-complete="off"
            placeholder="请输入手机号码"
          >
          </el-input>
        </el-form-item>
        <div class="button">
          <el-form-item style="width: 100%">
            <el-button
              size="medium"
              type="primary"
              style="width: 100%"
              @click.native.prevent="handlePhoneNumber"
            >
              验证手机号码
            </el-button>
          </el-form-item>
        </div>
      </div>

      <!-- 验证码输入部分 -->
      <div v-if="flag == 'verificationCode'" class="verification-code">
        <div class="tx">输入验证码</div>
        <div class="tx">我们已向{{ phoneNumber }} 发送验证码</div>
        <div class="tx">请查看短信并输入验证码</div>
        <div class="six-digit-wrapper">
          <input
            v-for="(item, index) in digits"
            :key="index"
            :ref="`ref${index}`"
            class="input"
            v-model="item.value"
            type="text"
            oninput="value=value.replace(/[^\d]/g,'')"
            @input="onInput(index)"
            @keyup.delete="onDelete(index)"
            maxlength="1"
          />
        </div>
        <div
          class="anew-verification-code anew-verification-code-send"
          v-if="show"
          @click="handleGetCode"
        >
          重新获取验证码
        </div>
        <div class="anew-verification-code" v-else>
          {{ count }}秒后重新获取短信
        </div>
      </div>

      <!-- 切换登录方式按钮 -->
      <div class="btn-cont" @click="showPhone" v-if="flag == 'account'">
        验证码登录
      </div>
      <div class="btn-cont" @click="showAccount" v-if="flag == 'phone'">
        账号字码登录
      </div>
    </el-form>
  </div>
</template>

<script>
import { sendCode, mwlogin } from "@/api/login";
export default {
  name: "Login",
  components: {},
  data() {
    return {
      loginForm: {
        username: "",
        password: "",
        phoneNumber: "",
      },
      loginRules: {
        username: [
          { required: true, trigger: "blur", message: "请输入您的账号" },
        ],
        password: [
          { required: true, trigger: "blur", message: "请输入您的密码" },
        ],
        phoneNumber: [
          { required: true, message: "手机号码不能为空", trigger: "blur" },
          {
            pattern: /^1(3|4|5|6|7|8|9)\d{9}$/,
            message: "手机号码格式错误",
            trigger: "blur",
          },
        ],
      },
      formTitle: "管理员账号登录",
      flag: "account",
      phoneNumber: "",
      show: true, // 控制倒计时状态
      count: 60, // 倒计时秒数
      timer: null, //计时器
      digits: [
        {
          value: "",
        },
        {
          value: "",
        },
        {
          value: "",
        },
        {
          value: "",
        },
        {
          value: "",
        },
        {
          value: "",
        },
      ],
    };
  },
  watch: {},
  mounted() {},
  created() {},
  methods: {
    //管理员账号登录
    handleLogin() {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          //你的调用登录接口的代码
        }
      });
    },
    // 切换到手机号码登录
    showPhone() {
      this.formTitle = "管理员手机号码登录";
      this.flag = "phone";
    },
    // 切换到账号登录
    showAccount() {
      this.formTitle = "管理员账号登录";
      this.flag = "account";
    },
    // 验证手机号码
    handlePhoneNumber() {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          this.formTitle = "验证手机号码";
          this.phoneNumber = this.loginForm.phoneNumber;
          this.flag = "verificationCode";
          this.handleGetCode();
        }
      });
    },
    // 获取短信验证码
    handleGetCode() {
      // 验证码倒计时
      if (!this.timer) {
        //调取你的发送验证码的接口
        sendCode({ phone: this.phoneNumber }).then((res) => {
          // 处理发送验证码的响应
        });

        this.count = 60;
        this.show = false;
        this.timer = setInterval(() => {
          if (this.count > 0 && this.count <= 60) {
            this.count--;
          } else {
            this.show = true;
            clearInterval(this.timer);
            this.timer = null;
          }
        }, 1000);
      }
    },
    // 输入验证码时的处理
    onInput(index) {
      // index < 5 ,如果是第6格,不触发光标移动至下一个输入框。
      if (this.digits[index].value && index < 5) {
        this.$refs["ref" + (index + 1)][0].focus();
      } else {
        let resultString = this.digits.map((obj) => obj.value).join("");
        if (resultString.length == 6) {
          let data = { phone: this.phoneNumber, code: resultString };
          //调取你的验证码登录接口
          mwlogin(data).then((res) => {
            // 处理验证码登录的响应
          });
        }
      }
    },
    // 删除验证码时的处理
    onDelete(index) {
      // 如果是第1格,不触发光标移动至上一个输入框
      if (index > 0) {
        this.$refs["ref" + (index - 1)][0].focus();
      }
    },
  },
};
</script>

<style rel="stylesheet/scss" lang="scss">
.login {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  width: 100%;
  background-image: url("https://img202.yun300.cn/img/s05bg.jpg?tenantId=238938&viewType=1&k=1632806193000");
  background-size: 100% 100%;
  background-repeat: no-repeat;
  position: relative;
}
.btn-cont {
  font-family: "Arial Normal", "Arial", sans-serif;
  font-weight: 400;
  font-style: normal;
  color: #ca512f;
  line-height: 20px;
  text-align: center;
  margin-top: 30px;
  cursor: pointer;
}
.title {
  text-align: left;
  margin: 0 auto 35px;
  height: 40px;
  padding-top: 10px;
  display: flex;
  .title-back {
    color: #ca512f;
  }
  .title-span {
    position: relative;
    margin: 0 auto 32px auto;
    width: -webkit-fit-content;
    width: -moz-fit-content;
    width: fit-content;
    height: -webkit-fit-content;
    height: -moz-fit-content;
    height: fit-content;
    background: -webkit-gradient(
      linear,
      left top,
      left bottom,
      color-stop(50%, #e2eff6),
      to(#8cbcdf)
    );
    background: linear-gradient(180deg, #e2eff6 50%, #8cbcdf);
    color: transparent;
    -webkit-background-clip: text;
    font-size: 38px;
    letter-spacing: 2px;
    font-family: cursive;
    font-weight: 700;
  }
}
.verification-code {
  text-align: center;
  font-family: "Arial Normal", "Arial", sans-serif;
  font-weight: 400;
  font-style: normal;
  font-size: 18px;
  letter-spacing: normal;
  .tx {
    margin-bottom: 16px;
    color: #ffffff;
  }
  .anew-verification-code {
    color: #ca512f;
  }
  .anew-verification-code-send {
    cursor: pointer;
  }
}
.login .login-form {
  position: absolute;
  top: 30vh;
  left: 50%;
  transform: translateX(-50%);
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.2);
  width: 503px;
  height: 400px;
  .formCont {
    padding: 0 40px 0;
  }
  .el-input {
    height: 40px;
    width: 300px;
    input {
      height: 40px;
      border: 1px solid RGBA(28, 57, 77, 0.6);
    }
  }
  .input-icon {
    height: 39px;
    width: 14px;
    margin-left: 2px;
  }
  .phone-cont {
    .text {
      font-family: "微软雅黑", sans-serif;
      font-weight: 400;
      font-size: 14px;
      color: #ffffff;
      text-align: center;
    }

    .el-input {
      width: 423px;
    }
  }
}

.login-code {
  height: 38px;
  float: right;
  img {
    cursor: pointer;
    vertical-align: middle;
  }
}
.login {
  .login-code-img {
    height: 38px;
    width: 75px;
    margin-left: 25px;
  }
  .el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__label:before {
    display: none;
  }
  .el-form-item--medium .el-form-item__label {
    color: #fff;
    width: 64px;
    height: 22px;
    text-align: left;
    font-size: 15px;
    font-weight: unset;
  }
  .el-form-item {
    margin: 22px 10px 22px 0;
  }
  .button {
    .el-form-item {
      margin-bottom: unset;
    }
    .el-form-item__content {
      width: 100%;
    }
    .el-button--primary {
      background: linear-gradient(
        to top right,
        rgb(231, 133, 106) rgb(202, 81, 47, 1)
      );
    }
  }

  .el-tabs__item.is-active {
    color: rgba(0, 204, 255, 1) !important;
  }
  .el-tabs--top .el-tabs__item {
    color: RGBA(3, 129, 170, 1);
    padding: unset;
  }

  .six-digit-wrapper {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    margin: 20px 0 50px 0;
    .input {
      display: flex;
      width: 60px;
      margin-left: 10px;
      height: 60px;
      font-size: 24px;
      color: #333333;
      background-color: #f2f2f2;
      text-align: center;
      outline: none; // 去除选中状态边框
      border: solid 1px #d2d2d2;
      border-top: 0px;
      border-left: 0px;
      border-right: 0px;
    }
  }
}
</style>
<style scoped lang="scss">
::v-deep {
  .el-dialog {
    .el-dialog__header {
      background: #ffffff !important;
      padding: 0;
      height: 30px;
    }
  }
}
</style>
总结

本文详细介绍了如何使用Vue.js和Element UI实现一个多方式登录功能的登录页面。通过本文的学习,你可以掌握如何根据用户选择动态切换表单、如何进行表单验证以及如何实现验证码的发送和倒计时功能。希望本文对你有所帮助,如果你在实现过程中遇到任何问题,欢迎在评论区留言讨论。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode 单词规律

即判断给定的模式字符串&#xff08;pattern&#xff09;和单词字符串&#xff08;s&#xff09;是否遵循相同的对应规则。具体来说&#xff0c;就是要判断 pattern 中的字符与 s 中的单词是否存在一一对应的关系&#xff0c;即双射&#xff08;bijection&#xff09;。 算法思…

ant design vue TimePicker时间选择器不点击确认也可以设置值

文章目录 前言一、背景二、操作步骤1.复现前的准备工作&#xff08;1&#xff09;vue版本和ant design vue 版本&#xff08;2&#xff09;任意ant design vue TimePicker的demo 2.解决问题&#xff08;1&#xff09;使用change时间&#xff08;无效&#xff09;&#xff08;2&…

【学习】word保存图片

word中有想保存的照片 直接右键另存为的话&#xff0c;文件总是不清晰&#xff0c;截屏的话&#xff0c;好像也欠妥。 怎么办? 可以另存为 网页 .html 可以得到&#xff1a; 原图就放到了文件夹里面

在线白板:为远程课堂注入活力的协作工具

在线白板作为一种协作平台&#xff0c;极大地丰富了远程教学的互动性和创造性。在即时白板的帮助下&#xff0c;教师能够与学生共同在虚拟空间中创作和交流&#xff0c;实现知识的共享与思维的碰撞。 https://js.design/?sourcecsdn&planjh1018 首先&#xff0c;在线白板…

Spring Security 基础配置详解(附Demo)

目录 前言1. 基本知识2. Demo3. 实战 前言 基本的Java知识推荐阅读&#xff1a; java框架 零基础从入门到精通的学习路线 附开源项目面经等&#xff08;超全&#xff09;【Java项目】实战CRUD的功能整理&#xff08;持续更新&#xff09; 1. 基本知识 HttpSecurity 是 Spri…

【计算机网络 - 基础问题】每日 3 题(四十五)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…

基于Spring Cloud的电商系统设计与实现——用户与商品模块的研究(上)

操作系统&#xff1a;Windows Java开发包&#xff1a;JDK1.8 项目管理工具&#xff1a;Maven3.6.0 项目开发工具&#xff1a;IntelliJIDEA 数据库&#xff1a;MySQL Spring Cloud版本&#xff1a;Finchley.SR2 Spring Boot版本&#xff1a;2.0.6.RELEASE 目录 用户模块—user-…

机器学习-RBF

径向基函数内核 – 机器学习 内核在将数据转换为更高维空间方面发挥着重要作用,使算法能够学习复杂的模式和关系。在众多的内核函数中,径向基函数(RBF)内核作为一种多功能且强大的工具脱颖而出。在本文中,我们深入探讨了RBF内核的复杂性,探讨了它的数学公式、直观理解、…

【分布式知识】MapReduce详细介绍

文章目录 MapReduce概述1. MapReduce编程模型Map阶段Reduce阶段 2. Shuffle和Sort阶段3. MapReduce作业的执行流程4. MapReduce的优化和特性5. MapReduce的配置和调优 MapReduce局限性相关文献 MapReduce概述 MapReduce是一个分布式计算框架&#xff0c;它允许用户编写可以在大…

使用串口中断接收时遇到的小问题(单字节接收,固定多字节接收,不定长字节接收)

单字节接收 在cubemx初始化串口1&#xff0c;打开串口中断 在usart。c文件中修改中断回调函数 //串口接收回调函数 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if( huart &huart1)//判断中断源 { if(g_ucUsart1ReceiveData 0x01) { …

Java使用原生HttpURLConnection实现发送HTTP请求

1、HttpURLConnection 类的介绍 HttpURLConnection 是 Java 提供的原生标准的用于发送 HTTP 请求和接收 HTTP 响应的一个类&#xff0c;它位于 java.net 包下&#xff0c;并继承了 URLConnection 类。 HttpURLconnection 是基于 HTTP 协议的&#xff0c;支持 get&#xff0c;…

Flink有状态计算

前言 状态是什么&#xff1f;状态就是数据&#xff0c;准确点说&#xff0c;状态是指 Flink 作业计算时依赖的历史数据或中间数据。如果一个 Flink 作业计算依赖状态&#xff0c;那它就是有状态计算的作业&#xff0c;反之就是无状态计算的作业。 举个例子&#xff0c;服务端…

【高阶数据结构】揭开红黑树‘恶魔’的面具:深度解析底层逻辑

高阶数据结构相关知识点可以通过点击以下链接进行学习一起加油&#xff01;二叉搜索树AVL树 大家好&#xff0c;我是店小二&#xff0c;欢迎来到本篇内容&#xff01;今天我们将一起探索红黑树的工作原理及部分功能实现。红黑树的概念相对抽象&#xff0c;但只要我们一步步深入…

单链表算法题(二)(超详细版)

前言 : 通过算法题 &#xff0c; 学习解决问题的思路 &#xff0c; 再面对类似的算法题时 &#xff0c; 能快速定位解决方案 一 . 链表的回文结构 链表的回文结构 : 链表的回文结构_牛客题霸_牛客网 思路一 : 创建新链表 &#xff0c; 对原链表进行反转&#xff0c;结果存储在…

计算机毕业设计Python深度学习房价预测 房源可视化 房源爬虫 二手房可视化 二手房爬虫 递归决策树模型 机器学习 深度学习 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 房地产是促进我国经济持续增…

Google play开发者账号被封,申诉就有机会,别不信

在谷歌上架&#xff0c;开发者账号被封对很多开发者来说已经是家常便饭了&#xff0c;虽说一直都有在流传申诉没有用。别灰心啊&#xff0c;申诉就有机会&#xff0c;不少开发者都申诉成功了。 尤其是用一个少一个、价值好几个w的老号&#xff0c;不申诉就认栽实在是太亏了&…

Bootstrap 弹出框(Popover)插件

弹出框&#xff08;Popover&#xff09;与工具提示&#xff08;Tooltip&#xff09;类似&#xff0c;提供了一个扩展的视图。如需激活弹出框&#xff0c;用户只需把鼠标悬停在元素上即可。弹出框的内容完全可使用 Bootstrap 数据 API&#xff08;Bootstrap Data API&#xff09…

Mysql底层原理详细剖析

1. 索引数据结构 索引是帮助mysql 是帮助数据排序 且高效获取数据的数据结构 索引的数据结构有&#xff1a; 二叉树红黑树hash表b树 1.1 二叉查找树 二叉查找树 如果要查找&#xff0c;通过二分查找的复杂度进行查找数据&#xff0c;确实优化了性能&#xff0c;减少了io的…

【中危】Oracle TNS Listener SID 可以被猜测

一、漏洞详情 Oracle 打补丁后&#xff0c;复测出一处中危漏洞&#xff1a;Oracle TNS Listener SID 可以被猜测。 可以通过暴力猜测的方法探测出Oracle TNS Listener SID&#xff0c;探测出的SID可以用于进一步探测Oracle 数据库的口令。 建议解决办法&#xff1a; 1. 不应该使…

机器学习—特性缩放

特性缩放的技术能使梯度下降运行得更快&#xff0c;让我们先来看看功能大小之间的关系&#xff0c;这就是该特性的数字和相关参数的大小&#xff0c;作为一个具体的例子&#xff0c;让我们用两个特征来预测房子的价格&#xff0c;X1代表一个房子的大小&#xff0c;X2代表两个卧…