当前位置:首页 > 技术分析 > 正文内容

vue3+deepseek 实现简单的问答(vue deep原理)

ruisui8816小时前技术分析3

概述

本文档描述了基于 DeepSeek API 实现的智能助手 Web 应用的技术实现细节。该应用提供文本聊天和语音输入功能,支持与 DeepSeek 大模型进行交互。

功能特性

  1. 文本聊天:用户可通过文本输入与 AI 进行交互
  2. 语音输入:支持按住说话进行语音输入
  3. 响应式设计:适配移动端和 Web 端
  4. 消息展示:区分用户消息和 AI 回复
  5. 加载状态:显示加载动画提升用户体验

技术栈

  • Vue 3 (Composition API)
  • Axios (HTTP 请求)
  • Web Speech API (语音识别)
  • Vant UI (部分组件)
  • DeepSeek API (AI 交互)

API 配置

javascript

复制

const apiKey = '自己的key';
const baseURL = 'https://api.deepseek.com';

核心组件

模板结构

html

复制

<template>
  <div class="chat-container">
    <!-- 标题 -->
    <div class="title">智能助手</div>
    
    <!-- 消息列表 -->
    <div class="inner">
      <!-- 消息项 -->
      <div v-for="(msg, index) in messages" :key="index" :class="['msgbox', msg.role == 'user' ? 'msgboxright' : 'msgboxleft']">
        <!-- 头像 -->
        <div class="headImg" v-if="msg.role != 'user'">
          <img src="机器人头像URL" />
        </div>
        
        <!-- 消息内容 -->
        <div :class="['message', msg.role]">
          {{ msg.content }}
        </div>
        
        <!-- 用户头像 -->
        <div class="headImg" v-if="msg.role == 'user'">
          <img src="用户头像URL" />
        </div>
      </div>
      
      <!-- 加载动画 -->
      <div v-if="isLoading" class="snippet" data-title=".dot-elastic">
        <div class="stage">
          <div class="dot-elastic"></div>
        </div>
      </div>
    </div>
    
    <!-- 底部输入区域 -->
    <div class="footer">
      <div class="talk">
        <!-- 语音/文本输入切换 -->
        <div v-if="flag" class="aa" @touchstart="startListening" @touchend="stopListening">
          {{ talkFlag ? '讲话中...' : '按住说话' }}
        </div>
        
        <!-- 文本输入框 -->
        <input placeholder="请输入您的问题" v-else v-model="userInput" @keyup.enter="sendToDeepSeek" />
        
        <!-- 发送按钮/切换按钮 -->
        <div v-if="userInput" @click.stop="sendToDeepSeek">
          <img v-if="!flag" src="发送图标URL" class="send" />
        </div>
        <div v-else @click.prevent.stop="changeFlag">
          <img :src="flag ? '键盘图标URL' : '语音图标URL'" class="jianpan" />
        </div>
      </div>
    </div>
  </div>
</template>

运行 HTML

脚本逻辑

javascript

复制

import { ref, onMounted } from 'vue';
import axios from 'axios';

// 响应式数据
const messages = ref([{ role: 'system', content: '您好,请问有什么可以帮助您的吗?' }]);
const flag = ref(true); // 语音/文本输入标志
const userInput = ref(''); // 用户输入
const isLoading = ref(false); // 加载状态
const recognition = ref(null); // 语音识别对象
const transcript = ref(''); // 语音识别文本
const talkFlag = ref(false); // 语音识别状态

// 初始化语音识别
const initSpeechRecognition = () => {
  if (window.webkitSpeechRecognition) {
    recognition.value = new window.webkitSpeechRecognition();
    recognition.value.continuous = true;
    recognition.value.interimResults = true;
    recognition.value.lang = 'zh-CN';
  } else {
    alert('你的浏览器不支持语音识别功能');
  }
};

// 开始语音识别
const startListening = (e) => {
  e.preventDefault();
  talkFlag.value = true;
  if (recognition.value) {
    recognition.value.start();
    recognition.value.onresult = (event) => {
      transcript.value = Array.from(event.results)
        .map(result => result[0])
        .map(result => result.transcript)
        .join('');
    };
  }
};

// 停止语音识别
const stopListening = (e) => {
  e.preventDefault();
  talkFlag.value = false;
  if (recognition.value) {
    if (transcript.value) {
      messages.value.push({ role: 'user', content: transcript.value });
      setTimeout(() => {
        scrollNext();
        handelMes();
      });
    }
    recognition.value.stop();
  }
};

// 发送消息到DeepSeek
const sendToDeepSeek = () => {
  messages.value.push({ role: 'user', content: userInput.value });
  userInput.value = '';
  setTimeout(() => {
    scrollNext();
    handelMes();
  });
};

// 处理AI回复
const handelMes = async () => {
  try {
    isLoading.value = true;
    const response = await axios.post(
      `${baseURL}/chat/completions`,
      {
        model: 'deepseek-chat',
        messages: [...messages.value],
        temperature: 0.7,
        stream: false
      },
      {
        headers: {
          Authorization: `Bearer ${apiKey}`,
          'Content-Type': 'application/json'
        }
      }
    );
    messages.value.push(response.data.choices[0].message);
    setTimeout(() => {
      scrollNext();
    });
  } catch (error) {
    console.error('API调用失败:', error.response?.data || error.message);
  } finally {
    isLoading.value = false;
  }
};

// 滚动到最新消息
const scrollNext = () => {
  let list = document.getElementsByClassName('msgbox');
  let tmp = list[list.length - 1];
  let bottom = tmp.getBoundingClientRect().top;
  window.scrollTo({
    top: bottom,
    left: 0,
    behavior: 'smooth'
  });
};

