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

项目介绍

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

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

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

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

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

视频演示

http://cdn.algbb.cn/School-Partners%E6%BC%94%E7%A4%BA%E8%A7%86%E9%A2%91.mp4

技术选型

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

后端:Node.js + MySql + websocket

其他:七牛云存储

项目功能

小程序端

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

管理端

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

运行截图

1. 主页

2. 个人中心

3. 课程详情

4. 做题练习

5. 学习交流群

6. 聊天室

7. 课程列表

8. 习题列表

9. 排行榜

10. 论坛

11. 活动任务管理

管理端

1. 登录界面

2. 题库管理

3. 修改题库

项目分析

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

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

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

1. 后端部分

  • 数据库部分

    我们将所有的聊天记录存放到一张表上方便管理,因为我们有多个聊天群组,我们该如何区分这些不同的聊天群组呢?答案是,通过room_name来区分,获取聊天记录的时候就直接查询这个群组名即可,这样就不用开很多的表,将不同的群聊记录存放到不同的表中啦!

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

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

  • 后端处理聊天记录的方法。
router.get('/chatlog/:to', async (ctx) => {const to = ctx.params.toconst 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 } = itemresponse[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 } = socketMessageonlineUserSocket[socketId] = wsonlineUserInfo[socketId] = { userName, userAvatar }ws.socketId = socketId
}// 广播消息
const broadcast = (message) => {const { from, userName } = messageObject.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 } = thissocketTask.onMessage(async ({ data }) => {const messageInfo: ReceiveMessageInfo = JSON.parse(data)const { to, messageId, isMyself, userName, userAvatar, currentTime, message } = messageInfoconst 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的方式访问接口添加聊天记录到数据库中。

可以看到我们的聊天记录是分为左边以及右边的,自己发的消息即为右边,我们可以通过简单的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 } = thissocketTask.onClose((msg) => {this.socketTask = nullthis.socketReconnect()console.log('onClose: ', msg)})}handleSocketError(): void {const { socketTask } = thissocketTask.onError(() => {this.socketTask = nullthis.socketReconnect()console.log('Error!')})}

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

  socketConnect() {// 生成随机特有的socketIdthis.generateSocketId()/* 使用then的方法才能正确触发onOpen的方法,暂时不知道原因 */Taro.connectSocket({url: 'ws://localhost:3000',}).then(task => {this.socketTask = taskthis.handleSocketOpen()this.handleSocketMessage()this.handleSocketClose()this.handleSocketError()})}socketReconnect(): void {this.isReconnected = trueclearTimeout(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栏

实现起来比较简单,首先定义一个变量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,将持续更新项目!

猛戳~

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

  1. 小程序源码:可以刷短视频的去水印工具微信小程序

    这是一个去水印小程序 支持各大平台短视频去水印 支持图集去水印 另外还有一个功能也就相当于抖音一样刷短视频 偷偷告诉你们哟,刷的短视频都是热门小姐姐哟!惊不惊喜意不意外 小程序源码下载地址:  小程序 ...

  2. 【小程序云开发】不用后端也能构建完整的微信小程序

    文章目录 什么是微信小程序云函数 云数据库 HTTP 云函数 定时触发云函数 总结 写在最后 什么是微信小程序云函数 微信小程序云函数是通过微信小程序云开发提供的一种服务器端代码,用于在小程序中进行服 ...

  3. 开发一个可以查询并显示数据库内容的微信小程序

    使用微信开发者工具可以创建云数据库,并通过代码可以查询并在客户端显示数据库的内容. 附:小程序一个功能页面有wxml(客户端呈现),js(功能函数),json,wxss(个性化处理),这些是局部的文件 ...

  4. Taro 小程序开发大型实战(六):尝鲜微信小程序云(上篇)

    欢迎继续阅读<Taro 小程序开发大型实战>系列,前情回顾: 熟悉的 React,熟悉的 Hooks[1]:我们用 React 和 Hooks 实现了一个非常简单的添加帖子的原型 多页面跳 ...

  5. 王者级微信小程序开发实战教学 从零到高手搭建微信小程序框架开发教程

    王者级微信小程序开发实战教学 从零到高手搭建微信小程序框架开发教程 小程序进阶 王者级微信小程序开发实战教学课程,讲师手把手对同学们进行微信小程序开发的进阶实战,从零开始搭建,从本地到云端开始系统化的 ...

  6. PySide是Python语言的Qt框架的一个绑定。PySide支持跨平台和本地GUI应用程序开发,是在Python 2.6、2.7和3.x版本下可用。

    PySide是Python语言的Qt框架的一个绑定.PySide支持跨平台和本地GUI应用程序开发,是在Python 2.6.2.7和3.x版本下可用. 在开始使用PySide之前,需要在你的机器上安 ...

  7. Taro 小程序开发大型实战(七):尝鲜微信小程序云(下篇)

    欢迎继续阅读<Taro 小程序开发大型实战>系列,前情回顾: 熟悉的 React,熟悉的 Hooks:我们用 React 和 Hooks 实现了一个非常简单的添加帖子的原型 多页面跳转和 ...

  8. 肝了两周,我做了一个面试刷题小程序

    大家好,我是poetry.过年放假那段时间没有回去过年,终于有了自己一整块时间做点自己喜欢的事情,大概花了两周时间开发完一个面试刷题小程序的全部功能,今天终于将它上线跟大家见面了. 市面上很多刷题小程 ...

  9. web开发作品演示之每天都要上报体温微信小程序

    一.项目来源 2020年疫情的到来,使得很多学校对学生的身体健康更加关注,因此每天学校都要收集学生体温数据,以便做好疫情防控工作.在我们学校,体温收集工作需要经过很多人收集,比如学生A要把体温报给学生 ...

最新文章

  1. 校验正确获取对象或者数组的属性方法(babel-plugin-idx/_.get)
  2. 全局函数(直接使用)
  3. Java语言实现二分查找(可查询重复数据)
  4. 数据库索引的实现原理及查询优化
  5. EF Core 2.0使用MsSql/Mysql实现DB First和Code First
  6. 阿里云峰会|数据库也能自动驾驶?DAS全天候给你保驾护航!
  7. python中集合运算_入门 | 一文带你了解Python集合与基本的集合运算
  8. 经典面试题(12):关于事件循环,以下代码将输出什么?
  9. 对于小波分解和傅立叶分解的理解
  10. linux diff 远程文件,登录diff命令,以单独的文件输出在linux
  11. java许愿墙_18.JavaScript实现许愿墙效果
  12. python爬虫(四)_urllib2库的基本使用
  13. 2021年行政区划代码(含经纬度)mysql库
  14. 西工大第三届“探索·解密”趣味密码比赛-个人WriteUp
  15. Excel公式不自动计算出结果
  16. iOS10 更新后问题,获取相册,录音时候闪退问题
  17. 去银行当程序员是一种什么体验
  18. 服务器蓝屏显示7f,电脑蓝屏代码7f怎么解决 如何处理电脑蓝屏代码7f
  19. 第十七届智能车竞赛英飞凌 | 逐飞联合直播-平衡单车组入门讲解
  20. (翻译)如何提示用户密码已变更

热门文章

  1. 如何在网页中用上自己下载的字体
  2. KubeFATE 部署多集群联邦学习平台 FATE
  3. [渝粤教育] 西南交通大学 体育健康课程Ⅰ—奥运裁判带你学规则 参考 资料
  4. Learning TypeScript 0x3 面向对象编程
  5. 凡客第二春 垂死挣扎还是绝地反击
  6. Linux网络编程——Unix本地套接字
  7. DecimalFormat使用心得
  8. 教育邮箱怎么申请?教育邮箱怎么登录?
  9. Kubernetes 中的 Secret加密存储
  10. 患者到医院看病事件模拟(c++)