SubQuiz Docs
概述
SubQuiz原为SubIT社团开发的一款智能答题系统,之后该系统将移交北大附中科协,作为北大附中学生刷题练习网站,成为北大附中信息化的一部分。
功能
1.0
题目
题目结构及分类:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|- 学科1
| |- 学科描述
| |- 题目类型1
| | |- 题目类型描述(markdown可选)
| | |- 大题1
| | | |- 大题描述(可选)
| | | |- 权重(学生不可见,用于影响推荐概率)
| | | |- 可见(若不可见则不会被推荐)
| | | |- 小题1
| | | | |- 小题题目描述
| | | | |- 小题类型
| | | | |- 选项(仅单选/多选有选项)
| | | | |- 标准答案(学生作答期间不可见)
| | | | |- 解析(学生作答期间不可见)
| | | | |- 用户答案(作答后)
| | | |- 小题2
| | | |- 小题3
| | |- 大题2
| | | |-...
| | |-...
| |- 题目类型2
| | |- ...
|- 学科2
| |- ...
|-...
即学科->题目类型->大题->小题
其中大题是推荐题目、计算得分、等等的基本单位。
每道小题的类型可以是以下5种之一:
- 单选
- 多选
- 判断
- 填空
- 简答
每道大题有自己独立的图片存储空间,可上传图片并通过markdown语法插入图片
测试
学生可以指定题目数量(大题数量)及学科(可选)开始一次测试,测试开始后,在测试结束并完成判卷前无法再次开始其他测试。
在答题过程中测试会自动保存。
可在答题记录中查看之前的全部测试。
若有未结束的测试可从答题记录中进入或在主页点开始新测试进入。
判卷
客观题(单选、多选、判断)由系统完成,简答和填空会将大题描述、小题描述、标准答案、用户答案合成提示词由大模型进行判卷
推荐
推荐即将全部符合要求的题目(可见、没有做过、学科限制)按“$权重\times错误率\times{random}$”进行排序
其中权重由老师设置,错误率是指该学生对于该题目类型的错误率,学生完成某道大题后按如下公式更新其对于该题目类型的错误率,其中$x$是这道大题的得分率
\[new\leftarrow1-\left(0.95\times\left(1-old\right)+0.05\times{x}\right)\]权限
首先所有权限都分为4级,从低到高依次是:
BANNED
NORMAL
ADMIN
ROOT
权限分为全局权限和学科权限两种,学科权限指某一用户在某一学科的权限
权限更改
若修改某人的全局权限,有如下限制:
- 自己的全局权限不低于
ADMIN
- 若修改他人权限:自己的全局权限高于对方当前(修改前)的全局权限
- 若修改他人权限:自己的全局权限高于目标(修改后)的全局权限
- 若修改自己权限:修改后的权限不高于当前权限
若修改某人的某一学科的权限有如下限制:
- 若自己全局权限不低于
ADMIN
,则修改成功,忽略以下限制 - 自己在该学科的权限不低于
ADMIN
- 若修改他人权限:自己在该学科的权限高于对方当前(修改前)在该学科的权限
- 若修改他人权限:自己在该学科的权限高于目标(修改后)在该学科的权限
- 若修改自己权限:修改后的权限不高于当前权限
权限作用/限制
- 若全局权限为
BANNED
无法进行登陆 - 若全局权限为
ROOT
有权进入终端 - 若全局权限不低于
ADMIN
或在某一学科的权限不低于ADMIN
则有权按上述权限修改规则修改自己/他人的全局权限/学科权限 - 若全局权限不低于
ADMIN
或在某一学科的权限不低于ADMIN
,则有权编辑该学科的信息,包括但不限于学科名称、描述、增/删/改该学科的题目类型、增/删/改该学科下全部题目
2.0
主要调整结构,在学科下增加备课组概念,备课组下有知识点,知识点以树形结构存储,且对深度没有限制。知识点下有题目类型,这部分与1.0版本相同。
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|- 学科1
| |- 学科描述
| |- 备课组1
| | |- 知识点文件夹
| | | |- 知识点文件夹
| | | | |- 知识点1
| | | | |- 知识点2
| | | |- 知识点3
| | | | |- 题目类型1
| | | | | |- 题目类型描述(markdown可选)
| | | | | |- 大题1
| | | | | | |- 大题描述(可选)
| | | | | | |- 权重(学生不可见,用于影响推荐概率)
| | | | | | |- 可见(若不可见则不会被推荐)
| | | | | | |- 小题1
| | | | | | | |- 小题题目描述
| | | | | | | |- 小题类型
| | | | | | | |- 选项(仅单选/多选有选项)
| | | | | | | |- 标准答案(学生作答期间不可见)
| | | | | | | |- 解析(学生作答期间不可见)
| | | | | | | |- 用户答案(作答后)
| | | | | | |- 小题2
| | | | | | |- 小题3
| | | | | |- 大题2
| | | | | | |-...
| | | | | |-...
| | | | |- 题目类型2
| | | | | |- ...
|- 学科2
| |- ...
|-...
开发
项目结构及技术栈
整体采用前后端分离
后端
前端
- 框架: Vue
- 语言: TypeScript+SCSS
- 安卓: Capacitor
开发环境
BOTH
JDK(17或以上,推荐OpenJDK17)
后端
JetBrains IntelliJ Idea
前端
NodeJS
VSCode
Android Studio(仅安卓端构建需要)
构建&部署
前期准备
域名/服务器购买备案等这里不再赘述
若将前后端部署在同一域名下,则需要2个域名,例如cdn.bdfzscc.com和quiz.bdfzscc.com,若前后端不在同一域名下,则需要3个域名。
由于SubQuiz使用腾讯云的COS服务,因此建议购买腾讯云的域名和服务器。
建议将后端与前端部署在同一域名下,可以减少跨域问题,例如前端在
https://example.com/
,后端在https://example.com/api/
。后面的文档将都按照部署在同一域名下配置,如有需要可以调整
PostgreSQL
- 安装PostgreSQL
- 修改必要的配置文件,如配置监听端口等。保证PostgreSQL可以被SubQuiz后端所访问
- 为SubQuiz准备一个PostgreSQL用户,可以创建新的用户也可以使用默认的postgres
- 为SubQuiz准备一个database,请确认3中准备的用户有足够的权限访问该database,如创建表等。注意你只需要创建一个空的database,无需手动添加任何表或数据
- DONE! 留着用户名/密码/数据库备用
AI
- 物色一个大语言模型的服务商,需要注意的是,该服务商的接口必须遵循OpenAI协议。目前测试过的有Deepseek和硅基流动。
- 注册账户(若每个用户有请求频率/并发量限制,且限制过低,不足以支撑使用)
- 获取API TOKEN(如有需要可以获得多个TOKEN,原因同上)和API的URL
- DONE!留着URL和TOKEN备用
SSubitO
- 打开SSubITO注册并进入个人信息界面,点击
服务管理
,创建一个新的服务。名字和简介自行填写,授权后权限选择全部
- 等待审核通过,你可能需要联系SubIT以进行协商
- 审核通过后打开服务信息界面,查看服务id并获取服务密钥
- DONE!留着服务id和服务密钥备用
腾讯云COS及CDN
- 打开腾讯云COS,创建一个存储桶,地区建议选择和服务器相同,访问权限选择
共有读私有写
。其余配置不限 - 在存储桶的安全配置中,配置允许访问的域名(即你准备部署的域名)
- 打开腾讯云EO按提示创建一个站点。进入
域名服务
->域名管理
->添加域名
按提示创建一个对于刚刚创建的存储桶的加速服务 - 参考腾讯云文档为EO配置响应仅允许你的域名访问
- 打开腾讯云API密钥管理创建新的API密钥,记录ID和KEY
- DONE!留着你的存储桶名称、API密钥(ID和KEY)备用
恭喜你!准备工作到此结束,现在开始代码构建和部署:
后端的构建和部署
编译打包
在项目目录运行 ./gradlew clean build
(linux)或 ./gradlew.bat clean build
(windows)或在IntelliJ Idea中创建一个gradle任务,并在命令处输入 clean build
并运行
运行结束后你可以找到 build/libs/SubQuiz.jar
即为构建结果
配置并运行
使用命令java -jar SubQuiz.jar
运行构建出的jar文件,其中有几个可选参数:
-workDir=$dir
:工作目录,默认为当前目录-dataDir=$dir
:数据目录,默认为workDir
下的data
文件夹-config=$file
:配置文件,默认为workDir
下的config.yaml
-debug=$debug
:调试模式,默认为false
首次运行后,应该绘立刻退出,并生成主配置文件(-config
),以及在(workDir
)下的一个配置文件夹(configs
)。
你需要逐一浏览并编辑主配置文件和配置文件夹下的全部配置文件,这些配置文件基本都带有注释,按提示编辑将准备工作中活动的秘钥/域名等填入即可。
恭喜你!后端部署已经全部结束了!
前端的配置和构建
打开前端项目的.env
文件
0
1
2
3
4
5
6
VITE_APP_SUB_QUIZ_CDN=https://cdn.bdfzscc.com #你的EO的URL
VITE_APP_SUB_QUIZ_BACKEND=https://quiz.bdfzscc.com/api #你的后端的url
VITE_APP_SUB_QUIZ_FRONTEND=https://quiz.bdfzscc.com #你的前端的URL
VITE_APP_SUB_QUIZ_SSO_FRONTEND=https://pkus.sso.subit.org.cn #sso前端的url,应该不用该
VITE_APP_SUB_QUIZ_SSO_BACKEND=https://pkus.sso.subit.org.cn/api #sso后端的url,应该不用该
VITE_APP_SUB_QUIZ_SSO_SERVICE_ID=3 #你在sso创建的服务的id
依次运行:
npm install
npm run build-web
此时你应当会看到一个/dist
文件夹,即为前端构建结果
前端部署及反向代理后端
安装nginx,添加一个新的站点配置
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
server {
listen 80;
server_name quiz.bdfzscc.com; # 你的域名
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 1024M;
location / {
root /var/www/SubQuiz; # 你的前端构建结果文件夹
index index.html;
try_files $uri $uri/ /index.html;
location /android_latest.json {
add_header Access-Control-Allow-Origin "*";
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
expires 1y;
add_header Cache-Control "public, no-transform";
}
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}
location /api/ {
proxy_pass http://localhost:8080; # 你的后端地址
}
location /api/terminal/api {
proxy_pass http://localhost:8080; # 你的后端地址
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}