Skip to content

A concise program that can quickly, conveniently, and efficiently facilitate team formation for extracurricular activities, research projects, major assignments, etc.

License

Notifications You must be signed in to change notification settings

akynazh/form-team-talent

Repository files navigation

组队达人 (form-team-talent)

简介

一个简洁的小程序,可以快速,方便,高效地进行课外活动,课题研究,大作业等的组队。

点击查看小程序展示

团队分工情况

  • jzh:40%,后端代码和部分前端代码
  • wfy:30%,界面设计和部分前端代码
  • wyz:30%,负责文档,PPT的编写和部分前端代码

功能设计

每个人都可以通过组队达人创建一个活动,活动可以设置为私有活动或者公共活动,可以指定截止时间和具体内容,其他人可以通过扫描二维码加入活动。

加入活动页面,可以创建自己的小组,小组可以设置人数限制,说明小组的目标,对成员的要求等等。

活动参与者可以申请加入小组,说明自己的情况,以便组长筛选组员,组长同意申请之后就成功加入了小组。

每个人可以编辑自己的具体信息,以便了解和认识其他人。

技术设计

一、后端技术概览:

主要通过 Java 实现,支持通过 Docker 快速部署。使用微信云托管部署服务,使用腾讯云COS(或阿里云OSS)存储静态文件, 通过 Redis 实现缓存,通过 Swagger3 构建 api 文档,通过 ElasticSearch 实现活动搜索功能。

  • SpringBoot 2.7.5
  • Docker & Docker-compose
  • MySQL 5.7.35
  • Redis 3.0.354
  • MybatisPlus
  • Hutool
  • JWT
  • Quartz
  • OkHttp
  • qcloud.cos / aliyun.oss
  • Swagger3
  • ElasticSearch 7.17.3

二、前端技术概览:

主要由 JavaScript 实现。

微信小程序端,通过微信官方API和 Vant Weapp 框架搭建UI。

  • WeChat API
  • Vant Weapp

浏览器端,通过 npm,axios 等进行构建。

三、关键技术点和问题:

1、docker 部署问题

如果不使用 docker-compose 部署服务,只通过 docker 进行部署的话,由于有多个容器需要部署且容器间需要通信,为了正常通信,需要建立桥接网络,通过创建一个 network(默认为 bridge 模式),将两个容器的网络均指定为该 network, 即可让两个容器互通。

对于 mysql 服务所在容器,假如容器名定为 mysqldb,那么在 java 后端配置文件里对应的 mysql 服务的 url 应该指定为 jdbc:mysql://mysqldb/xxxxxxx。这样才能顺利连通 mysql 服务。

当然,假如使用 docker-compose 则没有这个问题了。

2、前后端交互认证问题

微信小程序的认证流程大致是这样的:

P1: 在小程序端向用户申请获得用户信息的权限,用户同意后,微信服务器返回一个 code 授权码,小程序端携带该授权码访问后端认证接口。

P2: 后端通过该授权码访问微信提供的接口服务获得该用户的 openId,接着将 openId 通过 Jwt 进行加密生成 token,放入请求头中返回给小程序端。

P3: 小程序端将 token 存入本地,以后每次需要用户认证的请求都带上该请求头。后端尝试获取请求头中 token,如果 token 不存在或者 token 过期则向小程序端返回 token 失效的错误码。

P4: 如果小程序端收到 token 失效错误码后,则进行 P1 操作。

认证流程图如下所示:

f1

3、关于后端返回的 json 数据

对于一个采用驼峰命名法命名的变量,比如 userId,转换后返回前端的 json 属性名是 userId,没有问题。

但是当变量名为 uId时,转换后则变为 uid,这就产生了问题。我还测试了其它一些变量,如下:

# userId
{"code":200,"msg":"ok","obj":{"userId":"hello"}}
# uId
{"code":200,"msg":"ok","obj":{"uid":"hello"}}
# Id
{"code":200,"msg":"ok","obj":{"id":"hello"}}
# uuId
{"code":200,"msg":"ok","obj":{"uuId":"hello"}}

可见当为 uId 和 Id 时,都会出现问题。

一般可以考虑在后端变量命名时,不让第二个字符大写,或者采用 @JsonProperty("uId") 进行解决。

4. 建立适当的索引

有些索引建立了反而会降低效率,比如写多于读的场景:在本项目中,对于一个加入小组的请求,写入到 t_req 表之后, 撤销请求操作和处理请求操作都可能是较为频繁的,也就是增删行操作较多,可能导致索引频繁地进行重建。

这里对 t_uat 表索引的设计进行说明。

当用户获取自己所加入的活动或小组时,需要根据用户 id 进行查询,所以可以建立用户 id 的索引。

当一个用户申请加入某个小组时,需要查询用户是否已经加入了该小组,但由于用户不能加入同一活动下的其它小组,所以只需要根据用户 id,活动 id 进行查询即可,可以用这两者建立一个联合索引:CREATE INDEX t_uat_idx_join ON t_uat(a_id, u_id);

