Skip to content

详细设计文档

tootal edited this page Jun 23, 2021 · 2 revisions

2021年5月

实现一个在线编程笔试平台项目

任务分块

前端功能分块

前端需要完成的静态页面有:

(1) 首页欢迎界面;

(2) 登录/注册页面;

(3) 候选人/面试官面试界面(包括实时聊天界面、代码编辑器界面以及题目发送/接收界面);

(4) 发起/接收面试界面;

(5) 数据库题库界面;

(6) 题库修改/添加界面;

(7) 个人信息(如密码)修改界面;

(8) 其他功能界面(如设置界面,用于清除localstorage)

前端需要完成的主要功能模块有:

(1) 登录注册与注销功能:可以实现注册、登录与注销;同时实现持久化登录。

(2) 实时聊天界面以及消息发送与接收功能:实现消息的发送与接收,发出以及接收的消息页及时存储在远程数据库以及本地。

(3) 个人信息的配置功能:可以配置个人信息,由于不需要太多的信息,这里只设计了修改密码。

(4) 面试发起/接收功能:可以在面试发起/接收界面,面试官/候选人可以发起/(接收或拒绝)面试邀请。

(5) 题库功能:可以通过该界面增删改查数据库保存的题库中的题目;

(6) 实时聊天功能:实现实时聊天页面,用户能够通过访问数据库并同步到本地存储获取该面试聊天信息,候选人和面试官可实时文字聊天,其他获得链接的人都可参与文字聊天;当有人员进入/离开面试页面时,会自动发出提醒;同时记录聊天人数;

(7) 在线编程功能:提供代码编辑器monaco-editor,实现了切换语言和切换编辑器风格;编辑器支持代码补全、高亮等基本功能;同时支持候选人/面试官协同编辑。

(8) 题目发送接收功能: 提供富文本编辑器Tinymce,支持富文本格式编写和显示;

(9) 代码提交及代码运行功能:在线编程模块支持运行Javascript代码,候选人和面试官可在线运行代码并查看输出。

后台功能分块

通讯模块

实时聊天、代码同步以及题目发送采用websocket实现,后台需要提供的通讯板块需要实现的功能包括但不限于:

(1) 能够生成并辨别不同的面试id,根据面试id将发送方的信息发送到获得面试链接并进入面试界面的用户;

(2) 为了能够使得代码同步及时,需要将发送方发送给接收方的消息进行及时转发。

(3) 统计每个面试链接实时聊天的人数并发送到对应的接收方;

(4) 后台根据每个面试的hashid存储进入该面试的用户websocket连接,每当一个用户发送消息时,根据面试的hashid对应的连接分发给其他也在该面试中的用户。

面试id生成(用于拼接面试url)

若面试id直接使用数据库递增的id,与“获得面试链接的人即可参与聊天”需求结合会产生安全风险(意味着可以随机进入其它面试来聊天)。因此需要一种新的面试id方案,需要满足以下特点:

  • 唯一。不同面试要有不同的id。
  • 简短。面试id要用在url中用于分享,不能太长。
  • 不可枚举。无法通过简单的规律遍历所有id。
  • 生成算法简单通用,易于实现。

使用hashids,对面试id进行重构,重构后的hashid满足上述要求,通过相关接口返回到前端。

后台websocket服务器根据面试id分发前端面试题目,编辑器和实时聊天的信息

后台根据每个面试的hashid存储进入该面试的用户websocket连接,每当一个用户发送消息时,根据面试的hashid对应的连接分发给其他也在该面试中的用户。

具体逻辑如下:

面试id字典 interviewId => array of {connect, uid}

连接结构体

let conObj = {

 uid: obj.uid,

 con: connect,

};

用户进入面试链接,发送type为open的含有面试hashid和用户id的jsonstr,查找是否已有这个hashid的websocket连接,

  • 有则判断该数组中是否存在某个连接结构体,其用户id和该信息的用户id相同,有则重复连接,打印错误信息,无则push一个包含用户id和当前连接的一个结构体到该数组;
  • 无则,赋值一个数组,数组的0号元素是conObj

如果是type为close的消息,则删除hashid对应的数组中该用户的conObj

如果是普通消息,则遍历hashid对应的conObj数组,给每一个连接发送消息,即广播给其他也在该面试中的用户。

后端接口鉴权

(1) 后端接口采用基于JWT的Token认证机制实现

(2) 使用 express-jwtjson web token

(3) 对于前端发起的请求(除用户登录等少量接口不鉴权外),如果请求头headers里的authorization没有token,则不予返回数据(token可由登录接口获取)