// 切换输入模式
const changeFlag = () => {
  userInput.value = '';
  transcript.value = '';
  talkFlag.value = false;
  flag.value = !flag.value;
};

onMounted(() => {
  initSpeechRecognition();
});

样式设计

css

复制

.chat-container {
  min-height: 100vh;
  overflow-y: auto;
  
  .title {
    color: #fff;
    font-size: 20px;
    line-height: 60px;
    padding: 0px 20px;
    font-weight: bold;
    background: rgb(0, 162, 255);
  }
  
  .inner {
    padding: 20px;
  }
  
  .msgbox {
    display: flex;
    font-size: 14px;
    margin-bottom: 30px;
    
    .headImg {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      overflow: hidden;
      margin-right: 15px;
      
      img {
        width: 100%;
        height: 100%;
        object-fit: fill;
      }
    }
    
    .message {
      max-width: 80%;
      background: #fff;
      padding: 12px 16px;
      border-radius: 12px;
      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
    }
  }
  
  .msgboxright {
    justify-content: end;
    
    .headImg {
      margin-left: 15px;
    }
  }
  
  .footer {
    display: flex;
    bottom: 0px;
    width: 100%;
    height: 80px;
    padding: 0px 20px;
    position: fixed;
    background: #fff;
    align-items: center;
    justify-content: center;
    
    .talk {
      width: 100%;
      border-radius: 30px;
      border: 1px solid #e9e7e7;
      height: 50px;
      display: flex;
      align-items: center;
      padding: 0px 15px;
      justify-content: space-between;
      
      .aa {
        font-size: 14px;
        font-weight: bold;
        line-height: 50px;
        text-align: center;
        width: 100%;
      }
      
      input {
        width: 70%;
        border: 0;
        padding: 0px 5px;
        font-size: 14px;
      }
      
      .send, .jianpan {
        width: 30px;
        height: 30px;
      }
    }
  }
}

/* 加载动画样式 */
.dot-elastic {
  position: relative;
  width: 5px;
  height: 5px;
  margin: auto;
  border-radius: 50%;
  background-color: rgb(0, 162, 255);
  color: rgb(0, 162, 255);
  animation: dotElastic 1s infinite linear;
}

/* 动画关键帧定义 */
@keyframes dotElasticBefore {
  0% { transform: scale(1, 1); }
  25% { transform: scale(1, 1.5); }
  50% { transform: scale(1, 0.67); }
  75% { transform: scale(1, 1); }
  100% { transform: scale(1, 1); }
}

@keyframes dotElastic {
  0% { transform: scale(1, 1); }
  25% { transform: scale(1, 1); }
  50% { transform: scale(1, 1.5); }
  75% { transform: scale(1, 1); }
  100% { transform: scale(1, 1); }
}

@keyframes dotElasticAfter {
  0% { transform: scale(1, 1); }
  25% { transform: scale(1, 1); }
  50% { transform: scale(1, 0.67); }
  75% { transform: scale(1, 1.5); }
  100% { transform: scale(1, 1); }
}

部署说明

  1. 在 DeepSeek 平台注册账号并获取 API Key
  2. 替换代码中的 apiKey 为您的实际 Key
  3. 构建并部署 Vue 应用

注意事项

  1. API Key 应妥善保管,避免泄露
  2. 语音识别功能需要浏览器支持 Web Speech API
  3. 生产环境应考虑添加 API 调用频率限制和错误处理
  4. 对于敏感信息,建议在后端处理 API 调用而非前端

示例效果

可通过以下链接查看实际效果:

https://h5-dev.ennejb.cn/h5_application/#/test

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/3772.html

分享给朋友:

“vue3+deepseek 实现简单的问答(vue deep原理)” 的相关文章

Gitlab+Jenkins通过钩子实现自动部署web项目,图文详细教程

扩展参考:Jenkins+Gitlab通过脚本自动部署回滚web项目至集群 一:基础环境介绍及准备1):Gitlab服务器:ubuntu 192.168.152.131 ---参考搭建:Linux安装gitlab,docker安装gitlab教程2):Jenkins服务器:ubunu 192.168...

30 个纯 HTML5 实现的游戏

浏览器和 JavaScript 的功能逐年不断的变强变大。曾几何时,任何类型的游戏都需要Flash。但随着 HTML5 发展,HTML5 + WebGL 游戏式就慢慢占领着这个舞台。以下是30款流行的游戏,它们可以在所有现代浏览器中运行,并且只使用web技术构建。1. HexGL地址:http://...

Vue学习笔记之动态路由的参数传递应用及技巧

路由的参数传递:①通过params的类型· 配置路由格式:/router/:id· 传递的方式:在path后面跟上对应的值· 传递后形成的路径:/router/list,/router/profile这个就是前两篇中提到的"动态路由"中有应用过这个方法:②通过query的类型(对象方...

Vue中路由router的基本使用

??本文开始我们来给大家介绍在Vue中非常重要的一个内容,就是路由Router什么是路由后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源;前端路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特...

前端路由简介以及vue-router实现原理

作者:muwoo 来源:https://zhuanlan.zhihu.com/p/37730038后端路由简介路由这个概念最先是后端出现的。在以前用模板引擎开发页面时,经常会看到这样http://www.xxx.com/login 大致流程可以看成这样:浏览器发出请求服务器监听到80 端口(或443...

Vue中的路由配置常用属性

router:路由页面跳转的核心库;引入路由:import VueRouter from 'vue-router'; 注册路由:const router = new VueRouter({ })mode:模式路由有hash history两种模式:hash模式URL中包含#,#后边是...