同时,有了这个索引,当要查询某个活动所含小组时,无需再建立 活动 id 的索引,因为 mysql 当前使用默认引擎为 innodb,索引底层数据结构为 B+ 树,根据 B+ 树的最左匹配原则,使用该索引可以命中活动 id 对应的条目。

数据库设计

Mysql

ER

  • t_user:用户表,记录用户基本信息,其中,用户 id 为主键。
  • t_activity:活动表,记录活动基本信息,其中,活动 id 为主键,活动创始人 id 外键约束于 t_user。
  • t_team:小组表,记录小组基本信息,其中,小组 id 为主键,隶属活动 id 外键约束于 t_activity,小组创始人 id 外键约束于 t_user。
  • t_uat:参与情况表,记录用户加入小组(活动)情况,其中,id 为主键,用户 id 外键约束于 t_user,活动 id 外键约束于 t_activity,小组 id 外键约束于 t_team。
  • t_req:请求表,记录用户所发送请求,其中,请求 id 为主键,发送者 id 和 目标者 id 外键约束于 t_user,请求对应活动 id 和小组 id 外键约束于 t_activity 和 t_team。

Redis

本项目对用户,活动,小组,请求,参与情况等条目均做了缓存优化。

以用户为例,将用户信息进行缓存,键为 “user:{uId}”,值为经过 Json 序列化的对象字串。

用户每次获取个人信息,都会首先访问 Redis 缓存,如果命中缓存,则将值反序列化后得到对象信息,直接返回。如果用户更新个人信息,则直接删除缓存。

ElasticSearch

本项目针对活动实现了搜索功能,用户可以根据活动名进行模糊搜索活动。

索引名设置为 activity,文档 _id 设置为活动 id。

在进行新增活动时,同时将结果插入到 ElasticSearch 中,删除活动时则同时删除 ElasticSearch。而在更新活动时,仅当活动名发生更改时,对 ElasticSearch 中的对应活动进行更改。查询活动时,将查询所有活动名中含有对应查询字段的活动。

后端开发步骤

application.pub.yaml 重命名为 application.yaml,然后开始编辑。(“xxxxxx...”为需编辑内容)

需要配置的内容:

  • 微信小程序的 appId 和 appSecret
  • 数据库用户和密码
  • 对象存储相关字段
  • 本地静态资源存储位置
  • token 密钥和过期时间(单位:s)
  • redis 基本配置
  • elasticsearch 基本配置
  • 是否开启 swagger (生产环境下建议关闭)

执行 init.sql 初始化数据库,之后即可开始开发。

前端开发步骤

mini-program 为小程序开发目录,后端未使用微信云托管,需通过该文件夹开发。

mini-program-cloud 也为小程序开发目录,若后端使用了微信云托管,需通过该文件夹开发。

cd mini-program # or cd mini-program-cloud
npm install

接着,如果在 mini-program 开发,编辑 app.js,将“xxxxxx”替换为后端服务地址即可。

App({
  globalData: {
    baseUrl: "xxxxxx",
  },
})

如果在 mini-program-cloud 开发,编辑 app.js 如下(先将 app.pub.js 重命名为 app.js):

that.cloud = new wx.cloud.Cloud({
  resourceAppid: 'xxxxxxxxxxxxxxxxxx', // 微信云托管环境所属账号,服务商appid、公众号或小程序appid
  resourceEnv: 'xxxxxxxxxxxxxxxxxx', // 微信云托管的环境ID
})

注:后端 api 地址为 localhost:端口号/swagger-ui/index.html

部署步骤

方法1、通过 docker 部署

docker-compose-pub.yaml 重命名为 docker-compose.yaml,然后编辑数据库密码。

创建 docker-compose.yaml 所涉及到的挂载卷目录,并将 init.sql 放到 /docker/mysql/init 目录下。

接着,编辑配置文件中 mysql 地址如下:

url: jdbc:mysql://mysqldb/form_team_talent?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8

最后,执行 ./publish.sh -u (-u 字段是为了重新生成 jar包)。

方法2、通过微信云托管部署

在数据库界面创建账号(对应数据库用户和密码),进入数据库管理界面,运行数据库初始化脚本 init.sql 即可。

在数据库界面获取数据库内网地址,然后编辑配置文件中 mysql 地址如下:

url: jdbc:mysql://数据库内网地址/form_team_talent?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8

接着进行 ElasticSearch 和 Redis 服务的部署。

最后,重新生成 jar 包,进入服务界面,创建服务,将jar包上传并部署。

测试步骤

  • 可通过 thunder client 进行测试,将 test/api_test_ftt_thunderclient.json 导入即可
  • 可通过 postman 进行测试,将 test/api_test_ftt_postman.json 导入即可

小程序界面展示

主页

个人页

管理页

活动页

小组页

请求

发送加入小组的请求:

处理请求:

联系与交流

Github: akynazh

Mail: akynazh@gmail.com

About

A concise program that can quickly, conveniently, and efficiently facilitate team formation for extracurricular activities, research projects, major assignments, etc.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages