使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序项目介绍当代大学生上课缺少积极性,学习缺乏效率。同为大学生的我深有体会。所以特别开发出这样一款学习类的微信小程序帮助学生进行学习、巩固知识,同时增加对战PK模块来加强学生们的学习积极性。这是一个为学生提供在线学习课程、题库练习、考试答题、做题PK、上课签到、资料查阅、成绩分析等功能的微信小程序希望大佬们走过路过给个star~技术选型前端:Taro+微信小程序+Echarts后端:…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

本项目小程序端采用Taro技术框架,可将React代码编译为微信小程序、安卓APP、IOS程序、H5页面等,管理端采用React Hook + TypeScript来进行开发

项目介绍

当代大学生上课缺少积极性,学习缺乏效率。同为大学生的我深有体会。所以特别开发出这样一款学习类的微信小程序帮助学生进行学习、巩固知识,同时增加对战PK模块来加强学生们的学习积极性。这是一个为学生提供在线学习课程、题库练习、考试答题、做题PK、上课签到、资料查阅、成绩分析等功能的微信小程序!

目前因学业任务比较重,没有好好的完善,目前小程序端比较完善的只有习题,课程,论坛,聊天室。管理端也开始进行开发了,现在完成了题库管理,新增题库,修改题库以及登录的功能

希望大佬们走过路过可以给个star鼓励一下感激不尽

https://github.com/zhcxk1998/School-Partners

这个是小程序后台管理端的介绍文章
后台管理端介绍文章,使劲戳!

视频演示

技术选型

前端:Taro + 微信小程序 + Echarts

后端:Node.js + MySql + websocket

其他:七牛云存储

项目功能

小程序端

  1. 在线学习课程
  2. 专项题库练习
  3. 课程考试答题
  4. 知识趣味竞赛
  5. 上课签到系统
  6. 专业资料查阅
  7. 学生成绩分析
  8. 活动日程安排
  9. 学习分享论坛

管理端

  1. 登录注册
  2. 题库管理

运行截图

1. 主页

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

2. 个人中心

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

3. 课程详情

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

4. 做题练习

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

5. 学习交流群

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

6. 聊天室

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

7. 课程列表

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

8. 习题列表

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

9. 排行榜

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

10. 论坛

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

11. 活动任务管理

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

管理端

1. 登录界面

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

2. 题库管理

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

3. 修改题库

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

项目分析

项目采用前后端分离的技术,前端采用了Taro微信小程序框架,因为本人比较喜欢React,所以采用了Taro这款类React语法的框架,后端则采用了Node.js,koa2框架。聊天室页面采用websocket来进行连接

今天,我们首先来聊一聊聊天室使用的小技巧(并不)

首先我们的后端数据库采用的是mysql,我们建了一个聊天记录的表(萌新勿喷~)

1. 后端部分

  • 数据库部分
    使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序
    我们将所有的聊天记录存放到一张表上方便管理,因为我们有多个聊天群组,我们该如何区分这些不同的聊天群组呢?答案是,通过room_name来区分,获取聊天记录的时候就直接查询这个群组名即可,这样就不用开很多的表,将不同的群聊记录存放到不同的表中啦!

同时因为我们的聊天记录内需要存储emoji等信息,所以,我们需要将数据库的字符集调整为utf8mb4 -- UTF-8 Unicode,排序规则选择utf8mb4_unicode_ci,这个可以通过自行百度,或者navicat中设置。

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

然后我们将数据表以及字段类型也设置为utf8mb4,便于存储emoji信息

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

  • 后端处理聊天记录的方法。
router.get('/chatlog/:to', async (ctx) => { 
   
  const to = ctx.params.to
  const response = []
  const res = await query(`SELECT * FROM chatlog WHERE room_name = '${ 
     to}' ORDER BY current_time DESC`);
  res.map((item, index) => { 
   
    const { 
    room_name, user_name, user_avatar, current_time, message } = item
    response[index] = { 
   
      to: room_name,
      userName: user_name,
      userAvatar: user_avatar,
      currentTime: formatTime(current_time),
      message,
      messageId: `msg${ 
     current_time}${ 
     Math.ceil(Math.random() * 100)}`
    }
  })
  ctx.response.body = parse(response)
})

这是获取指定群聊的后端接口,to代表的是群组名,使用get的方法即可获取到指定群聊的聊天记录啦!

继续聊聊我们如何为所有连接到聊天室的网友们发送信息,这里我们采用的是广播的方式,不同于socket.io内已经封装好广播的方法,小程序规定只能使用websocket,所以我粗略的封装了一下广播(十分丑陋的代码)

let onlineUserSocket = { 
   }
let onlineUserInfo = { 
   }

const handleLogin = (ws, socketMessage) => { 
   
  const { 
    socketId, userName, userAvatar } = socketMessage
  onlineUserSocket[socketId] = ws
  onlineUserInfo[socketId] = { 
    userName, userAvatar }
  ws.socketId = socketId
}

// 广播消息
const broadcast = (message) => { 
   
  const { 
    from, userName } = message
  Object.values(onlineUserSocket).forEach((socket) => { 
   
    socket.send(JSON.stringify({ 
   
      ...message,
      isMyself: userName === onlineUserInfo[socket.socketId].userName
    }))
  })
}

我们再登录的时候,就将前端传来的消息存入对象中,以及他的socket对象,然后广播的时候就可以遍历所有的socket对象,为所有在线用户广播消息,其中的isMyself代表的是否为本人,例如我发的消息,自己的socket对象接受广播的时候就是true。别人的就是false,这样做是为了方便区分,自己的聊天消息和被人的聊天消息


2. 前端部分

接下来聊聊前端的聊天室部分

handleSocketMessage(): void { 
   
    const { 
    socketTask } = this
    socketTask.onMessage(async ({ 
    data }) => { 
   
      const messageInfo: ReceiveMessageInfo = JSON.parse(data)
      const { 
    to, messageId, isMyself, userName, userAvatar, currentTime, message } = messageInfo
      const time: string = formatTime(currentTime)

      this.messageList[to].push({ 
   
        ...messageInfo,
        currentTime: time
      })
      /* 设置群组最新消息 */
      this.contactsList.filter(contacts => contacts.contactsId === to)[0].latestMessage = { 
   
        userName, message, currentTime: time
      }
      this.scrollViewId = isMyself ? messageId : ''
      await Taro.request({ 
   
        url: 'http://localhost:3000/chatlog',
        method: 'PUT',
        data: { 
   
          to,
          userName,
          userAvatar,
          currentTime,
          message,
        }
      })
    })
  }

我们先接受消息,然后先更新指定群组名的聊天群组的聊天记录,然后再使用PUT的方式访问接口添加聊天记录到数据库中。

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

可以看到我们的聊天记录是分为左边以及右边的,自己发的消息即为右边,我们可以通过简单的flex布局来实现

// 这里是覆盖默认样式,显示自己消息的样式
.myself {
  justify-content: flex-end;

  .avatar {
    order: 1;
  }

  .info {
    display: flex;
    flex-direction: column;
    align-items: flex-end;

    .header {
      justify-content: flex-end;

      .username {
        order: 1;
        margin-right: 0 !important;
        margin-left: .5em;
      }
    }

    .content {
      color: #333 !important;
      border: #e7e7e7 1px solid;
      background: #fff !important;
      box-shadow: 0 8px 20px -8px #d7d7d7;
    }
  }
}

// 以下是默认样式,就是左边的样式
.message-wrap {
  display: flex;
  margin: 20px 0;

  .avatar {
    width: 14vw;
    height: 14vw;
    margin: 10px;
    border-radius: 50%;
    background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
  }

  .info {

    .header {
      display: flex;
      align-items: center;
      max-width: 40vw;
      padding: 10px 0;
      color: #666;
      font-size: .8em;

      .username {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        max-width: 40vw;
        margin-right: .5em;
        color: #555;
        font-size: 1.2em;
        font-weight: bold;
      }
    }

    .content {
      display: inline-block;
      max-width: 60vw;
      padding: 10px 20px;
      color: #fff;
      word-break: break-all;
      border-radius: 20px;
      background: #66a6ff;
    }
  }
}

最后我们聊一下websocket的断线重连

  handleSocketClose(): void { 
   
    const { 
    socketTask } = this
    socketTask.onClose((msg) => { 
   
      this.socketTask = null
      this.socketReconnect()
      console.log('onClose: ', msg)
    })
  }

  handleSocketError(): void { 
   
    const { 
    socketTask } = this
    socketTask.onError(() => { 
   
      this.socketTask = null
      this.socketReconnect()
      console.log('Error!')
    })
  }

