vue简简单单实现一个AI页面

1,895 阅读4分钟

vue简简单单实现一个AI页面

在当今数字化时代,AI 技术正逐渐融入我们的生活。本项目将带领您使用 Vue 框架,以简洁高效的方式实现一个令人惊叹的 AI 页面。通过深入浅出的步骤和清晰的代码示例,即使您是 Vue 的初学者,也能轻松掌握其中的奥秘,为您开启通往 AI 与前端交互的精彩之旅。

开始前的准备:node环境,vue3(包含路由),tailwindcss css,chatgpt的网站以及api。 node环境可以参考这个教程:(blog.csdn.net/Nicolecocol…)

vue3的npm的安装命令:

初始化项目 npm init -y

安装 Vite npm init vite

在后续的选择中选择vue -> JavaScript

tailwindcss css的npm安装

npm install -D tailwindcss postcss autoprefixer

npx tailwindcss init -p

chatgpt网站: api.302.ai/v1/chat/com…

开干

所需文件及位置 image.png

**tailwind.css文件的内容

**

@tailwind base; 
//导入 Tailwind CSS 的基础样式,这些通常是一些重置和默认
//的样式设置,用于确保在不同浏览器中的一致性和基本的样式表现。

@tailwind components;
//导入可能自定义的组件相关的样式。这部分通常用于覆盖或扩展
//Tailwind 提供的默认组件样式,或者引入您自己定义的基于 Tailwind 类的组件样式。

@tailwind utilities;
//导入 Tailwind 的实用工具类,这包含了各种常见的样式类,如
//间距、字体大小、颜色、阴影等,可以直接应用于 HTML 元素来快速实现各种样式效果。

当然您也可以用原生css,这些都是指提供页面的样式

gpt.js里面的的内容

export const chat = async (messages, apiKey) => { 
  // 定义一个名为 chat 的异步函数,接收消息数组 messages 和 API 密钥 apiKey 作为参数
  try { 
    // 尝试执行以下代码
    const result = await fetch("https://api.302.ai/v1/chat/completions", { 
      // 发送一个 fetch 请求
      method: "POST", 
      // 请求方法为 POST
      headers: { 
        // 设置请求头
        "Content-Type": "application/json", 
        // 设置授权信息
        Authorization: `Bearer ${apiKey}`,
      },
      body: JSON.stringify({ 
        // 将请求体转换为 JSON 字符串
        model: "gpt-3.5-turbo",
        messages: messages,
      }),
    });

    const data = await result.json(); 
    // 等待将响应解析为 JSON 格式
    console.log(data); 
    // 打印响应数据
    return data.choices[0].message.content; 
    // 返回响应数据中 choices 数组的第一个元素的 message 对象的 content 属性值
  } catch (err) { 
    // 如果上述操作过程中发生错误
    throw err; 
    // 抛出错误
  }
};

router.js路由文件的内容:

import { createRouter, createWebHashHistory } from "vue-router";
// 从 'vue-router' 库中导入创建路由和创建哈希历史记录的方法

// 定义路由对象
const router = createRouter({
  history: createWebHashHistory(),
  // 使用 createWebHashHistory 方法创建哈希路由的历史记录模式

  routes: [
    // 定义路由配置数组
    {
      path: "/",
      // 根路径
      name: "home",
      // 路由名称为 'home'
      component: () => import("../views/Home.vue"),
      // 当访问根路径时,通过动态导入加载 '../views/Home.vue' 组件
    },
    {
      path: "/about",
      name: "about",
      // 路径为 '/about',路由名称为 'about'
      component: () => import("../views/About.vue"),
      // 当访问 '/about' 路径时,通过动态导入加载 '../views/About.vue' 组件
    },
  ],
});

export default router;
// 将创建的路由对象导出,以便在其他模块中使用

APP.vue文件的内容:

APP.vue是根组件,在此的作用是

路由整合:包含 <router-view> 来展示根据路由匹配动态切换的页面内容。

<template>
  <div>
    <router-view />
  </div>
</template>

<script setup>

</script>

<style lang="css" scoped></style>

主角来了:

