微信小程序WebSocket实现stream流式聊天对话功能

news2024/11/19 9:32:30

要在微信小程序实现聊天对话功能,回话是流式应答,这里使用了WebSocket技术。WebSocket大家应该都很熟悉,使用wx.connectSocket就可以了。这里可能需要注意下的是流式应答,后端如何发送,前端如何接收。直接上代码:

可以扫码体验:

后端关键代码:

// 定义正则表达式
                    String regex = "data:\\s*(\\{.*\\})";
                    // 创建Pattern对象
                    Pattern pattern = Pattern.compile(regex);

                    String line;
                    while ((line = reader.readLine()) != null) {
                        // 处理每条数据
                        // System.out.println(line);
                        // 创建Matcher对象
                        Matcher matcher = pattern.matcher(line);
                        // 查找匹配项
                        if (matcher.find()) {
                            String dataValue = matcher.group(1);
                            JSONObject jsonObject = JSON.parseObject(dataValue);

                            String content = jsonObject.getString("result");
                            Boolean end = jsonObject.getBoolean("is_end");

                            JSONObject data = new JSONObject();
                            data.put("content", content);
                            data.put("end", end);
                            data.put("type", "message");
                            webSocketServer.sendInfo(uid.toString(), data.toJSONString());
                        }
                    }

小程序ts代码:

data: {
    messages: [],    // 聊天消息列表
    inputValue: '',  // 输入框的值
    ask: '',  // 输入框的值
    socketOpen: false,  // WebSocket 连接状态
    socketTask: null,  // WebSocket 实例
    answering: false, // 回答中。。。
    type: 2,
    credit: 0,
    scrollTop: 0,
  }
scrollToBottom() {
    // 在需要滚动到最底部的时机
    const query = wx.createSelectorQuery();
    query.select('.chat-container').boundingClientRect();
    query.select('.msgList').boundingClientRect();
    query.exec(res => {
      const scorllHeight = res[0].height;
      const listHeight = res[1].height;

      this.setData({
        scrollTop: listHeight - scorllHeight + 92
      });
    });
  },
async onLoad() {
    const chatList = 历史聊天记录;
    const chatListMessage: any = [];
    if (chatList && chatList.length > 0) {
      chatList.map((v: any) => {
        const ask = {
          sender: 'user',
          avatar: '',
          content: v.ask,
          createTime: v.createTime,
          id: v.id,
        };
        const answer = {
          sender: 'chat',
          avatar: 'xxx',
          content: v.answer,
          id: v.id,
        }
        chatListMessage.push(ask);
        chatListMessage.push(answer);
      })
    }
    // 初始化聊天消息列表,包含一条欢迎消息
    const messages: any = [
      {
        sender: 'chat',
        avatar: 'xxx',
        content: `欢迎`
      },
      ...this.data.messages,
      ...chatListMessage
    ]
    // @ts-ignore
    this.setData({ messages });
    this.scrollToBottom();
  },
  //滾動到底部
  bindscroll() {
    // console.log(1);
  },
  onUnload: function () {
    // 页面卸载时关闭 WebSocket 连接
    this.closeSocket();
  },

  inputChange: function (e: any) {
    // 监听输入框值的变化
    this.setData({
      inputValue: e.detail.value
    });
  },

  async sendMessage() {
    // 发送消息
    const message = this.data.inputValue;
    if (message.trim() === '') {
      showToast("请输入问题");
      return;
    }

    

    // 添加用户发送的消息到聊天消息列表
    const newMessage = {
      sender: 'user',
      avatar: '',
      content: message
    };
    //@ts-ignore
    this.data.messages.push(newMessage);

    // 清空输入框
    this.setData({
      messages: this.data.messages,
      inputValue: '',
    });

    this.data.ask = message;
    // 发送消息到 Chat
    this.sendToChat(message);
  },

  sendToChat: function (message: any) {
    if (!this.data.socketOpen) {
      // 如果 WebSocket 连接未打开,则创建连接
      this.createSocket();
    }
    this.setData({ answering: true });

    // 这里请求后台

    // 处理 Chat 的回答消息
    const newMessage: any = {
      sender: 'chat',
      avatar: '',
      content: ""
    };
    //@ts-ignore
    this.data.messages.push(newMessage);
    // 更新聊天消息列表并滚动到最新消息
    this.setData({ messages: this.data.messages });
    this.scrollToBottom();
  },

  createSocket: function () {
    // 创建 WebSocket 连接
    const socketTask = wx.connectSocket({
      url: ``,  // 替换为你的 WebSocket 服务器地址
      success: () => {
        console.log('WebSocket 连接成功');
      },
      fail: (error) => {
        console.error('WebSocket 连接失败', error);
      }
    });

    // 监听 WebSocket 连接打开事件
    socketTask.onOpen(() => {
      console.log('WebSocket 连接已打开');
      this.setData({
        socketOpen: true,
        socketTask: socketTask
      });
    });

    // 监听 WebSocket 接收到服务器的消息事件
    socketTask.onMessage((res: any) => {
      const data = JSON.parse(res.data);
      // console.log(data);
      if (data.type === 'message') {
        // 收到 Chat 的回答消息
        this.handleChatResponse(data);
      }
    });

    // 监听 WebSocket 连接关闭事件
    socketTask.onClose(() => {
      console.log('WebSocket 连接已关闭');
      this.setData({
        socketOpen: false,
        socketTask: null
      });
    });

    // 监听 WebSocket 错误事件
    socketTask.onError((error) => {
      console.error('WebSocket 错误', error);
    });
  },

  closeSocket: function () {
    if (this.data.socketOpen) {
      // 关闭 WebSocket 连接
      this.data.socketTask.close();
    }
  },

  handleChatResponse: async function (data: any) {

    // 处理 Chat 的回答消息
    const index = this.data.messages.length - 1;
    this.data.messages[index].content += data.content;
    // 更新聊天消息列表并滚动到最新消息
    this.setData({ messages: this.data.messages });

    if (data.end) {
      this.setData({ answering: false, messages: this.data.messages });
      this.data.ask = "";
    };

    this.scrollToBottom();
  },