我们这里先监听一下websocket关闭或者异常的情况,调用重连方法,以及清空socketTask的对象,接下来是重连的方法

  socketConnect() { 
   
    // 生成随机特有的socketId
    this.generateSocketId()

    /* 使用then的方法才能正确触发onOpen的方法,暂时不知道原因 */
    Taro.connectSocket({ 
   
      url: 'ws://localhost:3000',
    }).then(task => { 
   
      this.socketTask = task
      this.handleSocketOpen()
      this.handleSocketMessage()
      this.handleSocketClose()
      this.handleSocketError()
    })
  }

  socketReconnect(): void { 
   
    this.isReconnected = true
    clearTimeout(this.timer)

    /* 3s延迟重连,减轻压力 */
    this.timer = setTimeout(() => { 
   
      this.socketConnect()
    }, 3000)
  }

我们每三秒调用一遍socket连接的方法,重新再设置好socketId,以及socketTask,重新监听各种方法。这里有一个奇特的地方,就是Taro的connectSocket方法,不能使用async/await的方法来获取socketTask,也就是说不能这样const socketTask = await Taro.connectSocket({...})来获取socketTask,只能通过then的方法才能获取到,卑微的我暂时不知道如何解决这个问题…

聊天界面中有一个emoji表情的按钮,点击就会弹出emoji栏

使用Taro小程序框架开发一个学习、刷题、论坛、聊天交流的微信小程序

实现起来比较简单,首先定义一个变量emojiOpened来判断用户是否点击emoji按钮,若点击则为输入栏新增一个类名来控制弹出的样式

<View className={`chat-input-container ${emojiOpened ? 'emoji-open' : ''}`}>

同时再scss中设置弹出的样式

.emoji-open {
  transform: translateY(-30vh);
  transition: all .2s ease;
}

...

&-input-container {
    position: fixed;
    left: 0;
    bottom: -30vh;
    width: 100vw;
    height: 40vh;
    background: #fff;
    z-index: 1;
    transition: all .2s ease;
    ...
}

因为在下还只是可怜巴巴的大学生,好多大作业有待完成!具体后续请关注一下我的github,将持续更新项目!

猛戳~

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/188089.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • lua字符串截取_lua删除数组元素

    lua字符串截取_lua删除数组元素localstr=”helloworld!”string.sub(str,1,string.len(str)-1)–hellowordstring.sub(str,起始位置,整个字符串的长度)–获取指定位置长度的字符串string.len(目标字符串)–获取字符串的长度

  • tcp三次握手的seq和ack_tcp三次握手的第一个报文

    tcp三次握手的seq和ack_tcp三次握手的第一个报文TCP(TransmissionControlProtocol)传输控制协议TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:位码即tcp标志位,有6种标示:SYN(synchronous建立联机)ACK(acknowledgement确认)PSH(push传送)FIN(finish结束)RST(reset重置)URG(urgent紧急)Sequ…

  • 动态规划:最长上升子序列(二分算法 nlogn)「建议收藏」

    动态规划:最长上升子序列(二分算法 nlogn)「建议收藏」解题心得:1、在数据量比较大的时候n^2会明显超时,所以可以使用nlogn的算法,此算法少了双重循环,用的lower_bound(二分法)。2、lis中的数字并没有意义,仅仅是找到最小点lis[0]和最大点lis[len],其中,在大于lis[len]时len++,在小于lis[len]时可以将arr[i]在lis中的数进行替换掉。所以此算法主要是在不停的找最合适的起点和最合适的终点。

  • 关于浏览器报错:stack overflow at line: 0 的解决法

    关于浏览器报错:stack overflow at line: 0 的解决法本文主要是从程序猿的角度进行分析的,致力于提供解决问题的思路,而不是盲目的从网上百度关于页面错误:stackoverflowatline:0 很明白,就是堆栈的溢出!所以,导致的原因也很清楚,无非就是页面中出现了类似于递归式的无线循环而导致的,所以可能出现的原因就很明晰了:1.浏览器对图片,js等引用进入了无线循环这时候出错的原因,无非是图片路径不正确或者引用多个相同的js…

  • Java异常Error和Exception的区别「建议收藏」

    Java异常Error和Exception的区别「建议收藏」异常发生的原因有很多,通常包含以下几大类:用户输入了非法数据。要打开的文件不存在。网络通信时连接中断,或者JVM内存溢出。这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。-要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个

  • docker导出镜像命令_docker批量导出镜像

    docker导出镜像命令_docker批量导出镜像docker导出镜像docker导出镜像使用dockersave命令,可以使用dockersave–help查看用法为dcokersave[镜像名]:[TAG]-o[保存后文件名]-o,–output#输出为文件,后跟保存后的文件名[TAG]可以通过dockerimages查看示例…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号