目录
一、效果展示
二、项目概述
三、手把手快速搭建实现本项目
3.1 前端实现
3.2 后端方向
五、后续开发操持
一、效果展示
默认展示
一般对话展示:
代码对话展示:
二、项目概述
本项目是一个基于Web的智能对话服务平台,通过后端与第三方AI公司的API接口对接,为前端用户提供了一个简洁、直观的聊天界面。该项目的核心代价在于其便捷性与普适性,让用户可以或许轻松接入高质量的AI对话服务,无论是寻求信息咨询、娱乐互动,还是感情伴随,都能得到即时响应与个性化体验。
技能模块:
1.前端:接纳Vue框架+elementUi框架+HTML本地存储信息
2.后端:接纳SpringBoot框架举行数据响应
三、手把手快速搭建实现本项目
3.1 前端实现
前置预备工作:创建一个新的Vue模板,并导入axios
导入elementUI
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 = false
- Vue.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) => {
- // 设置身份为AI
- this.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, // 将端口设置为你想要的端口号
- },
- };
复制代码 运行:在控制台启动步调
打开欣赏器:前端的配置改为(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:这里填写自己申请的APIKEY
- MessageManager 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 {
- @Autowired
- AICHAT 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部署到服务器上
.......
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |