创建一个聊天窗口
先创建一个model.vue 该文件作为弹窗的内容
前端代码如下:
页面部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <template> <div class="model-bg" v-show="show" @mousemove="modelMove" @mouseup="cancelMove"> <div class="model-container"> <div class="model-header" @mousedown="setStartingPoint"> {{ title }} </div> <div class="model-main" ref="box"> <div v-for="(item,i) in list" :key="i" :class="item.id== 2 ? 'atalk' : 'btalk'"> <span>{{ item.content }}</span> </div>
</div> <div></div> <input type="text" v-model="wordone" class="inputword" @keyup.enter="sendmsg1"> <el-button type="primary" round @click="sendmsg1" class="btnsend">发送</el-button> <div class="model-footer"> <el-button round @click="cancel">关闭</el-button> </div> <Loading></Loading>
</div> </div> </template>
|
- 分为两块:
- 上面的 model-main 为聊天信息的内容,其中根据list的id来判断聊天消息在左侧和在右侧
- 下面的 text 为聊天的按钮
js部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| <script>
import Loading from "@/views/loading.vue";
export default { props: { show: { type: Boolean, default: false }, title: { type: String, default: '智能助手' }, }, data() { return { x: 0, y: 0, node: null, isCanMove: false,
list: [ { id: 1, name: '111', content: '你好', }, { id: 2, name: '222', content: '你好👋,我是你的智能小助手', } ], wordone: '', wordtow: '', } }, components: { Loading, }, mounted() { this.node = document.querySelector('.model-container') }, methods: { sendmsg1() { this.list.push({ id: 1, name: 'sigtuna', content: this.wordone }); var $this = this; this.getBotContent($this); console.log(this.wordone); this.wordone = ''; var div = this.$refs.box; setTimeout(() => { div.scrollTop = div.scrollHeight; }, 0) },
getBotContent() { this.bus.$emit("loading", true);
this.$http({ url:"/AiController/query?content="+this.wordone, method:"post" }) .then(res => { console.log(res); if(res.data.code == 200){ var data = res.data.msg; console.log(data); this.list.push({ id: 2, name: 'kanade', content: data }); var div = this.$refs.box; setTimeout(() => { div.scrollTop = div.scrollHeight; }, 0)
} this.bus.$emit("loading", false);
}).catch(err => { this.loading = false; this.$message.error(err.message); }); },
cancel() { this.$emit('cancel') },
submit() { this.$emit('submit') },
setStartingPoint(e) { this.x = e.clientX - this.node.offsetLeft this.y = e.clientY - this.node.offsetTop this.isCanMove = true },
modelMove(e) { if (this.isCanMove) { this.node.style.left = e.clientX - this.x + 'px' this.node.style.top = e.clientY - this.y + 'px' } },
cancelMove() { this.isCanMove = false },
} } </script>
|
点击发送,向后端发送请求,然后更新消息list
css部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| <style scoped> .model-bg { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, .5); z-index: 10; }
.model-container { background: #fff; border-radius: 10px; position: fixed; top: 50%; left: 50%; width: 500px; height: 500px; transform: translate(-50%, -50%); }
.model-header { height: 56px; background: #409EFF; color: #fff; display: flex; align-items: center; justify-content: center; cursor: move; }
.model-footer { display: flex; align-items: center; justify-content: center; height: 57px; border-top: 1px solid #ddd; }
.model-footer button { width: 100px; }
.model-main { width: 500px; height: 300px; overflow : auto; }
.main { height: 85%; overflow: scroll; }
div::-webkit-scrollbar { display: none; }
.atalk { margin: 10px; }
.atalk span { display: inline-block; padding: 3px 10px; border: 1px solid aliceblue; border-radius: 15px; padding: 5px 10px; }
.btalk { text-align: right; margin: 10px; }
.btalk span { display: inline-block; padding: 3px 10px; border: 1px solid aliceblue; border-radius: 15px; }
.sendbox { height: 50px; border-bottom-left-radius: 15px; border-bottom-right-radius: 15px; margin-top: 5px; margin-left: 2%; }
.inputword { outline: none; width: 80%; height: 25px; border-radius: 15px; text-indent: 12px; }
.btnsend { align-items: center; justify-content: center; }</style>
|
通过想后端发送请求,可以实现在线聊天功能,也可以通过接入AI来实现客服对话功能
后代码如下:
service层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| @Service public class ApiService {
@Value("${ai-key}") private String apiKey;
public String query(String queryMessage) { Constants.apiKey = apiKey; try { Generation gen = new Generation(); MessageManager msgManager = new MessageManager(10); Message systemMsg = Message.builder().role(Role.SYSTEM.getValue()).content("你是Hibiki开发的智能助手,你只回答与动漫的问题,不要回答其他问题!").build(); Message userMsg = Message.builder().role(Role.USER.getValue()).content(queryMessage).build(); msgManager.add(systemMsg); msgManager.add(userMsg); QwenParam param = QwenParam.builder().model(Generation.Models.QWEN_TURBO).messages(msgManager.get()).resultFormat(QwenParam.ResultFormat.MESSAGE).build(); GenerationResult result = gen.call(param); GenerationOutput output = result.getOutput(); Message message = output.getChoices().get(0).getMessage(); return message.getContent(); } catch (Exception e) { return "智能助手现在不在线,请稍后再试~"; } } }
|
通过阿里的通义千问大模型,可以实现在线的对话机器人功能
也能自定义模型的回答类型,非常实用
所需的依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.9.1</version> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>dashscope-sdk-java</artifactId> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> </exclusion> </exclusions> <version>2.9.0</version> </dependency>
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.10.0</version> </dependency>
|
其中阿里的sdk会有依赖冲突,exclusion看情况添加
在所需页面里引入弹窗
<template>
<div class="navbar">
<div :style='{ "cursor": "pointer", "margin": "0 5px", "lineHeight": "44px", "color": "#fff" }' class="logout"
@click="diaglog">智能助手</div>
<Model :show="show" @cancel="cancel" @submit="submit"></Model>
</div>
</template>
<script>
import Model from '@/views/model.vue'
export default {
data() {
return {
show: false,
};
},
created() {
},
components: {
Model
},
mounted() {
},
methods: {
cancel() {
// 取消弹窗回调
this.show = false
},
submit() {
// 确认弹窗回调
this.show = false
},
diaglog() {
this.show = true;
},
onLogout() {
let storage = this.$storage
let router = this.$router
storage.clear()
router.replace({
name: "login"
});
},
onIndexTap() {
window.location.href = `${this.$base.indexUrl}`
},
}
};
</script>
<style lang="scss" scoped>
.navbar {}
</style>