当前位置:   article > 正文

个人开发实现AI套壳网站快速搭建(Vue+elementUI+SpringBoot)_如何做一个ai问答前端网页

如何做一个ai问答前端网页

目录

一、效果展示

二、项目概述

三、手把手快速搭建实现本项目

3.1 前端实现

3.2 后端方向

五、后续开发计划


一、效果展示

默认展示

一般对话展示:

代码对话展示:


二、项目概述

        本项目是一个基于Web的智能对话服务平台,通过后端与第三方AI公司的API接口对接,为前端用户提供了一个简洁、直观的聊天界面。该项目的核心价值在于其便捷性与普适性,让用户能够轻松接入高质量的AI对话服务,无论是寻求信息咨询、娱乐互动,还是情感陪伴,都能获得即时响应与个性化体验。

技术模块:

1.前端:采用Vue框架+elementUi框架+HTML本地存储信息

2.后端:采用SpringBoot框架进行数据响应


三、手把手快速搭建实现本项目

3.1 前端实现

前置准备工作:创建一个新的Vue模板,并导入axios

npm install 'axios'

导入elementUI

npm i element-ui -S

Vue中main.js 进行配置

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import router from './router'
  4. import ElementUI from 'element-ui';
  5. import 'element-ui/lib/theme-chalk/index.css';
  6. Vue.config.productionTip = false
  7. Vue.use(ElementUI);
  8. new Vue({
  9. router,
  10. render: h => h(App)
  11. }).$mount('#app')

本项目为了简单化,将项目整体仅设置为了一个Vue主视图(App.vue)

template:

  1. <template>
  2. <div id="Chat">
  3. <el-container>
  4. <el-aside width="200px">
  5. <!-- 添加导航 -->
  6. <el-row class="tac" >
  7. <el-col :span="12" style="width: 100%;">
  8. <h1>个人工具网站</h1>
  9. <el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose">
  10. <el-submenu index="1">
  11. <template slot="title">
  12. <i class="el-icon-location"></i>
  13. <span>人工智能助手</span>
  14. </template>
  15. <el-menu-item-group>
  16. <el-menu-item index="1-1">通义千问</el-menu-item>
  17. <el-menu-item index="1-2">文言一心</el-menu-item>
  18. <el-menu-item index="1-2">GPT</el-menu-item>
  19. </el-menu-item-group>
  20. </el-submenu>
  21. <el-menu-item index="2">
  22. <i class="el-icon-menu"></i>
  23. <span slot="title">知识星球</span>
  24. </el-menu-item>
  25. <el-menu-item index="3" >
  26. <i class="el-icon-document"></i>
  27. <span slot="title">工具集合</span>
  28. </el-menu-item>
  29. <el-menu-item index="4">
  30. <i class="el-icon-setting"></i>
  31. <span slot="title">素材集合</span>
  32. </el-menu-item>
  33. </el-menu>
  34. </el-col>
  35. </el-row>
  36. </el-aside>
  37. <el-container>
  38. <el-header>
  39. <h3>通义千问-API套壳网站</h3>
  40. </el-header>
  41. <el-main>
  42. <div id="ChatLayOut">
  43. <!-- 对话内容列举 -->
  44. <div v-for="(msg, index) in messages" :key="index" id="ChatBubble">
  45. <img :src="getImageUrl(msg.sender)" id="chatImage">
  46. <!-- <p id="ChatContent">{{ msg.sender }}: {{ msg.content }}</p> -->
  47. <div class="chat-content-wrap">
  48. <!-- 使用预处理后的消息内容 -->
  49. <div v-html="preprocessMessageContent(msg.sender+':'+msg.content) "></div>
  50. </div>
  51. </div>
  52. </div>
  53. </el-main>
  54. <el-footer>
  55. <!-- 使用flex布局使元素水平排列 -->
  56. <div style="display: flex; align-items: center;">
  57. <!-- 将输入框放入表单中 -->
  58. <form @submit.prevent="onFormSubmit" style="margin-left: 30%; width: 500px; margin-right: 10px;">
  59. <el-input id="DialogTextCSS" v-model="message" :placeholder="DialogText" :disabled="flag"
  60. style="flex-grow: 1; "></el-input>
  61. </form>
  62. <!-- 提交按钮 -->
  63. <el-button type="primary" @click="sendMessage" style="width:90px ;">提交</el-button>
  64. <!-- 清空按钮 -->
  65. <el-button type="danger" @click="deleteMessage">清空本地聊天记录</el-button>
  66. </div>
  67. <div>COPYRIGHT: CSDN-ALPHAMILK</div>
  68. <div>version : 测试版</div>
  69. </el-footer>
  70. </el-container>
  71. </el-container>
  72. </div>
  73. </template>

