概述

上节通过传统的方式获取router路由守卫,拦截路由,用于用户登录,发现无法使用的问题。
嘟宝是为监督孩子身边环境而创建的一套应用,它能够实现后台驻留长连接,随时接收嘟妈信令,建立音视频通道点对点通信,而不需要中转 服务器。嘟妈是一套WEB 应用,使用vue3编写,能够兼容app、小程序开发。目前为止,嘟宝完成的基本功能设计包括

  • MQTT 基础通信
  • 后台驻留
  • SQLite数据存储
  • 二维码显示身份识别码
  • 开启自启动前台服务
  • 任务栏消息发送与点击
    嘟宝使用WebRtc与嘟妈建立音视频通信,它的核心需求包含以下部分:
  • 嘟妈获取嘟宝摄像头、麦克风音视频流
  • 获取嘟宝桌面共享内容
  • 嘟妈与嘟宝建立音视频通话
    嘟宝想要建立与嘟宝交互,需完成用户登录密码。用户登录完成,需生成唯一UUID,作为嘟妈ID与嘟宝交互。

uuid

UUID(通用唯一标识符)是一个128位的标准化数字标识符,核心价值在于让每台设备或系统独立生成的ID在全球范围内几乎不可能重复(重复概率低至天文数字级别)。它通常以32个十六进制字符的字符串形式呈现(如 123e4567-e89b-12d3-a456-426614174000),常用于数据库主键、分布式系统追踪、会话标识等场景。UUID有多个版本(如基于时间的v1、基于命名空间的v3/v5、完全随机的v4),其中v4最常用——它简单可靠,无需中心化协调,就能为海量对象提供唯一“身份证”,是构建现代分布式系统的基石工具之一。
如下代码,可以很轻松获取到uuid

let uuid=crypto.randomUUID 

但这在只能在localhost与https环境使用。非环境会报如下错误

Uncaught (in promise) TypeError: crypto.randomUUID is not a function

为了解决此类问题,引入第三方库uuid,它很好的解决了在http与https环境下生成uuid的问题
安装

npm install uuid

设计用具类uuid.ts

// utils/uuid.js
import { v4 as uuidv4 } from 'uuid'

/**
 * 生成 UUID
 * 优先使用原生 crypto.randomUUID,降级使用 uuid 库
 */
export function generateUUID() {
  try {
    // 尝试使用原生方法
    if (typeof crypto !== 'undefined' && crypto.randomUUID) {
      return crypto.randomUUID()
    }
  } catch (error) {
    console.warn('crypto.randomUUID 不可用,使用 uuid 库替代',error)
  }

  // 降级方案:使用 uuid 库
  return uuidv4()
}

// 或者直接导出 uuidv4
export { v4 as uuidv4 } from 'uuid'

在Login.vue调用

<template>
  <div class="login-container">
    <!-- 标题 -->
    <div class="login-title">密码登录</div>

    <!-- 登录表单 -->
    <van-form @submit="onSubmit">
      <!-- 账号输入 -->
      <van-field
        v-model="formData.account"
        name="account"
        placeholder="请输入手机号/邮箱"
        :rules="phoneRules"
      >
        <template #left-icon>
          <span class="country-code">+86</span>
        </template>
      </van-field>

      <!-- 密码输入 -->
      <van-field
        v-model="formData.password"
        type="password"
        name="password"
        placeholder="请输入密码"
        :rules="[{ required: true, message: '请输入密码' }]"
      />

      <!-- 协议勾选 -->
      <div class="agreement-wrapper">
        <van-checkbox v-model="formData.agreed" shape="round">
          <span class="agreement-text">
            我已阅读并同意签署
            <span class="link" @click.stop="goToAgreement('user')">《用户协议》</span>
            <span class="link" @click.stop="goToAgreement('privacy')">《隐私政策》</span>
          </span>
        </van-checkbox>
      </div>

      <!-- 登录按钮 -->
      <div class="login-btn-wrapper">
        <van-button
          round
          block
          type="primary"
          native-type="submit"
          :disabled="!formData.agreed"
        >
          登录/注册
        </van-button>
      </div>

      <!-- 验证码登录切换 -->
      <div class="switch-login" @click="switchToCodeLogin">
        验证码登录
      </div>
    </van-form>
  </div>
</template>

<script setup lang="ts">
import { reactive, onMounted } from 'vue'
import { showToast } from 'vant'
import 'vant/es/toast/style'
import { getUserData, setUserData } from '@/api/storge'
import { useRouter } from 'vue-router'
import { generateUUID } from '@/utils/uuid'
const router = useRouter()
// 表单数据
const formData = reactive({
  account: '',
  password: '',
  agreed: false,
  dumaId:''
})
onMounted(() => {
  console.log();
  if (getUserData()) {
    router.push('/home');

  } else {
    formData.dumaId =generateUUID();
  }


})
// 手机号校验规则
const phoneRules = [
  { required: true, message: '请输入手机号' },
  { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式' }
];
// 提交登录
const onSubmit = (values:any) => {
  if (!formData.agreed) {
    showToast('请先阅读并同意用户协议和隐私政策')
    return
  }

  console.log('登录提交:', values)
  setUserData(JSON.stringify(formData));
  router.push('/home');
  // 在这里调用登录 API
}

// 跳转协议页面
const goToAgreement = (type:any) => {
  console.log(`跳转到${type === 'user' ? '用户协议' : '隐私政策'}页面`)
  // 使用路由跳转
  // router.push(`/agreement/${type}`)
}

// 切换到验证码登录
const switchToCodeLogin = () => {
  showToast('切换到微信登录')
  // router.push('/login/code')
}
</script>

效果如下:
在这里插入图片描述

更多推荐