可以扫码体验:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1059514.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【1】c++设计模式——>UML类图的画法

UML介绍 UML:unified modeling language 统一建模语言 面向对象设计主要就是使用UML类图,类图用于描述系统中所包含的类以及他们之间的相互关系,帮助人们简化对系统的理解,他是系统分析和设计阶段的重要产物,也是系统编码和测试的…

小程序 用户反馈 与 客服对话 使用说明

在开发小程序时,通过翻阅官方文档,会发现 button 的 open-type 属性有很多值可以选。因此,我们就可以实现相应的按钮功能。 微信开发文档-表单组件-buttonhttps://developers.weixin.qq.com/miniprogram/dev/component/button.html contact…

嵌入式学习笔记(44)S5PV210的SD卡启动实战

8.5.1任务:大于16KB的bin文件使用SD卡启动 (1)总体思路:将我们的代码分为2部分,第一部分BL1小于等于16KB,第二部分为任意大小,iROM代码执行完成后从SD卡启动会自动读取BL1到iRAM中执行;BL1执行时负责初始化…

ChatGPT启蒙之旅:弟弟妹妹的关键概念入门

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

腾讯云服务器哪个配置比较值得?

腾讯云服务器哪款配置比较好值得买?轻量应用服务器性价比值得买,轻量2核2G3M带宽95元一年、2核4G5M带宽218元一年、2核2G4M带宽三年540元一年、4核8G12M配置446元一年、8核16G18M带宽1668元15个月、16核32G28M轻量服务器3468元15个月。腾讯活动入口&…

tiny模式基本原理整合

【Tiny模式】的基本构成 M【首头在首位】 U【/】 V【HTTP/】 Host H【真实ip】 XH \r回车 \n换行 \t制表 \ 空格 一个基本的模式构成 [method] [uri] [version]\r\nHost: [host]\r\n[method] [uri] [version]\r\nHost: [host]\r\n 检测顺序 http M H XH 有些地区 XH H M 我这边…

lenovo联想台式机 拯救者 刃7000-28ICBR(90KX)原装出厂Windows10系统镜像

LENOVO联想拯救者(90KX)原厂WIN10系统 下载链接:https://pan.baidu.com/s/1beocPJSmnFbY4Y_ZQM2djA?pwd4d1n 系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件、联想电脑管家等预装程序 所需要工具:16G或以上的U盘 文件格式:ISO 文件大…

华为云云耀云服务器L实例评测|云耀云服务器L实例部署ZFile在线网盘服务

