目錄
一、效果展示
二、項目概述
三、手把手快速搭建實現本項目
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 進行配置
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';Vue.config.productionTip = falseVue.use(ElementUI);new Vue({router,render: h => h(App)
}).$mount('#app')
本項目為了簡單化,將項目整體僅設置為了一個Vue主視圖(App.vue)
template:
<template><div id="Chat"><el-container><el-aside width="200px"><!-- 添加導航 --><el-row class="tac" ><el-col :span="12" style="width: 100%;"><h1>個人工具網站</h1><el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"><el-submenu index="1"><template slot="title"><i class="el-icon-location"></i><span>人工智能助手</span></template><el-menu-item-group><el-menu-item index="1-1">通義千問</el-menu-item><el-menu-item index="1-2">文言一心</el-menu-item><el-menu-item index="1-2">GPT</el-menu-item></el-menu-item-group> </el-submenu><el-menu-item index="2"><i class="el-icon-menu"></i><span slot="title">知識星球</span></el-menu-item><el-menu-item index="3" ><i class="el-icon-document"></i><span slot="title">工具集合</span></el-menu-item><el-menu-item index="4"><i class="el-icon-setting"></i><span slot="title">素材集合</span></el-menu-item></el-menu></el-col></el-row></el-aside><el-container><el-header><h3>通義千問-API套殼網站</h3></el-header><el-main><div id="ChatLayOut"><!-- 對話內容列舉 --><div v-for="(msg, index) in messages" :key="index" id="ChatBubble"><img :src="getImageUrl(msg.sender)" id="chatImage"><!-- <p id="ChatContent">{{ msg.sender }}: {{ msg.content }}</p> --><div class="chat-content-wrap"><!-- 使用預處理后的消息內容 --><div v-html="preprocessMessageContent(msg.sender+':'+msg.content) "></div></div></div></div></el-main><el-footer><!-- 使用flex布局使元素水平排列 --><div style="display: flex; align-items: center;"><!-- 將輸入框放入表單中 --><form @submit.prevent="onFormSubmit" style="margin-left: 30%; width: 500px; margin-right: 10px;"><el-input id="DialogTextCSS" v-model="message" :placeholder="DialogText" :disabled="flag"style="flex-grow: 1; "></el-input></form><!-- 提交按鈕 --><el-button type="primary" @click="sendMessage" style="width:90px ;">提交</el-button><!-- 清空按鈕 --><el-button type="danger" @click="deleteMessage">清空本地聊天記錄</el-button></div><div>COPYRIGHT: CSDN-ALPHAMILK</div><div>version : 測試版</div></el-footer></el-container></el-container></div>
</template>
JavaScript:
<script>
import axios from 'axios';export default {data() {return {message: '',messages: [],Identify: '',senderType: '', // 新增一個變量來標識發送者類型flag:false,DialogText:'請您輸入內容',}},mounted() {// 頁面加載時從localStorage讀取消息const savedMessages = JSON.parse(localStorage.getItem('messages'));if(savedMessages===null){this.messages.push({sender: "AI", content: "歡迎使用通義千問API的套殼網站,請您通過輸入內容到下方的文本框并提交即可開啟聊天"});}if (savedMessages) {this.messages = savedMessages;}},methods: {scrollToBottom() {this.$nextTick(() => {// 嘗試手動觸發一次重繪,看是否有助于解決滾動問題const chatLayout = this.$el.querySelector('#ChatLayOut');if (chatLayout) {// 強制瀏覽器重繪void chatLayout.offsetHeight; setTimeout(() => {console.log('scrollHeight:', chatLayout.scrollHeight);window.scrollTop = chatLayout.scrollHeight;console.log('scrollTop after setting:', chatLayout.scrollTop);}, 100); // 增加延時時間以確保元素尺寸和內容更新完成}});
},sendMessage() {if (this.message.trim() !== '') {// 設置身份為用戶this.senderType = '用戶';this.messages.push({sender: this.senderType, content: this.message});localStorage.setItem('messages', JSON.stringify(this.messages)); // 保存消息到localStorage//禁用對話框this.flag = true;this.DialogText = '請您耐心等待AI的回答';// //進行滾動操作,滾動到最新消息// this.scrollToBottom(); // 調用接口獲取AI生成的內容axios.get('http://localhost:8080/Test/Chat',{params:{message : this.message}}).then((response) => {// 設置身份為AIthis.senderType = 'AI';this.messages.push({sender: this.senderType, content: response.data});localStorage.setItem('messages', JSON.stringify(this.messages));//解除對話框this.flag = false;this.DialogText = '請您輸入內容';});this.message = ''; // 清空輸入框}else{alert("輸入不能為空噢!");}},deleteMessage(){localStorage.removeItem("messages");this.messages = [];this.messages.push({sender: "AI", content: "歡迎使用通義千問API的套殼網站,請您通過輸入內容到下方的文本框并提交即可開啟聊天"});},getImageUrl(sender) {if (sender === 'AI') {return 'https://img.alicdn.com/imgextra/i3/O1CN01sffRIx1nb3dXCKdFC_!!6000000005107-2-tps-1024-1024.png';} else {return 'https://bpic.51yuansu.com/pic3/cover/00/94/68/58dcd742dd10d_610.jpg?x-oss-process=image/resize,h_360,m_lfit/sharpen,100';}},onFormSubmit() {this.sendMessage();},preprocessMessageContent(content) {const codeBlockRegex = /```(.*?)```/gs;const sortTextRegex = /\*\*(.*?)\*\*/gs;let tempContent = content.replace(sortTextRegex, `<p class="sort-text">$1</p>`);let processedContent = tempContent.replace(codeBlockRegex, `<pre class="code-block"><code>$1</code></pre>`);let segments = processedContent.split(/```.*?```/gs); // 分割代碼塊segments = segments.filter(segment => segment.trim());let finalContent = segments.map((segment) => {return `<p class="content-common">${segment}</p>`;}).join('');return finalContent;
}},handleOpen(key, keyPath) {console.log(key, keyPath);},handleClose(key, keyPath) {console.log(key, keyPath);}}</script>
css:
<style>.el-header, .el-footer {background-color: #B3C0D1;color: #333;text-align: center;line-height: 60px;}.el-aside {background-color: #D3DCE6;color: #333;text-align: center;line-height: 200px;box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)}.el-main {background-color: #E9EEF3;color: #333;text-align: center;line-height: 160px;height: 1000px;}body > .el-container {margin-bottom: 40px;}.el-container:nth-child(5) .el-aside,.el-container:nth-child(6) .el-aside {line-height: 260px;}.el-container:nth-child(7) .el-aside {line-height: 320px;}#ChatBubble{position: relative;padding: 10px;border-radius: 10px;margin-bottom: 30px;max-width: 70%;background-color: white;line-height: normal;}
/* 用戶和AI的不同樣式 */
#ChatBubble.user {background-color: #E0F2F7; /* 用戶氣泡顏色 */float: left;clear: both;margin-right: 30px;
}#ChatBubble.AI {background-color: #ECEFF1; /* AI氣泡顏色 */float: right;clear: both;margin-left: 30px;
}/* 指向箭頭,這里僅示例用戶氣泡右邊的箭頭 */
#ChatBubble.user::after {content: "";position: absolute;top: 50%;right: -15px;transform: translateY(-50%);border-style: solid;border-width: 10px 15px 10px 0;border-color: transparent #E0F2F7;
}/* 可能需要清除浮動,避免布局問題 */
#dialog-display::after {content: "";display: block;clear: both;
}#chatImage{float: left;margin-top: 17px;margin-right: 10px;height: 30px;width: 30px;background-color:#faeeee;
}#Topic{background-color: #f6f6fe;border-radius: 10px;height: 60px;}#chat{height: 56px;width: 100%;background-color: pink;}
.el-footer{background-color: #f7f8fc;
}
.el-main{background-color: #f7f8fc;
}
#ChatContent { line-height: 1.5; /* 或者根據需要調整 */padding: 0; /* 取消內邊距 */ } #ChatLayOut{margin-left: 20%;
}.el-header{background-color: #333;
}
h3{color: #E9EEF3;
}.el-aside{background: white;box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);/* 實現右邊border-radi */border-top-right-radius: 30px;
}
/* 明亮風格的代碼塊,文字及行號全部左對齊 */
.code-block {background-color: #f8f8f8; /* 明亮背景 */color: #333; /* 深色文字 */font-family: 'Courier New', monospace; /* 適合代碼的字體 */white-space: pre-wrap; /* 保留空格和換行 */border-radius: 5px; /* 邊角圓潤 */overflow-x: auto; /* 橫向滾動條,如果需要 */line-height: 1.5;padding: 10px;position: relative; /* 為行號預留位置 */
}/* 顯示所有行的行號,確保向左對齊 */
.code-block::before {content: counter(line);counter-increment: line;position: absolute; /* 行號絕對定位 */left: 0; /* 行號緊貼左側 */margin-left: 15px; /* 與代碼內容的距離,可根據需要調整 */text-align: left; /* 行號左對齊 */width: 30px; /* 行號寬度 */color: #666; /* 行號顏色,可調整 */display: block; /* 每行前面均顯示 */line-height: inherit; /* 繼承代碼塊的行高 */
}/* 確保代碼內容也左對齊 */
.code-block code {display: block; /* 確保代碼塊內代碼作為獨立塊顯示 */padding-left: 45px; /* 為代碼內容預留行號和額外的間距 */text-align: left; /* 確保代碼文本左對齊 */
}.content-common {/* 為普通文本內容定義樣式 */margin-bottom: 10px; /* 示例:增加段落間距 */line-height: 1.5; /* 示例:調整行高 */
}.el-col-12 {width: 100%;
}.sort-text {font-weight: bold; /* 設置為粗體 */text-align: left; /* 文本左對齊 */line-height: normal; /* 行高設置為正常,確保與未加樣式時的文本行高一致 */
}</style>
最后配置端口為8081(在vue.config.js文件下):
const { defineConfig } = require('@vue/cli-service')
module.exports = {devServer: {port: 8081, // 將端口設置為你想要的端口號},
};
運行:在控制臺啟動程序
npm run serve
打開瀏覽器:前端的配置改為(localhost:8081)
3.2 后端方向
創建一個SpringBoot項目
在項目pom.xml文件導入以下依賴:
<!-- https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java --><dependency><groupId>com.alibaba</groupId><artifactId>dashscope-sdk-java</artifactId><version>2.8.2</version></dependency><!--okhttp3 依賴--><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.3</version></dependency>
由于后端功能十分簡單,僅需要一個Utils和一個Controller即可
Utils:(注意:這里要填自己申請的APIKey(十分簡單,一毛錢就能開通))
@Component
public class AICHAT {public static String callWithMessage(String message)throws NoApiKeyException, ApiException, InputRequiredException {Generation gen = new Generation();Constants.apiKey="xxxxxx";//TODO:這里填寫自己申請的APIKEYMessageManager msgManager = new MessageManager(10);Message systemMsg =Message.builder().role(Role.SYSTEM.getValue()).content("You are a helpful assistant.").build();Message userMsg = Message.builder().role(Role.USER.getValue()).content(message).build();//這里填寫對話內容msgManager.add(systemMsg);msgManager.add(userMsg);QwenParam param =QwenParam.builder().model(Generation.Models.QWEN_TURBO).messages(msgManager.get()).resultFormat(QwenParam.ResultFormat.MESSAGE).topP(0.8).enableSearch(true).build();GenerationResult result = gen.call(param);String Message = extractContentFromResult(result);System.out.println(Message);return Message;}// 僅獲取JSON結果中message字段的信息public static String extractContentFromResult(GenerationResult result) {if (result != null && result.getOutput() != null && !result.getOutput().getChoices().isEmpty()) {Message message = result.getOutput().getChoices().get(0).getMessage();return message.getContent();}return null; // 或者返回一個默認值}}
ChatController:
@RestController
@RequestMapping("/Test")
@CrossOrigin
public class ChatController {@AutowiredAICHAT aichat;@GetMapping("/Chat")public String GetParameter(String message) {try {if (message != null) {String AiResponse = null;try {AiResponse = aichat.callWithMessage(message);} catch (ApiException | NoApiKeyException | InputRequiredException e) {System.out.println(e.getMessage());}return AiResponse;}} catch (Exception e) {return "出錯了>_<"+e.getMessage();}return null;}}
?啟動(Application):
前后端聯調測試:
五、后續開發計劃
后續改進計劃:
后續將會修改許多的bug,并加入許多新的功能,一步步將其打造成一個能夠實現商業化的,滿足普通人可以使用的通用網站。關注后即可獲取最新的動態
1.加入多個可用個人免費的API,讓切換AI模型能夠方便快捷
2.加入用戶管理,滿足以后實現商業化的一步
3.加入動畫效果,讓聊天更生動
4.加入語音輸入功能,與語音輸出功能。實現外語教師功能
5.將項目通過nginx部署到服務器上
?.......