123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- <template>
- <div style="width:1000px; margin: auto;">
- <el-row>
- <el-col :span="18">
- <div class="chat-window-wrapper" ref="chatWindowWrapper">
- <el-card class="chat-window" ref="chatWindow">
- <div v-for="(message, index) in messages" :key="index" class="message">
- <img
- :src="message.sender === 'user' ? require('@/assets/search/soldier.png') : require('@/assets/search/robot.png')"
- alt="avatar"
- class="avatar"
- />
- <div :class="['bubble', message.sender === 'user' ? 'user-bubble' : message.sender === 'ai' ? 'ai-bubble' : 'system-bubble']">
- {{ message.content }}
- <el-button v-if="message.sender === 'system' && requestError" size="mini" type="text" @click="retry(message.oldMsg)" style="margin-left:10px;width:80px"> 重 试</el-button>
- </div>
- </div>
- <div v-show="isWaitingForResponse" class="response-indicator" ref="aiBubble">
- <img :src="require('@/assets/search/robot.png')" alt="avatar" class="avatar" />
- <div class="loader"></div>
- </div>
- </el-card>
- </div>
- <div class="input-area">
- <el-input v-model="inputMessage" type="textarea" placeholder="输入您的消息..." style="margin:5px" :disabled="isWaitingForResponse"
- @keyup.enter.native="sendMessage(null)"></el-input>
- </div>
- </el-col>
- <el-col :span="6">
- <el-card class="chat-msg">
- <!-- <p v-html="dict.type.show_msg[0]?dict.type.show_msg[0].raw.remark:''"/> -->
- <li><span style="color:red">故障原因</span>:为什么xxxxx;xxxxx是什么原因;</li>
- <li><span style="color:red">故障影响</span>:xxxx有什么后果;xxxx有什么影响;xxxx会怎么样;xxxx会造成什么</li>
- <li><span style="color:red">组成</span>:xxxx有什么零件;xxxx由什么组成;xxxx包含什么</li>
- <li><span style="color:red">维修方法</span>:xxxx怎么修;xxxx处理方法;xxxx怎么解决</li>
- <li><span style="color:red">检测工具</span>:xxxx的检测工具;xxxx的测试工具;xxxx怎么诊断;</li>
- <li><span style="color:red">部件故障</span>:xxxx有什么故障;xxxx会有什么问题</li>
- </el-card>
- </el-col>
- </el-row>
- </div>
- </template>
-
- <script>
- import { question } from "@/api/knowledge/search";
- export default {
- name: 'question',
- dicts: ['show_msg'],
- data() {
- return {
- inputMessage: "",
- messages: [],
- requestError: false,
- isWaitingForResponse: false,
- hint: "",
- };
- },
- mounted(){
- this.hint = this.getHint();
- },
- methods: {
- getHint(){
- let showMsgs = this.dict.type.show_msg;
- for(let showMsg of showMsgs) {
- if(showMsg.value == "qa_msg"){
- return showMsg.raw.remark
- }
- }
- },
- sendMessage(msg) {
- let inputMessage = msg ? msg :this.inputMessage.trim()
- if (!inputMessage) return;
- // this.isWaitingForResponse = true;
- if(!msg){
- this.messages.push({
- sender: "user",
- content: inputMessage,
- });
- }
- // 获取最后一行的焦点
- const aiBubbles = this.$refs.aiBubble;
- aiBubbles.focus();
- let oldMsg = inputMessage;
- this.scrollToBottom();
- question(inputMessage).then(resp => {
- this.messages.push({
- sender: "ai",
- content: resp.data,
- });
- this.scrollToBottom();
- this.isWaitingForResponse = false;
- }).catch(error => {
- console.info(error)
- this.requestError = true;
- this.messages.push({
- sender: "system",
- content: "系统异常",
- oldMsg,
- });
- this.scrollToBottom();
- this.isWaitingForResponse = false;
- })
- this.inputMessage = "";
- },
- retry(msg) {
- if (this.requestError) {
- this.requestError = false;
- this.messages.pop(); // 移除系统提示消息
- this.sendMessage(msg); // 重新发送
- }
- },
- scrollToBottom() {
- this.$nextTick(() => {
- const chatWindowWrapper = this.$refs.chatWindowWrapper;
- chatWindowWrapper.scrollTop = chatWindowWrapper.scrollHeight;
- });
- },
- },
- };
- </script>
-
- <style scoped>
- .chat-window {
- overflow-y: scroll;
- margin-bottom: 10px;
- border: 0px;
- border-radius: 5px;
- }
- .input-area {
- display: flex;
- }
- .message {
- margin-bottom: 10px;
- }
- .bubble {
- display: inline-block;
- padding: 5px 10px;
- border-radius: 5px;
- font-family: "Courier New", Courier, monospace;
- font-size: 14px;
- line-height: 1.5;
- margin-bottom: 5px;
- /* flex: 1; */
- }
- .message {
- display: flex;
- align-items: flex-start;
- margin-bottom: 10px;
- }
- .avatar {
- width: 32px;
- height: 32px;
- border-radius: 50%;
- margin-right: 8px;
- }
- .user-bubble {
- background-color: #45a1ff;
- color: #fff;
- }
- .ai-bubble {
- background-color: #1a1a1a;
- color: #45a1ff;
- border: 1px solid #45a1ff;
- }
- .el-input {
- flex: 1;
- margin-right: 10px;
- }
- .el-input__inner {
- background-color: #333;
- border-color: #45a1ff;
- color: #45a1ff;
- }
- .el-input__inner::placeholder {
- color: #45a1ff;
- }
- .el-button {
- background-color: #45a1ff;
- border-color: #45a1ff;
- color: #1a1a1a;
- }
- .el-textarea__inner {
- background-color: transparent;
- }
- .response-indicator {
- display: flex;
- align-items: center;
- margin-bottom: 10px;
- }
- .loader {
- border: 2px solid #45a1ff;
- border-top: 2px solid #1a1a1a;
- border-radius: 50%;
- width: 14px;
- height: 14px;
- margin-left: 5px;
- animation: spin 0.8s linear infinite;
- }
- @keyframes spin {
- 0% {
- transform: rotate(0deg);
- }
- 100% {
- transform: rotate(360deg);
- }
- }
- .chat-window-wrapper {
- border: 2px solid #45a1ff;
- height: calc(100vh - 200px);
- /* max-height: 500px; */
- overflow-y: auto;
- }
- .chat-window {
- width: 100%;
- /* min-height: 100%; */
- }
- .chat-msg {
- height: calc(100vh - 200px);
- white-space: pre-wrap;
- margin-left: 5px;
- font-size: 1rem;
- }
- </style>
|