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

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

ruisui882个月前 (05-03)技术分析19

概述

本文档描述了基于 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原理)” 的相关文章

首个支持苹果 M1 Mac 的 Linux 发行版发布,面向用户开放下载

IT之家 3 月 20 日消息,Asahi Linux 是研究 Linux for Apple Silicon macs 的组织群体,3 月 18 日,Asahi Linux 宣布成功在 M1 MacBook Air 笔记本电脑上运行,并开放了 Asahi Linux 的下载安装。Asahi Lin...

2024前端面试真题之—VUE篇

添加图片注释,不超过 140 字(可选)1.vue的生命周期有哪些及每个生命周期做了什么? beforeCreate是new Vue()之后触发的第一个钩子,在当前阶段data、methods、computed以及watch上的数据和方法都不能被访问。 created在实例创建完成后发生,当前阶段已...

git的几种分支模式

编写代码,是软件开发交付过程的起点,发布上线,是开发工作完成的终点。代码分支模式贯穿了开发、集成和发布的整个过程,是工程师们最亲切的小伙伴。那如何根据自身的业务特点和团队规模来选择适合的分支模式呢?本文分享几种主流 Git 分支模式的流程及特点,并给出选择建议。分支的目的是隔离,但多一个分支也意味着...

学无止境:Git 如何优雅地回退代码

来源:https://zhenbianshu.github.io前言从接触编程就开始使用 Git 进行代码管理,先是自己玩 Github,又在工作中使用 Gitlab,虽然使用时间挺长,可是也只进行一些常用操作,如推拉代码、提交、合并等,更复杂的操作没有使用过,看过的教程也逐渐淡忘了,有些对不起 L...

虚幻引擎5.5发布

IT之家 11 月 13 日消息,虚幻引擎 5.5 现已发布。据介绍,新版本虚幻引擎在动画创作、虚拟制作和移动游戏开发方面取得进步;渲染、摄像机内视觉特效和开发人员迭代等领域的部分功能已可用于生产。IT之家整理部分功能亮点如下:动画Sequencer增强虚幻引擎的非线性动画编辑器 Sequencer...

最快清除数组空值?分享 1 段优质 JS 代码片段!

本内容首发于工粽号:程序员大澈,每日分享一段优质代码片段,欢迎关注和投稿!大家好,我是大澈!本文约 600+ 字,整篇阅读约需 1 分钟。今天分享一段优质 JS 代码片段,用最简洁的代码清除了数组中的空值。老规矩,先阅读代码片段并思考,再看代码解析再思考,最后评论区留下你的见解!const arr...