<template>
    <div class="flex flex-col h-screen">
        <!-- 顶部导航栏 -->
        <div class="flex flex-nowrap fixed w-full items-baseline top-0 px-6 py-4 bg-gray-100">
            <div class="text-2xl font-bold">ChatGPT</div>
            <div class="ml-4 text-sm text-gray-500">
                基于OpenAI的ChatGPT自然语言模型人工智能对话
            </div>
            <div class="ml-auto px-3 py-2 text-sm cursor-pointer hover:bg-white rounded-md" @click="clickConfig()">
                设置
            </div>
        </div>
        <!-- 消息显示区域 -->
        <div class="flex-1">
            <div class="flex flex-col mt-24 px-6 pb-8">
                <div :class="`flex flex-col justify-center ${item.role == 'user'? 'items-end' : 'items-start'
                    }`" v-for="(item, index) in messageList.slice(2)" :key="index">
                    <p>{{ item.role }}</p>
                    <p class="color-gray-500 text-sm">{{ item.content }}</p>
                </div>
            </div>
        </div>
        <!-- 输入区域 -->
        <div class="sticky bottom-0 w-full p-6 pb-8 bg-gray-100">
            <div class="mb-2 text-sm text-gray-500">请输入API KEY:</div>
            <div class="flex">
                <input v-model="messageContent" class="input flex-1" :type="isConfig? 'password' : 'text'"
                    :placeholder="isConfig? 'k-xxxxxx' : '给ChatGPT发送消息'" @keydown.enter="sendOrSave()" />
                <button class="btn ml-4" :disabled="isTalking" @click="sendOrSave()">
                    保存
                </button>
            </div>
        </div>
    </div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { chat } from '../libs/gpt.js'

// 定义消息内容的响应式变量
const messageContent = ref('') 
// 定义是否处于配置状态的响应式变量
const isConfig = ref('') 
// 定义是否正在处理中的响应式变量
const isTalking = ref(false) 

// 点击设置的处理函数
const clickConfig = () => {
    isConfig.value = true;
    messageContent.value = getApiKey() || '';
}

// 发送或保存的处理函数
const sendOrSave = () => {
    if (!messageContent.value.length) return;
    if (isConfig.value) {
        // 保存 API 密钥
        if (saveAPIKey(messageContent.value.trim())) {
            isConfig.value = false;
        }
        messageContent.value = '';
    } else {
        // 发送消息
        sendMessage()
    }
}

// 组件挂载时的处理
onMounted(() => {
    if (getApiKey()) {
        isConfig.value = false
    }
})

// 消息列表的响应式变量
const messageList = ref([
    {
        role:'system',
        content: '你是 人工智能客服,请尽可能简洁地回答问题',
    },
    {
        role: 'assistant',
        content: `你好,我是AI语言模型,我可以提供一些常用服务和信息,例如:

1. 翻译:我可以把中文翻译成英文,英文翻译成中文,还有其他一些语言翻译,比如法语、日语、西班牙语等。

2. 咨询服务:如果你有任何问题需要咨询,例如健康、法律、投资等方面,我可以尽可能为你提供帮助。

3. 闲聊:如果你感到寂寞或无聊,我们可以聊一些有趣的话题,以减轻你的压力。

请告诉我你需要哪方面的帮助,我会根据你的需求给你提供相应的信息和建议。`
    }
])

// 发送消息的异步函数
const sendMessage = async () => {
    const message = messageContent.value.trim();
    try {
        isTalking.value = true;
        messageList.value.push({
            role: 'user',
            content: message
        })

        const data = await chat(messageList.value, getApiKey())
        messageList.value.push({
            role: 'assistant',
            content: data
        })
        messageContent.value = ''
    } catch (e) {

    } finally {
        isTalking.value = false
    }
    isTalking.value = true;
}

// 保存 API 密钥的函数
const saveAPIKey = (apiKey) => {
    localStorage.setItem("apiKey", apiKey);
    return true;
}

// 获取 API 密钥的函数
const getApiKey = () => {
    return localStorage.getItem("apiKey");
}
</script>

<style lang="css" scoped></style>

这段代码是一个 Vue 组件的模板和脚本部分:

  • 模板中包含顶部导航栏、消息显示区域和输入区域。

    • 导航栏显示应用名称和描述,并提供了“设置”按钮。
    • 消息显示区域根据消息的发送者角色(用户或助手)进行布局显示。
    • 输入区域用于输入消息或 API 密钥,并包含保存或发送的操作按钮。
  • 脚本部分使用 ref 定义了一些响应式变量,如 messageContentisConfigisTalking 和 messageList

    • messageContent 用于存储输入的消息或 API 密钥。
    • isConfig 表示是否处于配置 API 密钥的状态。
    • isTalking 表示是否正在处理发送或接收消息。
    • messageList 存储了消息的角色和内容。
  • 定义了多个函数来处理不同的操作,如 clickConfig 处理设置按钮的点击,sendOrSave 处理发送或保存的操作,sendMessage 实际发送消息并处理响应,saveAPIKey 保存 API 密钥到本地存储,getApiKey 从本地存储获取 API 密钥。

例如,当用户点击“设置”按钮时,isConfig 变为 true,输入框变为密码输入模式,并显示已保存的 API 密钥(如果有)。当用户输入消息并按下回车键或点击“保存”按钮时,根据 isConfig 的状态进行保存 API 密钥或发送消息的操作。在发送消息时,会将用户输入添加到 messageList 中,等待服务器响应并将响应内容也添加到 messageList 中。