vue.js登录页怎么调用二维码的接口

admin 102 0
在Vue.js登录页调用二维码接口,首先通过axios或fetch向后端接口发送请求,获取二维码数据(如base64编码或图片URL),使用async/await处理异步请求,结合ref/reactive管理二维码状态,将返回数据绑定到img标签的src属性渲染,需处理请求异常,并可根据需求设置定时器刷新二维码(如过期后重新获取),确保登录流程顺畅,核心步骤包括接口请求、数据渲染、异常处理及定时更新,实现二维码登录功能。

Vue.js登录页实现二维码登录:接口调用与集成指南

在现代化Web应用开发中,二维码登录凭借其便捷性和安全性优势,已成为用户认证的主流方式之一,本文将系统性地介绍如何在Vue.js项目中集成二维码登录功能,涵盖后端接口对接、二维码生成与展示、状态轮询机制以及完整的用户交互流程,为开发者提供一套可落地的技术实现方案。

需求分析与流程梳理

实现二维码登录功能需要遵循以下核心流程:

  1. 前端请求二维码:用户访问登录页面时,前端向后端接口发起请求,生成唯一的二维码标识。

  2. 二维码展示:前端接收后端返回的二维码数据(URL或base64图片格式),并将其渲染到页面指定区域。

  3. 状态轮询机制:前端设置定时器,定期向后端查询二维码当前状态(包括:未扫描、已扫描、已确认登录、已过期等)。

  4. 登录结果处理:根据轮询结果实时更新UI状态,显示相应提示信息,并在登录成功后执行页面跳转或业务逻辑。

技术准备

前端依赖配置

本项目基于以下技术栈构建:

  • Vue.js 3:采用Composition API进行组件开发(Vue 2项目可类似实现)
  • Axios:处理HTTP请求,支持请求/响应拦截器
  • 二维码生成库:推荐使用qrcode(生成base64图片)或vue-qrcode(Vue专用组件)

安装依赖命令:

npm install axios qrcode
# 或使用vue-qrcode组件化方案
npm install vue-qrcode@2

后端接口规范

假设后端已提供以下标准化接口(具体字段需与后端团队协商确定):

生成二维码接口

请求POST /api/login/qrcode

// 请求参数(可选)
{
  "deviceInfo": "web_chrome_2024",
  "platform": "pc"
}

响应

{
  "code": 0,
  "message": "success",
  "data": {
    "token": "qr_2024052012345678", // 二维码唯一标识
    "qrCodeUrl": "https://api.example.com/qr?token=xxx", // 二维码图片URL
    "qrCodeBase64": "data:image/png;base64,iVBORw0KGgoAAAANS...", // 或直接返回base64
    "expireTime": 300, // 有效时间(秒)
    "createTime": 1716234567890 // 创建时间戳
  }
}
查询二维码状态接口

请求GET /api/login/qrcode/status

// 请求参数
{
  "token": "qr_2024052012345678"
}

响应

{
  "code": 0,
  "message": "success",
  "data": {
    "status": 1, // 1:未扫描 2:已扫描 3:已确认登录 4:已过期 5:已取消
    "userInfo": { // status=3时返回
      "userId": "1001",
      "username": "张三",
      "avatar": "https://example.com/avatar.jpg",
      "token": "user_jwt_token_2024"
    },
    "scanTime": 1716234578900, // 扫描时间戳
    "confirmTime": 1716234580000 // 确认登录时间戳
  }
}

前端实现步骤

创建登录页组件

src/views/Login.vue中实现完整的登录页面布局:

<template>
  <div class="login-container">
    <div class="login-box">
      <h2>二维码登录</h2>
      <!-- 二维码展示区域 -->
      <div v-if="qrCodeUrl" class="qr-code-wrapper">
        <img 
          :src="qrCodeUrl" 
          alt="二维码" 
          class="qr-code"
          @error="handleQrError"
        />
        <p class="status-text">{{ statusText }}</p>
        <!-- 扫码动画效果 -->
        <div v-if="status === 2" class="scan-animation">
          <div class="scan-line"></div>
        </div>
      </div>
      <!-- 加载状态 -->
      <div v-else class="loading">
        <div class="loading-spinner"></div>
        <p>{{ loadingText }}</p>
      </div>
      <!-- 操作按钮 -->
      <div class="action-buttons">
        <button 
          v-if="showRefreshBtn" 
          @click="getQrCode" 
          class="refresh-btn"
        >
          重新生成
        </button>
        <button 
          v-if="status === 4" 
          @click="resetQrCode" 
          class="reset-btn"
        >
          刷新二维码
        </button>
      </div>
      <!-- 其他登录方式 -->
      <div class="other-login-methods">
        <p>其他登录方式</p>
        <div class="social-login">
          <!-- 社交媒体登录按钮 -->
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import axios from 'axios'
import QRCode from 'qrcode'
// 状态定义
const qrCodeUrl = ref('') // 二维码图片URL
const qrToken = ref('') // 二维码唯一标识
const status = ref(1) // 1:未扫描 2:已扫描 3:已确认 4:已过期 5:已取消
const loadingText = ref('正在生成二维码...')
const showRefreshBtn = ref(false)
const timer = ref(null) // 轮询定时器
const isPolling = ref(false) // 轮询状态标识
// 根据状态显示对应的文本
const statusText = computed(() => {
  const statusMap = {
    1: '请使用手机扫描二维码',
    2: '扫码成功,请在手机上确认登录',
    3: '登录成功,正在跳转...',
    4: '二维码已过期,请重新生成',
    5: '登录已取消'
  }
  return statusMap[status.value] || ''
})
// 生成二维码
const getQrCode = async () => {
  try {
    loadingText.value = '正在生成二维码...'
    showRefreshBtn.value = false
    status.value = 1
    const response = await axios.post('/api/login/qrcode', {
      deviceInfo: navigator.userAgent,
      platform: 'web'
    })
    if (response.data.code === 0) {
      const { token, qrCodeUrl, qrCodeBase64 } = response.data.data
      qrToken.value = token
      // 优先使用base64,否则使用URL
      if (qrCodeBase64) {
        qrCodeUrl.value = qrCodeBase64
      } else {
        qrCodeUrl.value = qrCodeUrl
      }
      // 开始轮询状态
      startPolling()
    } else {
      throw new Error(response.data.message || '生成二维码失败')
    }
  } catch (error) {
    console.error('生成二维码失败:', error)
    loadingText.value = '生成失败,请重试'
    showRefreshBtn.value = true
  }
}
// 轮询二维码状态
const pollQrStatus = async () => {
  if (!qrToken.value || isPolling.value) return
  try {
    isPolling.value = true
    const response = await axios.get('/api/login/qrcode/status', {
      params: { token: qrToken.value }
    })
    if (response.data.code === 0) {
      const newStatus = response.data.data.status
      // 状态变化处理
      if (newStatus !== status.value) {
        status.value = newStatus
        // 登录成功处理
        if (new

标签: #js #登录页 #二维码 #接口调用