【vue】仿微信对话

第一部分:下拉刷新

我这里就把主要的下拉刷新的写一下,上拉是一样的道理,就不写了

       <div class="talk_top" ref="listWrapper" id="listWrapper">
            <div class="loadingpic" v-loading="loading"></div>
            <div v-for="message in messages" :key="message.id" class="message">
                <div class="minetext" v-html="message.text"></div>
            </div>
          </div>
<script>
export default {
     data() {
        return {
              loading: false, // 加载中
              messages:[],
        }
     },
     mounted() {
       this.$nextTick(() => {
           this.getAiLogsByTopicId(); // 初始化数据
           this.re();
        });
      },
      methods: {
//这是放在mounted中获取初始数据
   getAiLogsByTopicId() {
      this.$axios
        .get("/userApp/ai/getAiLogsByTopicId", {
          params: {
            TopicId: this.topic.topicId,
            pageNum: 1,
            pageSize: this.page.pageSize
          }
        })
        .then(res => {
          if (res.code === 200) {
            this.messages = res.rows.reverse();
            // console.log(res.rows);
            this.total = Number(res.total);
          }
        });
    },
   //放在re()里面的数据接口
   getlist() {
     if (this.total >= this.messages.length) {
        this.page.pageNum++;
        this.loading = true;
        this.$axios
          .get("/userApp/ai/getAiLogsByTopicId", {
            params: {
              TopicId: this.topic.topicId,
              pageNum: this.page.pageNum,
              pageSize: this.page.pageSize
            }
          })
          .then(res => {
            if (res.code === 200) {
              if (this.page.pageNum >= Number(res.allPage)) {
                this.$message.success("数据到底啦");
                this.loading = false;
                return;
              } else {
                this.messages = [...res.rows.reverse(), ...this.messages];
                this.total = Number(res.total);
                // console.log(this.messages);
                this.loading = false;
              }
            }
          })
          .catch(error => {
            this.$message.error(error.msg);
            this.loading = false;
          });
      } else {
        this.$message.success("数据到底啦");
        // this.showdown = true;
        this.loading = false;
      }
    },
           // 下拉、上拉刷新
    re() {
      var flag = false;
      var PstartX;
      var PstartY;
      var PMoveX;
      var PMoveY;
      var PendX;
      var PendY;
      let that = this;
      document.onmousedown = function(ev) {
        flag = true;
        PstartX = ev.pageX;
        PstartY = ev.pageY;
        // console.log("start:" + PstartX, PstartY);
        document.onmousemove = function(ev) {
          PMoveX = ev.pageX;
          PMoveY = ev.pageY;
          if (flag) {
            // console.log("move:" + PMoveX, PMoveY);
            var resutl = getpostion(PMoveY, PstartY);
            switch (resutl) {
              case 0:
                // console.log("无操作");
                break;
              case 1:
                // console.log("向上");
                break;
              case 2:
                // console.log("向下");
                if (PMoveY - PstartY > 0) {
                  if (PMoveY - PstartY >= 50) {
                    document.getElementById("listWrapper").style.marginTop =
                      PMoveY - PstartY + "px";
                  }
                  that.loading = true;
                  // document.getElementById("loadingpic").style.display = "block";
                }
                break;
            }
          }
        };
        document.onmouseup = function(ev) {
          flag = false;
          PendX = ev.pageX;
          PendY = ev.pageY;
          // console.log("end:" + PendX, PendY);
          var resutl = getpostion(PMoveY, PstartY);
          switch (resutl) {
            case 0:
              // console.log("无操作");
              break;
            case 1:
              // console.log("向上");
              break;
            case 2:
              // console.log("向下");
              // location.reload();
              setTimeout(() => {
                that.getlist(); //调用接口
                //回弹到初始位置
                document.getElementById("listWrapper").style.marginTop = "0px";
              }, 500);
              break;
          }
        };
        // 判断是上拉还是下拉
        function getpostion(PMoveY, PstartY) {
          if (PMoveY - PstartY == 0) {
            return 0; //无操作
          }
          if (PMoveY - PstartY < 0) {
            return 1; //向上
          }
          if (PMoveY - PstartY > 0) {
            return 2; //向下
          }
        }
      };
    },
      }
}
</script>