JavaScript:

  1. <script>
  2. import axios from 'axios';
  3. export default {
  4. data() {
  5. return {
  6. message: '',
  7. messages: [],
  8. Identify: '',
  9. senderType: '', // 新增一个变量来标识发送者类型
  10. flag:false,
  11. DialogText:'请您输入内容',
  12. }
  13. },
  14. mounted() {
  15. // 页面加载时从localStorage读取消息
  16. const savedMessages = JSON.parse(localStorage.getItem('messages'));
  17. if(savedMessages===null){
  18. this.messages.push({sender: "AI", content: "欢迎使用通义千问API的套壳网站,请您通过输入内容到下方的文本框并提交即可开启聊天"});
  19. }
  20. if (savedMessages) {
  21. this.messages = savedMessages;
  22. }
  23. },
  24. methods: {
  25. scrollToBottom() {
  26. this.$nextTick(() => {
  27. // 尝试手动触发一次重绘,看是否有助于解决滚动问题
  28. const chatLayout = this.$el.querySelector('#ChatLayOut');
  29. if (chatLayout) {
  30. // 强制浏览器重绘
  31. void chatLayout.offsetHeight;
  32. setTimeout(() => {
  33. console.log('scrollHeight:', chatLayout.scrollHeight);
  34. window.scrollTop = chatLayout.scrollHeight;
  35. console.log('scrollTop after setting:', chatLayout.scrollTop);
  36. }, 100); // 增加延时时间以确保元素尺寸和内容更新完成
  37. }
  38. });
  39. },
  40. sendMessage() {
  41. if (this.message.trim() !== '') {
  42. // 设置身份为用户
  43. this.senderType = '用户';
  44. this.messages.push({sender: this.senderType, content: this.message});
  45. localStorage.setItem('messages', JSON.stringify(this.messages)); // 保存消息到localStorage
  46. //禁用对话框
  47. this.flag = true;
  48. this.DialogText = '请您耐心等待AI的回答';
  49. // //进行滚动操作,滚动到最新消息
  50. // this.scrollToBottom();
  51. // 调用接口获取AI生成的内容
  52. axios.get('http://localhost:8080/Test/Chat',
  53. {
  54. params:{
  55. message : this.message
  56. }
  57. }
  58. ).then((response) => {
  59. // 设置身份为AI
  60. this.senderType = 'AI';
  61. this.messages.push({sender: this.senderType, content: response.data});
  62. localStorage.setItem('messages', JSON.stringify(this.messages));
  63. //解除对话框
  64. this.flag = false;
  65. this.DialogText = '请您输入内容';
  66. });
  67. this.message = ''; // 清空输入框
  68. }else{
  69. alert("输入不能为空噢!");
  70. }
  71. },
  72. deleteMessage(){
  73. localStorage.removeItem("messages");
  74. this.messages = [];
  75. this.messages.push({sender: "AI", content: "欢迎使用通义千问API的套壳网站,请您通过输入内容到下方的文本框并提交即可开启聊天"});
  76. },
  77. getImageUrl(sender) {
  78. if (sender === 'AI') {
  79. return 'https://img.alicdn.com/imgextra/i3/O1CN01sffRIx1nb3dXCKdFC_!!6000000005107-2-tps-1024-1024.png';
  80. } else {
  81. return 'https://bpic.51yuansu.com/pic3/cover/00/94/68/58dcd742dd10d_610.jpg?x-oss-process=image/resize,h_360,m_lfit/sharpen,100';
  82. }
  83. },
  84. onFormSubmit() {
  85. this.sendMessage();
  86. },
  87. preprocessMessageContent(content) {
  88. const codeBlockRegex = /```(.*?)```/gs;
  89. const sortTextRegex = /\*\*(.*?)\*\*/gs;
  90. let tempContent = content.replace(sortTextRegex, `<p class="sort-text">$1</p>`);
  91. let processedContent = tempContent.replace(codeBlockRegex, `<pre class="code-block"><code>$1</code></pre>`);
  92. let segments = processedContent.split(/```.*?```/gs); // 分割代码块
  93. segments = segments.filter(segment => segment.trim());
  94. let finalContent = segments.map((segment) => {
  95. return `<p class="content-common">${segment}</p>`;
  96. }).join('');
  97. return finalContent;
  98. }
  99. },
  100. handleOpen(key, keyPath) {
  101. console.log(key, keyPath);
  102. },
  103. handleClose(key, keyPath) {
  104. console.log(key, keyPath);
  105. }
  106. }
  107. </script>