(4) token 使用 id 和 email 生成

分页

参考github文档中后端关于分页的实现;

前端发起请求:

$ curl 'https://api.github.com/user/repos?page=2&per_page=100'

后端在返回相关数据的同时,在响应头中包含1个参数Total-Count,表示总记录数,方便前端进行上下页、第一和最后一页的跳转

数据库表的设计

数据库使用mysql :

(1) user用户表,存储用户id,邮箱email,密码password和昵称name

(2) problem题目表,存储标题,内容,题目创建者id,创建时间和修改时间

(3) interview面试表,存储面试官id,面试者id,开始时间,结束时间和面试状态

(4) answer答案表,存储面试id,问题id,语言,内容,创建时间

(5) comment留言表,存储留言内容,面试id,留言者id,留言时间

关系图(由MYSQL Workbench生成)如下:

后台接口

接口文档 :https://app.swaggerhub.com/apis-docs/tootal/codeview/1.0.0#/

根据接口文档,实现用户、题目、面试、答案、留言模块的接口(包含所有模块的增删查改的接口) 后端使用express,使用router实现路由

后端接口单元测试

(1) 后台接口单元测试使用:

(2) mocha作为测试主体框架,其中supertest负责http请求,should负责断言,判断各种请求的返回结果是否符合实际情况,从而测试接口。

(3) 接口已全部通过测试。

后端服务器实时监听

(1) 使用pm2,用于启动、监控服务器;

(2) 后台代码修改后,原先需要手动关闭后台服务器,然后再重启;

(3) 使用pm2监听后,修改后会自动重启,方便快捷。

技术选型

前端技术选型

前端框架:Vue脚手架+element-plus组件库;vue-cli初始化工程,基于vue3

代码编辑器:使用Monaco Editor

本地存储:localstorage

后台技术选型

后端框架:express框架

通讯服务:websocket

数据库存储:mysql

后端接口单元测试:http测试SuperTest;单元测试框架Mocha;断言库Should;

开发管理

代码管理:github协作开发

原型设计

概况页面原型图

登录界面原型图

注册界面原型图

发送/接收面试邀请界面原型图

创建面试原型图

新建题目原型图

题库界面原型图

题目界面原型图

面试官面试界面原型图

候选人面试界面原型图

项目流程图

下图是整个项目运行的一个流程,用于展示其各个页面之间的联系以及页面本身所具有的功能:

UML图

用例图

用户端用例图

系统端用例图

类图

(由MYSQL Workbench生成)

活动图

登录注册活动图

用户密码修改活动图

新建题目活动图

修改题目活动图

创建面试活动图

用户面试实时聊天活动图

代码协同编程活动图

面试题目发送接收活动图

时序图

登录注册时序图

实时聊天时序图

题目发送-接收时序图

状态图

登录注册状态图

用户密码修改状态图

新建题目状态图

实时聊天状态图

创建面试状态图

修改题目题库状态图

代码协同编程状态图

面试题目发送接收状态图

数据库表设计

用户表

属性 类型 属性描述 备注
id INT(11) 存储用户id 主键
email VARCHAR(100) 邮箱email
password VARCHAR(20) 密码password6.

题目表

属性 类型 属性描述 备注
id INT(11) 题目id 主键
title VARCHAR(100) 存储标题
content TEXT 内容
owner_id INT(11) 题目创建者id 外键
created_at DATATIME 创建时间
updated_at DATATIME 修改时间

答案表

属性 类型 属性描述 备注
id INT(11) 答案id 主键
interview_id INT(11) 存储面试id 外键
problem_id INT(11) 问题id 外键
language ENUM(...) 语言
content TEXT 内容
created_at DATATIME 创建时间

面试表

属性 属性类型 属性描述 备注
id INT(11) 面试记录编号ID 主键
viewer_id INT(11) 面试官账号ID 外键
viewee_id INT(11) 候选人账号ID 外键
start_time DATETIME 面试开始时间
finish_time DATETIME 面试结束时间
status ENUM 面试状态

留言表

属性 属性类型 属性描述 备注
id INT(11) 留言记录ID 主键
content TEXT 留言内容
interview_id INT(11) 面试ID 外键
owner_id INT(11) 留言者id 外键
created_at DATETIME 留言时间

面试题目关系表

属性 属性类型 属性描述 备注
id INT(11) 面试题目ID 主键
problem_id INT(11) 题目ID 外键
interview_id INT(11) 面试ID 外键

接口设计

接口设计详见接口设计文档

Clone this wiki locally