对接阿里云通义千问的流数据展示到聊天框

<template>
  <div class="content">
    <div class="message_content">
      <div class="message_title" style="position: relative;">
        <span>消息区</span>
        <i class="el-icon-close" @click="close"  style="cursor: pointer;position: absolute;top: 15px;right: 10px;font-size: 25px;"></i>
      </div>
      <!-- 消息区 -->
      <div class="message_area" ref="chatWindow">
        <div
          class="message_item"
          :style="{
            justifyContent: item.name == '张三' ? 'flex-end' : 'flex-start',
          }"
          v-for="(item, index) in messageList"
          :key="index"
        >
          <div class="avator" v-if="item.name != '张三'">
            <img src="xxx/avator.png" alt="" />
          </div>
          <div class="">
            <div class="name">{{ item.name }}</div>
            <div
              class="message"
              :class="{
                message_right: item.name == '张三',
                message_left: item.name != '张三',
              }"
            >
             <div v-html="item.content"></div>
            </div>
          </div>
          <div class="avator" v-if="item.name == '张三'">
            <img src="xxx/avator.png" alt="" />
          </div>
        </div>
      </div>
      <div class="message_input">
        <el-input
          type="textarea"
          v-model="textarea"
          autofocus
          :autosize="{ minRows: 7, maxRows: 7 }"
          resize="none"
          @keyup.enter="keyDown($event)"
        >
        </el-input>
        <div
          style="
            width: 100%;
            display: flex;
            align-items: center;
            justify-content: flex-end;
            height: 60px;
          "
        >
          <el-button @click="send">发送</el-button>
        </div>
      </div>
    </div>
  </div>
</template>
 
<script>
import { fetchEventSource } from '@microsoft/fetch-event-source';
import {
    getToken
  } from "@/utils/auth";
import axios from 'axios';
export default {
  data() {
    return {
      textarea: "",
      messageList: [

      ],
    };
  },
  watch: {},
  mounted() {
    // window.addEventListener("keydown", this.keyDowns);
  },
  methods: {
    /* 回车发送消息 */
    // keyDowns(e) {
    //   if (e.key == "Enter") {
    //     this.send();
    //     e.preventDefault(); // 去掉默认的换行
    //   }
    // },
    close(){
      this.$parent.closeMsg();
    },
    /* 点击发送消息 */
    async send() {
      console.log('[[[[]]]]')
      if (!this.textarea) return;
      this.messageList.push({
        name: "张三",
        content: this.textarea,
        time: this.formatDate(new Date()),
      });
      console.log(this.messageList);
      let url = 'you url'
      let apikey ='your apikey'
        const data = {
          "inputs": {
            "token":'Bearer ' + getToken(),
          },
          "query": this.textarea,
          "response_mode": 'streaming',//"blocking",
          "conversation_id": "",
          "user": this.$store.state.user.user.userId,
      };
      let that= this
      // this.textarea = "";
      // const response = await axios({
      //       method: 'post',
      //       url: url,
      //       data:data,
      //       // responseType: 'stream',
      //       headers: { 'Authorization': 'Bearer ' + apikey ,  'Content-Type': 'application/json'}
      //   });
      // this.messageList.push({
      //   name: "李四",
      //   content: response.data.answer,
      //   time: this.formatDate(new Date()),
      // });
      // this.scrollToBottom();
      // console.log(response,'---')

      // return
      let fullContent =''
      let eventSource =fetchEventSource(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            Accept: "text/event-stream",
            Authorization: `Bearer ${apikey}`,
            "Transfer-Encoding": "chunked",
        },
        body: JSON.stringify(data),
        // signal: cancelTokenSourceRef.current.signal,
        onopen(response) {
            // 建立连接
            console.log(response, "open");
            if (response.ok) {
               console.log("成功建立连接");
               that.messageList .push({
                  name: "李四",
                  content:'',
                  time: that.formatDate(new Date()),
                }
                );
            } else {
              throw new Error(JSON.stringify(response));
            }
          },
        onmessage(ev) {
            console.log('Received message:', ev.data);
            if(JSON.parse(ev.data).message == 'close'){
              eventSource.close()
            }else{
              let str = ev.data
              const obj = JSON.parse(str);
              const newContent = obj.answer || '';
              fullContent += newContent
              if (that.messageList.length > 0) {
                  that.messageList[that.messageList.length - 1].content = fullContent;
              }
            }
        },
        onclose() {
          console.log("连接关闭");
        },
        onerror(error) {
            console.log("关闭链接", error);
            throw Error(error);
        },
        openWhenHidden: true, // 实时通知
        
    });
    this.textarea = "";
    },
    /* 滚动到底部  永远保持显示最新消息 */
    scrollToBottom() {
      // 使用setTimeout确保DOM更新完成
      setTimeout(() => {
        this.$refs.chatWindow.scrollTop = this.$refs.chatWindow.scrollHeight;
      }, 0);
    },
    /* 时间格式化 */
    formatDate(date) {
      const d = new Date(date);
      let month = "" + (d.getMonth() + 1);
      let day = "" + d.getDate();
      let hour = "" + d.getHours();
      let minute = "" + d.getMinutes();
      let second = "" + d.getSeconds();
      let year = d.getFullYear();
 
      if (month.length < 2) month = "0" + month;
      if (day.length < 2) day = "0" + day;
      if (hour.length < 2) hour = "0" + hour;
      if (minute.length < 2) minute = "0" + minute;
      if (second.length < 2) second = "0" + second;
 
      return (
        [year, month, day].join("-") + " " + [hour, minute, second].join(":")
      );
    },
  },
  beforeDestroy() {
    window.addEventListener("keydown", this.keyDowns);
  },
};
</script>
 