css:

  1. <style>
  2. .el-header, .el-footer {
  3. background-color: #B3C0D1;
  4. color: #333;
  5. text-align: center;
  6. line-height: 60px;
  7. }
  8. .el-aside {
  9. background-color: #D3DCE6;
  10. color: #333;
  11. text-align: center;
  12. line-height: 200px;
  13. box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
  14. }
  15. .el-main {
  16. background-color: #E9EEF3;
  17. color: #333;
  18. text-align: center;
  19. line-height: 160px;
  20. height: 1000px;
  21. }
  22. body > .el-container {
  23. margin-bottom: 40px;
  24. }
  25. .el-container:nth-child(5) .el-aside,
  26. .el-container:nth-child(6) .el-aside {
  27. line-height: 260px;
  28. }
  29. .el-container:nth-child(7) .el-aside {
  30. line-height: 320px;
  31. }
  32. #ChatBubble{
  33. position: relative;
  34. padding: 10px;
  35. border-radius: 10px;
  36. margin-bottom: 30px;
  37. max-width: 70%;
  38. background-color: white;
  39. line-height: normal;
  40. }
  41. /* 用户和AI的不同样式 */
  42. #ChatBubble.user {
  43. background-color: #E0F2F7; /* 用户气泡颜色 */
  44. float: left;
  45. clear: both;
  46. margin-right: 30px;
  47. }
  48. #ChatBubble.AI {
  49. background-color: #ECEFF1; /* AI气泡颜色 */
  50. float: right;
  51. clear: both;
  52. margin-left: 30px;
  53. }
  54. /* 指向箭头,这里仅示例用户气泡右边的箭头 */
  55. #ChatBubble.user::after {
  56. content: "";
  57. position: absolute;
  58. top: 50%;
  59. right: -15px;
  60. transform: translateY(-50%);
  61. border-style: solid;
  62. border-width: 10px 15px 10px 0;
  63. border-color: transparent #E0F2F7;
  64. }
  65. /* 可能需要清除浮动,避免布局问题 */
  66. #dialog-display::after {
  67. content: "";
  68. display: block;
  69. clear: both;
  70. }
  71. #chatImage{
  72. float: left;
  73. margin-top: 17px;
  74. margin-right: 10px;
  75. height: 30px;
  76. width: 30px;
  77. background-color:#faeeee;
  78. }
  79. #Topic{
  80. background-color: #f6f6fe;
  81. border-radius: 10px;
  82. height: 60px;
  83. }
  84. #chat{
  85. height: 56px;
  86. width: 100%;
  87. background-color: pink;
  88. }
  89. .el-footer{
  90. background-color: #f7f8fc;
  91. }
  92. .el-main{
  93. background-color: #f7f8fc;
  94. }
  95. #ChatContent {
  96. line-height: 1.5; /* 或者根据需要调整 */
  97. padding: 0; /* 取消内边距 */
  98. }
  99. #ChatLayOut{
  100. margin-left: 20%;
  101. }
  102. .el-header{
  103. background-color: #333;
  104. }
  105. h3{
  106. color: #E9EEF3;
  107. }
  108. .el-aside{
  109. background: white;
  110. box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
  111. /* 实现右边border-radi */
  112. border-top-right-radius: 30px;
  113. }
  114. /* 明亮风格的代码块,文字及行号全部左对齐 */
  115. .code-block {
  116. background-color: #f8f8f8; /* 明亮背景 */
  117. color: #333; /* 深色文字 */
  118. font-family: 'Courier New', monospace; /* 适合代码的字体 */
  119. white-space: pre-wrap; /* 保留空格和换行 */
  120. border-radius: 5px; /* 边角圆润 */
  121. overflow-x: auto; /* 横向滚动条,如果需要 */
  122. line-height: 1.5;
  123. padding: 10px;
  124. position: relative; /* 为行号预留位置 */
  125. }
  126. /* 显示所有行的行号,确保向左对齐 */
  127. .code-block::before {
  128. content: counter(line);
  129. counter-increment: line;
  130. position: absolute; /* 行号绝对定位 */
  131. left: 0; /* 行号紧贴左侧 */
  132. margin-left: 15px; /* 与代码内容的距离,可根据需要调整 */
  133. text-align: left; /* 行号左对齐 */
  134. width: 30px; /* 行号宽度 */
  135. color: #666; /* 行号颜色,可调整 */
  136. display: block; /* 每行前面均显示 */
  137. line-height: inherit; /* 继承代码块的行高 */
  138. }
  139. /* 确保代码内容也左对齐 */
  140. .code-block code {
  141. display: block; /* 确保代码块内代码作为独立块显示 */
  142. padding-left: 45px; /* 为代码内容预留行号和额外的间距 */
  143. text-align: left; /* 确保代码文本左对齐 */
  144. }
  145. .content-common {
  146. /* 为普通文本内容定义样式 */
  147. margin-bottom: 10px; /* 示例:增加段落间距 */
  148. line-height: 1.5; /* 示例:调整行高 */
  149. }
  150. .el-col-12 {
  151. width: 100%;
  152. }
  153. .sort-text {
  154. font-weight: bold; /* 设置为粗体 */
  155. text-align: left; /* 文本左对齐 */
  156. line-height: normal; /* 行高设置为正常,确保与未加样式时的文本行高一致 */
  157. }
  158. </style>