在他的基础上修改了一下,他的上面有点小问题https://www.cnblogs.com/zmcxsf/p/10443189.html

第二部分:滚动条到底部

1、调用接口数据,然后调用re()方法,如果不调用re方法,页面没反应

2、在 mounted中获取滚动区域的document,然后让调用方法,让盒子滚动到底部,这样页面一打开,滚动条就在底部了

3、监听滚动事件,判断用户滚动状态

<template>
  <div class="chat">
    <div class="center">
      <div v-if="pasId === 0">
        <div class="talk_history" id="chat">
          <div class="talk_top" ref="listWrapper" id="listWrapper">
            <div class="loadingpic" v-loading="loading"></div>
            <div v-for="message in messages" :key="message.id" class="message">
             。。。。内容
            </div>
          </div>
        </div>
        <div class="talk_huifu">
          <div style="border-bottom:1px solid #f8f8f8;display:flex">
            <el-upload
              ref="upload"
              class="upload-demo"
              action="https://jsonplaceholder.typicode.com/posts/"
              :show-file-list="false"
              :file-list="fileList"
              accept=".pdf"
              :on-change="talkchange"
              :http-request="http"
            >
              <img
                style="margin:0 15px 0 10px"
                src="../../assets/img/wenjianjia.png"
                title="发送文件"
              />
            </el-upload>
          </div>
          <div align="right">
            <el-input
              type="textarea"
              v-model="talk"
              :maxlength="4000"
              :rows="3"
              resize="none"
              placeholder="有什么我可以帮您?"
            ></el-input>
            <el-button size="medium" :disabled="disabled" @click="sub(0)"
              >发送</el-button
            >
          </div>
        </div>
      </div>
  </div>
</template>

<script>
let source = null;
var AIurl = "http://192.168.4.172:8081/userApp/ai/sse";
var resultUrl = "http://192.168.4.172:8081/userApp/ai/aiHelp";

import { EventSourcePolyfill } from "event-source-polyfill";
export default {
  layout: "AI2",
  name: "",
  data() {
    return {
      disabled: false, //ai回答结束,按钮取消禁用
      showdown: false, //数据到底啦
      chatContent: null,
      isScrolling: true,
      loading: false, // 加载中
      page: 1,
      total: 0, //总条数
      
      talk: "", //发送的聊天信息
      len: true, //发送信息的次数
      fileList: [], //发送文件
      topic: {}, //新建对话的信息
      word: {}, //文件的信息
      messages: [], //聊天历史
      page: {
        pageNum: 0,
        pageSize: 10
      },
      total: 0,

      pasId: 0, //上一页的id
    };
  },
  mounted() {
      this.getAiLogsByTopicId(); // 初始化数据
      this.re();
      setTimeout(() => {
        this.chatContent = document.getElementsByClassName("talk_top")[0];
        this.scrollToBottom();
        // 监听滚动事件,判断用户滚动状态
        this.chatContent.addEventListener("scroll", this.handleScroll);
      }, 1000);
  },
  watch: {
    disabled: {
      handler(newval, oldval) {
        this.disabled = newval;
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    // 定义将滚动条定位在底部的方法
    scrollToBottom() {
      var that = this;
      this.$nextTick(() => {
        if (that.isScrolling) {
          that.chatContent.scrollTop =
            that.chatContent.scrollHeight - that.chatContent.offsetHeight;
          // console.log(that.chatContent.scrollTop);
        }
      });
    },
    handleScroll() {
      const scrollContainer = this.chatContent;
      const scrollTop = scrollContainer.scrollTop;
      const scrollHeight = scrollContainer.scrollHeight;
      const offsetHeight = scrollContainer.offsetHeight;

      if (scrollTop + offsetHeight < scrollHeight) {
        // 用户开始滚动并在最底部之上,取消保持在最底部的效果
        this.isScrolling = true;
      } else {
        // 用户停止滚动并滚动到最底部,开启保持到最底部的效果
        this.isScrolling = false;
      }
    },
    
    // 发送对话---------------------------------------------------
    // 加载数据对话
    getAiLogsByTopicId() {
      this.$axios
        .get("/userApp/ai/getAiLogsByTopicId", {
          params: {
            TopicId: this.topic.topicId,
            pageNum: 1,
            pageSize: this.page.pageSize
          }
        })
        .then(res => {
          if (res.code === 200) {
            this.messages = res.rows.reverse();
            // console.log(res.rows);
            this.total = Number(res.total);
          }
        });
    },
    getlist() {
      if (this.total >= this.messages.length) {
        this.page.pageNum++;
        this.loading = true;
        this.$axios
          .get("/userApp/ai/getAiLogsByTopicId", {
            params: {
              TopicId: this.topic.topicId,
              pageNum: this.page.pageNum,
              pageSize: this.page.pageSize
            }
          })
          .then(res => {
            if (res.code === 200) {
              if (this.page.pageNum >= Number(res.allPage)) {
                this.$message.success("数据到底啦");
                this.loading = false;
                return;
              } else {
                this.messages = [...res.rows.reverse(), ...this.messages];
                this.total = Number(res.total);
                // console.log(this.messages);
                this.loading = false;
              }
            }
          })
          .catch(error => {
            this.$message.error(error.msg);
            this.loading = false;
          });
      } else {
        this.$message.success("数据到底啦");
        // this.showdown = true;
        this.loading = false;
      }
    },
    // 下拉、上拉刷新
    re() {
      var flag = false;
      var PstartX;
      var PstartY;
      var PMoveX;
      var PMoveY;
      var PendX;
      var PendY;
      let that = this;
      document.onmousedown = function(ev) {
        flag = true;
        PstartX = ev.pageX;
        PstartY = ev.pageY;
        // console.log("start:" + PstartX, PstartY);
        document.onmousemove = function(ev) {
          PMoveX = ev.pageX;
          PMoveY = ev.pageY;
          if (flag) {
            // console.log("move:" + PMoveX, PMoveY);
            var resutl = getpostion(PMoveY, PstartY);
            switch (resutl) {
              case 0:
                // console.log("无操作");
                break;
              case 1:
                // console.log("向上");
                break;
              case 2:
                // console.log("向下");
                if (PMoveY - PstartY > 0) {
                  if (PMoveY - PstartY >= 50) {
                    document.getElementById("listWrapper").style.marginTop =
                      PMoveY - PstartY + "px";
                  }
                  that.loading = true;
                  // document.getElementById("loadingpic").style.display = "block";
                }
                break;
            }
          }
        };
        document.onmouseup = function(ev) {
          flag = false;
          PendX = ev.pageX;
          PendY = ev.pageY;
          // console.log("end:" + PendX, PendY);
          var resutl = getpostion(PMoveY, PstartY);
          switch (resutl) {
            case 0:
              // console.log("无操作");
              break;
            case 1:
              // console.log("向上");
              break;
            case 2:
              // console.log("向下");
              // location.reload();
              setTimeout(() => {
                that.getlist(); //调用接口
                //回弹到初始位置
                document.getElementById("listWrapper").style.marginTop = "0px";
              }, 500);
              break;
          }
        };
        // 判断是上拉还是下拉
        function getpostion(PMoveY, PstartY) {
          if (PMoveY - PstartY == 0) {
            return 0; //无操作
          }
          if (PMoveY - PstartY < 0) {
            return 1; //向上
          }
          if (PMoveY - PstartY > 0) {
            return 2; //向下
          }
        }
      };
    },
    
    sub(type) {
      let that = this;
      // 判断次数,在发送
      if (type === 1) {
        this.messages.push({
          aiId: "", //编号
          userId: "", //用户id
          userAsk: "", //用户询问
          aiReply: "", //ai回复
          askTime: "", //询问时间
          isPdf: true, //是否是pdf
          fileName: this.word.fileName, //文件名称
          fileSize: this.word.fileSize, //文件大小
          aiTopicId: this.topic.topicId //话题编号
        });
        this.$message.success("请稍等,正在响应中");
        this.load(this.messages[this.messages.length - 1], 1, that.chatContent);//调用接口
         setTimeout(() => {
            that.chatContent.scrollTop = that.chatContent.scrollHeight + 150;
          }, 500);
        this.word = {};
      } else {
        if (this.talk === "") {
          this.$message.error("请填写内容");
        } else {
          this.messages.push({
            aiId: "", //编号
            userId: "", //用户id
            userAsk: this.talk, //用户询问
            aiReply: "", //ai回复
            askTime: "", //询问时间
            isPdf: false, //是否是pdf
            fileName: null, //文件名称
            fileSize: null, //文件大小
            aiTopicId: this.topic.topicId //话题编号
          });
          this.$message.success("请稍等,正在响应中");
          this.load(
            this.messages[this.messages.length - 1],
            0,
            that.chatContent
          );
           setTimeout(() => {
            that.chatContent.scrollTop = that.chatContent.scrollHeight + 150;
          }, 500);
        }
        this.talk = "";
      }
    },
    // 获取ai结果
    load(item, type, chatContent) {
      this.disabled = true;
      if (type === 1) {
        source = new EventSourcePolyfill(
          Url +
            "userApp/ai/sse?question=" +
            this.word.fileDownloadPath +
            "&fileName=" +
            this.word.fileName +
            "&fileSize=" +
            this.word.fileSize +
            "&isPdf=true&aiTopicId=" +
            this.topic.topicId,
          {
            headers: {
              token: this.$cookies.get("userToken")
            }
          }
        );
      } else {
        source = new EventSourcePolyfill(
          Url +
            "userApp/ai/sse?question=" +
            this.talk +
            "&isPdf=false&aiTopicId=" +
            this.topic.topicId,
          {
            headers: {
              token: this.$cookies.get("userToken")
            }
          }
        );
      }
      // open:订阅成功(和后端连接成功)
      source.addEventListener("open", function(e) {});
      source.onmessage = e => {
        // console.log(JSON.parse(e.data));
        if (JSON.parse(e.data).end) {
          // 结束了
          item.aiId = JSON.parse(e.data).end;
          this.disabled = false;
          return;
        } else if (JSON.parse(e.data).error) {
          this.$message.error(JSON.parse(e.data).error);
          this.disabled = false;
          return;
        } else {
          item.aiReply += JSON.parse(e.data).content.replace(/\\n/g, "\n");
          if (this.isScrolling) {
            chatContent.scrollTop = chatContent.scrollHeight;
          }
        }
      };
      source.onerror = event => {
        if (event.error !== undefined) {
          this.$message.error("出错了,请联系客服人员");
        }
        this.disabled = false;
        event.target.close();
      };
    },
    // 上传文件
    talkchange(file, fileList) {
      this.$refs.upload.uploadFiles = [];
      this.fileList = [];
      this.fileList = fileList;
    },
    async http(file, fileList) {
      var formData = new FormData();
      formData.append("files", file.file);
      this.$axios.post("/dev/file/uploadFile", formData).then(res => {
        if (res.code === 200) {
          this.word = {
            fileName: res.data[0].fileName,
            fileSize: res.data[0].fileSize,
            fileDownloadPath: res.data[0].fileDownloadPath
          };
          // this.$message.success("上传成功");
          this.sub(1);
        }
      });
    },
  }
};
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值