创建一个聊天窗口

先创建一个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";//引用loading组件

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 = '';
// console.log(this.list)
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

<!--GSON -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java -->
<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>

<!--ok http client-->
<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>