华为云云耀云服务器L实例评测|云耀云服务器L实例部署ZFile在线网盘服务 一、云耀云服务器L实例介绍1.1 云耀云服务器L实例简介1.2 云耀云服务器L实例特点 二、ZFile介绍2.1 ZFile简介2.2 ZFile特点 三、本次实践介绍3.1 本次实践简介3.2 本次环境规划 四、购买华为云…

《幸福之路》罗素(读书笔记)

目录 作者简介 作者的感悟 经典摘录 一、不幸福的成因 1、一部分要归咎于社会制度 2、一部分则得归咎于个人心理——当然,你可以说个人心理是社会制度的产物。 二、欠缺某些想要的东西,是快乐的必要条件 三、无聊与刺激 四、现代人的精神疲劳 五…

word已排序好的参考文献,插入新的参考文献,序号更新

原排序好的文献序号。 现在在3号后面插入一个新文献。4,5号应该成为5,6 这时在3号后面,回车,就会自动的增长。如下图: 但是如果手滑,把[4]删除了如何排序?? 如下图: …

基于Java的医院药品管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

聊天记录一句一句出现的视频制作,制作抖音聊天记录视频教程

聊天记录情感中视频制作工具是一款专注于将聊天记录转化为抖音视频的工具。它可以将平淡的聊天截图转化为生动有趣的视频,让你的回忆变得更加具有观赏性和情感共鸣。 首先,聊天记录一句一句出现的视频制作功能是该工具的一大特点。通过这个功能&#xf…

应力分析概要

1.概述 应力分析是一种用于结构件寿命分析的方法,最早的应用场景可能是路桥,因为西方提前我们两百年以上进入大工业时代。许多人工建筑的寿命是有限的,这类实际需求催生出寿命预测和诊断。结构件的失效,最根本的因素是因为应力的…

基于Matlab求解高教社杯全国大学生数学建模竞赛(CUMCM2004A题)-奥运会临时超市网点设计(附上源码+数据)

文章目录 题目思路源码数据下载 题目 2008年北京奥运会的建设工作已经进入全面设计和实施阶段。奥运会期间,在比赛主场馆的周边地区需要建设由小型商亭构建的临时商业网点,称为迷你超市(Mini Supermarket, 以下记做MS)网&#xf…

mybatis项目启动报错:reader entry: ���� = v

问题再现 解决方案一 由于指定的VFS没有找,mybatis启用了默认的DefaultVFS,然后由于DefaultVFS的内部逻辑,从而导致了reader entry乱码。 去掉mybatis配置文件中关于别名的配置,然后在mapper.xml文件中使用完整的类名。 待删除的…

排序---P1781 宇宙总统

思路: 当我们要对这些超大数进行比较排序时,如果我们用int或long基本数据类型时,会超出能承载的范围,因此我们选择用引用数据类型:BigDecimal或BigInteger。 区别在于基本数据类型直接比较大小,而是调用这…

平面图—简单应用

平面图:若一个图𝐺能画在平面𝑆上,且使𝐺的边仅在端点处相交,则称图𝐺为可嵌入平面𝑆,𝐺称为可平面图,简称为平面图。 欧拉公式:设有…

机器学习笔记 - 深入研究spaCy库及其使用技巧

一、简述 spaCy 是一个用于 Python 中高级自然语言处理的开源库。它专为生产用途而设计,这意味着它不仅功能强大,而且快速高效。spaCy 在学术界和工业界广泛用于各种 NLP 任务,例如标记化、词性标注、命名实体识别等。 安装,这里使用阿里的源。 pip install spacy…

Arcgis小技巧【14】——拓扑(Topology)的方方面面

在ArcGIS中,拓扑是定义点要素、线要素以及面要素共享重叠几何的方式的排列布置。 简单来说,我们可以将拓扑理解各类要素的地理空间关系,如重叠、相交、相连等。 拓扑的主要功能就是用于保证数据质量,当然它还有其它很多功能&…

【物联网】浅谈单片机中的看门狗

STM32看门狗是一种重要的系统保护机制,能够监控系统的运行状态并在故障时自动重启。它在各个领域都有广泛的应用,如工业自动化、通信设备和汽车电子等。通过配置和控制看门狗定时器,我们可以提高系统的稳定性和可靠性。在实际应用中&#xff…