最后配置端口为8081(在vue.config.js文件下):

  1. const { defineConfig } = require('@vue/cli-service')
  2. module.exports = {
  3. devServer: {
  4. port: 8081, // 将端口设置为你想要的端口号
  5. },
  6. };

运行:在控制台启动程序

npm run serve

打开浏览器:前端的配置改为(localhost:8081)


3.2 后端方向

创建一个SpringBoot项目

在项目pom.xml文件导入以下依赖:

  1. <!-- https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java -->
  2. <dependency>
  3. <groupId>com.alibaba</groupId>
  4. <artifactId>dashscope-sdk-java</artifactId>
  5. <version>2.8.2</version>
  6. </dependency>
  7. <!--okhttp3 依赖-->
  8. <dependency>
  9. <groupId>com.squareup.okhttp3</groupId>
  10. <artifactId>okhttp</artifactId>
  11. <version>4.9.3</version>
  12. </dependency>

由于后端功能十分简单,仅需要一个Utils和一个Controller即可

Utils:(注意:这里要填自己申请的APIKey(十分简单,一毛钱就能开通))

  1. @Component
  2. public class AICHAT {
  3. public static String callWithMessage(String message)
  4. throws NoApiKeyException, ApiException, InputRequiredException {
  5. Generation gen = new Generation();
  6. Constants.apiKey="xxxxxx";//TODO:这里填写自己申请的APIKEY
  7. MessageManager msgManager = new MessageManager(10);
  8. Message systemMsg =
  9. Message.builder().role(Role.SYSTEM.getValue()).content("You are a helpful assistant.").build();
  10. Message userMsg = Message.builder().role(Role.USER.getValue()).content(message).build();//这里填写对话内容
  11. msgManager.add(systemMsg);
  12. msgManager.add(userMsg);
  13. QwenParam param =
  14. QwenParam.builder().model(Generation.Models.QWEN_TURBO).messages(msgManager.get())
  15. .resultFormat(QwenParam.ResultFormat.MESSAGE)
  16. .topP(0.8)
  17. .enableSearch(true)
  18. .build();
  19. GenerationResult result = gen.call(param);
  20. String Message = extractContentFromResult(result);
  21. System.out.println(Message);
  22. return Message;
  23. }
  24. // 仅获取JSON结果中message字段的信息
  25. public static String extractContentFromResult(GenerationResult result) {
  26. if (result != null && result.getOutput() != null && !result.getOutput().getChoices().isEmpty()) {
  27. Message message = result.getOutput().getChoices().get(0).getMessage();
  28. return message.getContent();
  29. }
  30. return null; // 或者返回一个默认值
  31. }
  32. }

ChatController:

  1. @RestController
  2. @RequestMapping("/Test")
  3. @CrossOrigin
  4. public class ChatController {
  5. @Autowired
  6. AICHAT aichat;
  7. @GetMapping("/Chat")
  8. public String GetParameter(String message) {
  9. try {
  10. if (message != null) {
  11. String AiResponse = null;
  12. try {
  13. AiResponse = aichat.callWithMessage(message);
  14. } catch (ApiException | NoApiKeyException | InputRequiredException e) {
  15. System.out.println(e.getMessage());
  16. }
  17. return AiResponse;
  18. }
  19. } catch (Exception e) {
  20. return "出错了>_<"+e.getMessage();
  21. }
  22. return null;
  23. }
  24. }

 启动(Application):

前后端联调测试:


五、后续开发计划

后续改进计划:

后续将会修改许多的bug,并加入许多新的功能,一步步将其打造成一个能够实现商业化的,满足普通人可以使用的通用网站。关注后即可获取最新的动态

1.加入多个可用个人免费的API,让切换AI模型能够方便快捷

2.加入用户管理,满足以后实现商业化的一步

3.加入动画效果,让聊天更生动

4.加入语音输入功能,与语音输出功能。实现外语教师功能

5.将项目通过nginx部署到服务器上

 .......


本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/874233
推荐阅读
相关标签
  

闽ICP备14008679号