<style lang="scss" scoped>
::v-deep .el-textarea {
  height: calc(100% - 60px);
}
 
::v-deep .el-textarea__inner {
  height: 105px !important;
  color: #fff;
  min-height: 105px !important;
  background-color: transparent;
  border: 0;
}
 
::v-deep ::-webkit-scrollbar {
  background-color: transparent !important;
}
 
.message_left {
  border-top-right-radius: 5px;
  border-bottom-left-radius: 5px;
  border-bottom-right-radius: 5px;
}
.message_right {
  border-top-left-radius: 5px;
  border-bottom-left-radius: 5px;
  border-bottom-right-radius: 5px;
}
 
.content {
  border: 2px solid #26c4d1;
  border-radius: 5px;
  background-color: rgba(13, 26, 42, 0.5);
  box-shadow: 0 0 10px 1px #26c4d1;
  margin-right: 10px;
  width: 100%;
  height: 600px;
  overflow-y: auto;
  display: flex;
 
  .message_content {
    width: 38%;
  }
  .message_content {
    width:100%;
    height: 100%;
    border-radius: 5px;
    box-shadow: 0 0 5px 1px #89d8f0;
    background-color: rgba(66, 86, 94, 0.2);
 
    .message_title {
      height: 50px;
      line-height: 50px;
      color: #50d7d3;
      text-align: center;
      background-color: #174670;
    }
 
    .message_area {
      width: 100%;
      height: calc(100% - 223px);
      overflow-y: auto;
 
      .message_item {
        display: flex;
        justify-content: flex-end;
        margin: 5px 0;
 
        .avator {
          width: 40px;
          height: 40px;
          border-radius: 50%;
          margin-right: 10px;
          margin-left: 10px;
 
          img {
            display: block;
            width: 100%;
            height: 100%;
          }
        }
 
        .name {
          color: #67798e;
        }
 
        .message {
          color: #71acbd;
          padding: 5px;
          background-color: #1f3144;
          border: 1px solid #71acbd;
        }
      }
    }
 
    .message_input {
      // border: 1px solid #3e5a77;
      margin: 5px auto 0 auto;
      width: 96%;
      height: 165px;
      border-radius: 5px;
      box-shadow: 0 0 5px 1px #89d8f0;
      background-color: rgba(97, 156, 180, 0.2);
    }
  }
}
 
::v-deep .el-button {
  color: #fff;
  border-radius: 5px;
  border: 1px solid #43a0a8;
  background-image: linear-gradient(to bottom, #15263b, #238298);
  margin-right: 10px;
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值