服务端集成示例源码

本文介绍远程监考服务端集成示例源码说明。

前提条件

  • 已完成控制台开通与配置相关操作。

  • 如果您需要通过容器镜像快速部署AppServer,请确保环境中已安装Docker,详情请参见Docker

  • 如果您需要通过源码构建并部署AppServer:

    • Java版本:请确保环境中已安装jdk8。

通过源码构建及部署

根据源码的说明文档配置并执行,源码地址参见源码

项目部署与体验

  • 关于技术选型

    • 基于主流的Java8 + Springboot2搭建框架

    • 基于Mybatis plus(https://baomidou.com/)作为Repository层选型,存储可以使用MySQL

    • 基于SpringSecurity + JWT 来实现权限控制

  • 关于部署

    • 理论上只要安装了Java8即可运行在各个ECS或容器上。也可以考虑使用Serverless平台来快速部署,但使用前提是要对函数计算比较清楚。

配置文件

server:
  port: 8080

# mysql
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://******:3306/*****?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: "******"
    password: "******"
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd'T'HH:mm:ss+08:00
    default-property-inclusion: non_null

#mybatis
mybatis-plus:
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.aliyuncs.aui.entity
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    default-statement-timeout: 10

# pop配置
biz:
  openapi:
    access:
      key: "*********"
      secret: "*********"
  # 融云相关配置,可不配置,需要高可用性考虑    
  live_rongcloud_im:
    app_key: "******"
    app_secret: "********"
  # 旧IM相关配置,新接入的客户不用配置
  live_im:
    app_id: TY3****
  # 新IM相关配置 
  new_im:
    appId: "********"
    appKey: "********"
    appSign: "********"
  # 配置推拉流信息
  live_stream:
    push_url: push.*****.vip
    pull_url: pull.*****.vip
    push_auth_key: zJl4******
    pull_auth_key: mDZs********
    app_name: live
    auth_expires: 604800
  # 配置连麦信息,需要再配置
  live_mic:
    app_id: 7c61********
    app_key: c461b*********
  # ram及upload用于考生端本地录制功能上传视频的功能,需要使用就配置
  ram:
    access_key_id: LTAI5*********
    access_key_secret: NLgHO********
  upload:
    role_arn: acs:ram::*******
    region: cn-shanghai
    bucket: *****
    base_path: /***
http:
  cors:
    host: "*"

参数说明

参数配置信息

说明

# pop配置。需要配置账号的AccessKey ID和AccessKey Secret,用于调用IM及live相关服务
 biz:
  openapi:
    access:
      key: "*********"
      secret: "*********"

调用阿里云IM及Live相关服务API时,您需要使用AccessKey完成身份验证。AccessKey包括AccessKey ID和AccessKey Secret。具体如下:

  • AccessKey ID:用于标识用户。

  • AccessKey Secret:用于验证用户的密钥。AccessKey Secret必须保密。

更多信息,请参见创建AccessKey

# 融云相关配置,请先开通融云IM服务   
    live_rongcloud_im:
    	app_key: "*********"
    	app_secret: "*********"

该场景默认使用直播互动消息简介服务,若您需要使用融云IM服务,请先开通其服务。

 # 旧IM相关配置,新接入的客户不用配置
  live_im:
    app_id: TY3****

旧版IM相关配置,新接入的客户不需要进行配置

# 新IM相关配置 
  new_im:
    appId: "********"
    appKey: "********"
    appSign: "********"

直播动消息应用ID,请参见控制台开通与配置中的创建直播互动消息应用获取。

# 配置推拉流信息
  live_stream:
    push_url: push.*****.vip
    pull_url: pull.*****.vip
    push_auth_key: zJl4******
    pull_auth_key: mDZs********
    app_name: live
    auth_expires: 604800
  • push_url: WebRTC(超低延时RTS2.0)推流域名

  • pull_url: WebRTC(超低延时RTS2.0)播放域名

  • push_auth_key: 推流域名的鉴权主KEY,可通过视频直播控制台>加速服务>域名管理>域名配置>直播管理>访问控制>URL鉴权>主key获取,具体详见配置URL鉴权

  • pull_auth_key: 播流域名的鉴权主KEY,可通过视频直播控制台>加速服务>域名管理>域名配置>直播管理>访问控制>URL鉴权>主key获取,具体详见配置URL鉴权

  • app_name: 旁路转推后直播流地址中的AppName,默认为live,可自定义。

    说明

    若您需要为转推后的流绑定转码、录制、截图等模板,需要设置该AppName与模板中的AppName一致才会生效。

 # 配置连麦信息,需要再配置
  live_mic:
    app_id: 7c61********
    app_key: c461b*********

连麦功能如果需要可进行配置,连麦应用IDAppKey,请参见创建互动直播应用

# ram及upload用于考生端本地录制功能上传视频的功能,需要使用就配置
  ram:
    access_key_id: LTAI5*********
    access_key_secret: NLgHO********
  upload:
    role_arn: acs:ram::*******
    region: cn-shanghai
    bucket: *****
    base_path: /***

请参阅使用STS临时访问凭证访问OSS使用STS临时授权方案上传视频文档创建RAM用户、角色,配置相关参数。

  • access_key_id:RAM用户ID。

  • access_key_secret:RAM用户访问密钥。

  • role_arn:RAM角色。

  • region:Bucket所在区域,如 oss-cn-shanghai。

  • bucket:OSS Bucket名。

  • base_path:上传至OSS Bucket的基础路径,如 /record/local/ ,注意和考生客户端配置项保持一致。

# 配置允许跨域的请求域名
http:
  cors:
    host: "*"

Web端使用该服务时请正确设置CORS,以允许跨域请求。

数据库配置

当配置好DB后,手工创建数据库表。以MySQL为例,建表语句为:

CREATE TABLE `cheat_config` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `exam_id` varchar(256) NOT NULL COMMENT '考试ID',
  `data` text NOT NULL COMMENT '具体配置,JSON串',
  `creator` varchar(256) DEFAULT NULL COMMENT '创建者',
  `created_at` datetime NOT NULL COMMENT '创建时间',
  `updated_at` datetime NOT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `exam_id` (`exam_id`),
  KEY `idx_create_at` (`created_at`)
) ENGINE=InnoDB;

CREATE TABLE `cheat_record` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `exam_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '考试ID',
  `room_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '考场id',
  `user_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '考生id',
  `detect_type` varchar(256) NOT NULL COMMENT '检测类型',
  `detect_time` datetime NOT NULL COMMENT '检测时间',
  `is_main_monitor` varchar(256) NOT NULL COMMENT '考生主机位/副机位',
  `extra_info` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '额外信息存储',
  `created_at` datetime NOT NULL COMMENT '创建时间',
  `updated_at` datetime NOT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`),
  KEY `idx_exam_id` (`exam_id`),
  KEY `idx_create_at` (`created_at`),
  KEY `idx_room_id` (`room_id`) USING BTREE
) ENGINE=InnoDB;


CREATE TABLE `exam_room_infos` (
  `id` varchar(256) NOT NULL,
  `name` varchar(256) DEFAULT NULL,
  `exam_id` varchar(256) DEFAULT NULL,
  `status` bigint DEFAULT NULL,
  `audio_status` bigint DEFAULT NULL,
  `im_group_id` varchar(256) DEFAULT NULL,
  `create_teacher` varchar(256) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_create_at` (`created_at`)
) ENGINE=InnoDB

CREATE TABLE `examinations` (
  `id` varchar(256) NOT NULL,
  `name` varchar(256) DEFAULT NULL,
  `start_time` datetime DEFAULT NULL,
  `end_time` datetime DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_create_at` (`created_at`)
) ENGINE=InnoDB

参数说明

  • cheat_config表: 存储作弊配置

  • cheat_record表:记录考生的作弊信息

  • exam_room_infos表:存储考场信息

  • examinations表:存储考试信息

具体字段可参考代码对应的各个实体:

com.aliyuncs.aui.entity.CheatConfigEntity

com.aliyuncs.aui.entity.CheatRecordEntity

com.aliyuncs.aui.entity.RoomInfoEntity

com.aliyuncs.aui.entity.ExamEntity

编译运行

详细信息请参见源码中的README文件。

## 构建执行文件


```bash
go build -o main ./cmd/main.go
```


## 本地运行


```bash
export ADMIN_PASSWORD=your-secret
./main
```


所有 API 及对应文档:
浏览器打开:http://localhost:7001/swagger/index.html
用户名为 admin,密码为您自行设置


## 生成`swagger`文档


```bash
# 安装swagger工具 请具体参考:https://github.com/swaggo/swag
go install github.com/swaggo/swag/cmd/swag@latest


# 动态生成文档
swag init -g pkg/handler/*.go
```

接口

通用请求头参数

用于请求header上。

name

type

required

desc

authorization

string

YES

身份认证token,通过页面URL参数传入。

创建考场

  • 请求协议:http/https

  • 请求Path:/exam/v2/createRoom

  • 是否需要授权:是

  • 请求Method:POST

  • 请求ContentType:JSON

请求参数

名称

类型

是否必填

示例值

描述

name

String

titlexxxx

直播标题, 长度小于64

imServer

Json数组

["aliyun_old","aliyun_new"]

配置使用哪些im服务。可多选

  • aliyun_old

  • aliyun_new

返回数据

名称

类型

示例值

描述

code

Integer

200

业务响应码。参考HTTP响应码

id

String

ee487235-5f9b-4cb3-82ce-45c91c3xxxx

考场ID。

createdAt

String

2023-02-27T17:34:00.592750182+08:00

创建时间。

updatedAt

String

2023-02-27T17:34:00.592750182+08:00

修改时间。

name

String

titlexxx

考场名称。

examId

String

noticexxx

考试ID。

status

String

考场状态。

  • 0:进行中。

  • 1:已结束。

audioStatus

String

anchor_idxxx

考场口播状态。

  • 0:未口播。

  • 1:正在口播。

imGroupId

String

anchor_nickxxx

消息组ID。

createTeacher

String

{"xx":"xxx"}

考场创建者ID。

addRoom 时序图

image

示例

请求示例

{
    "name": "考场名称-2024全国本科艺术考试第0001考场",
    "imServer":["aliyun_new", "aliyun_old"]
}

正常返回示例

{
    "success": true,
    "data": {
        "id": "f064a22d-9885-47ab-bce9-a058c74c****",
        "createdAt": "2023-12-12T15:59:12+08:00",
        "updatedAt": "2023-12-12T15:59:12+08:00",
        "name": "考场名称-2024全国本科艺术考试第0001考场",
        "examId": "d385e65a-8f3c-447e-9d57-01a18089****",
        "status": 0,
        "audioStatus": 0,
        "imGroupId": "f064a22d-9885-47ab-bce9-a058c74c****",
        "createTeacher": "teacher1"
    }
}

获取考场信息

Path: /exam/roomInfo

Method:GET

Query:

name

type

required

desc

roomId

string

YES

考场ID,通过页面URL参数传入。

Body:

name

type

desc

success

boolean

是否成功。

errorCode

string

异常码。

errorMsg

string

异常信息。

data

object

数据。

  |─id

string

考场ID。

  |─name

string

考场名称。

  |─examId

string

考试ID。

  |─status

integer

考场状态。

  • 0:进行中。

  • 1:已结束。

  |─audioStatus

integer

考场口播状态。

  • 0:未口播。

  • 1:正在口播。

  |─imGroupId

string

消息组ID。

  |─createTeacher

string

考场创建者ID。

Response Demo:

{
 "success": true,
 "errorCode": "",
 "errorMsg": "",
 "data": {
 "id": "roomId",
 "name": "模拟考场",
 "examId": "examId",
 "status": 0,
 "audioStatus": 0,
 "imGroupId": "xxx",
 "createTeacher": "teacherId"
 }
}

获取考试信息

Path:/exam/examInfo

Method:GET

Query:

name

type

required

desc

examId

string

YES

考试ID,来源是考场信息返回。

Body:

name

type

desc

success

boolean

是否成功。

errorCode

string

异常码。

errorMsg

string

异常信息。

data

object

数据。

  |─id

string

考试ID。

  |─name

string

考试名称。

  |─startTime

string

开始时间,使用YYYY/MM/DD HH:mm:ss格式化。

  |─endTime

string

结束时间。

  |─radioInfo

array

定时播放的音频。

    |─

object

      |─id

string

ID。

      |─classify

integer

分类。

      |─name

string

名字。

      |─startTime

string

触发播放时间。

      |─url

string

CDN地址。

      |─ossUrl

string

OSS地址(非必需)。

  |─audioInfo

array

需要老师手动播放的音频。

    |─

object

      |─id

string

ID。

      |─classify

integer

分类字典。

      |─name

string

音频名字。

      |─url

string

音频地址。

      |─ossUrl

string

OSS地址(非必需)。

Response Demo:

{
 "success": true,
 "errorCode": "",
 "errorMsg": "",
 "data": {
 "id": "123456",
 "name": "exam",
 "startTime": "2023/03/30 14:00:00",
 "endTime": "2023/03/30 17:00:00",
 "radioInfo": [
 {
 "id": "",
 "classify": 0,
 "name": "",
 "startTime": "2023/03/30 14:30:00",
 "url": ""
 }
 ],
 "audioInfo": [
 {
 "id": "",
 "classify": 0,
 "name": "",
 "url": ""
 }
 ]
 }
}

获取用户信息

Path:/exam/userInfo

Method:GET

Query:

name

type

required

desc

userId

string

YES

用户ID,通过页面URL参数传入。

roomId

string

YES

考场ID,通过页面URL参数传入。

Body:

name

type

desc

success

boolean

是否成功。

errorCode

string

异常码。

errorMsg

string

异常信息。

data

object

数据。

  |─id

string

用户ID。

  |─name

string

昵称。

  |─userStatus

int

状态(目前没用上)。

  • 0: 有进行中的考场。

  • 1: 无进行中的考场。

  |─rtcPushUrl

string

推流地址。

  |─rtcPullUrl

string

大流地址。

  |─rtsPullUrl

string

小流地址(转码低清晰度的流)。

Response Demo:

{
 "success": true,
 "errorCode": "",
 "errorMsg": "",
 "data": {
 "id": "userid",
 "name": "username",
 "userStatus": 0,
 "rtcPushUrl": "artc://{yourPushDomain}/exam/xxx-xxx-xxx?grtn_twin_rtmp=on",
 "rtcPullUrl": "artc://{yourBigPullDomain}/exam/xxx-xxx-xxx",
 "rtsPullUrl": "artc://{yourSmallPullDomain}/exam/xxx-xxx-xxx_240p"
 }
}

获取考场的学生列表

Path:/exam/userList

Method:GET

Query:

name

type

required

desc

roomId

考场id

YES

考场ID,通过页面URL参数传入。

Body:

name

type

desc

success

boolean

是否成功。

errorCode

string

异常码。

errorMsg

string

异常信息。

data

array

数据。

  |─

object

    |─id

string

用户ID。

    |─name

string

昵称。

    |─userStatus

int

状态(目前没有用上)。

    |─rtcPushUrl

string

推流地址。

    |─rtcPullUrl

string

大流地址。

    |─rtsPullUrl

string

小流地址。

Response Demo:

{
 "success": true,
 "errorCode": "",
 "errorMsg": "",
 "data": [
 {
 "id": "userid",
 "name": "username",
 "userStatus": 0,
 "rtcPushUrl": "artc://{yourPushDomain}/exam/xxx-xxx-xxx?grtn_twin_rtmp=on",
 "rtcPullUrl": "artc://{yourBigPullDomain}/exam/xxx-xxx-xxx",
 "rtsPullUrl": "artc://{yourSmallPullDomain}/exam/xxx-xxx-xxx_240p"
 }
 ]
}

获取IM建连的token

请参考建立长连接文档接入。

  • 请求协议:http/https

  • 请求Path:/exam/v2/getIMToken

  • 是否需要授权:是

  • 请求Method:POST

  • 请求ContentType:JSON

请求参数

名称

类型

是否必填

示例值

描述

userId

String

useridxxxx

用户UserId,用户自定义,在AppId下单独唯一。

deviceId

String

deviceidxxx

终端设备ID,唯一代表一个用户终端设备,用户自定义。

说明

仅针对aliyun_old服务起作用。

deviceType

String

android

终端设备类型,取值:

  • ios

  • android

  • web

  • pc

说明

仅针对aliyun_old服务起作用。

imServer

Json数组

["aliyun_old","aliyun_new"]

配置使用哪些IM服务。可多选

  • aliyun_old

  • aliyun_new

role

String

admin

角色,默认为空。当为admin时,表示该用户可以调用管控接口。

说明

仅针对aliyun_new服务起作用。

返回数据

名称

类型

示例值

描述

code

Integer

200

业务响应码。参考HTTP响应码。

aliyunOldIm

accessToken

String

eyJlbmRwb2ludHMiOlsid3NzOi8vbWV0YXBhdGguYWxpeXVuY3MuY29tL3dzIl0sImFwcElkIjoiMzhXWUg3RlQiLCJ0b2tlbiI6Im1wLmV5SjBlWEFpT2lKS1YxUWlMQ0poYkdjaU9pSklVekkxTmlKOS5le********

旧IM的token。

refreshToken

String

eyJlbmRwb2ludHMiOlsid3NzOi8vbWV0YXBhdGguYWxpeXVuY3MuY29tL3dzIl0sImFwcElkIjoiMzhXWUg3RlQiLCJ0b2tlbiI6Im1wLmV5SjBlWEFpT2lKS1YxUWlMQ0poYkdjaU9pSklVekkxTmlKOS5le********

旧IM的refreshtoken。

aliyunNewIm

appId

String

0c826fdeb1c5

用户的AppID。

appSign

String

H4sIAAAAAAAE/wBgAJ//zguHB+lYCilkv7diSkk4GgjFw0Ka520mdSvKR1g6pC4Y3s/sSRMZR8HgSaLZHP5mcR95bdEfWhnB2Br1efpa62ZdKcr5noeaExJXc1ZVZUGP6ZY2yOklt/1uAIlPpOn7AAAA//8BAAD///ZbnP*******

服务器生成的加密串,包含接入域名等信息。

appToken

String

42e96eeede710b738a561b9edcfac3507eae7036cf10fb7ed4b059afc6******

登录鉴权。

auth.userId

String

123456****

要登录的用户的ID。

auth.nonce

String

20d3acba-b4d4-4940-abb1-9e908813c71a

格式:"AK-随机串",最长64字节。

auth.timestamp

Long

1702371472

过期时间,从1970到过期时间的秒数。

auth.role

String

admin

角色,为admin时,表示该用户可以调用管控接口。

示例

请求示例

{
    "userId": "123456****",
    "deviceId": "fwfwqeqeq****",
    "deviceType":"web",
    "imServer":["aliyun_new", "aliyun_old"]
}

正常返回示例

{
    "success": true,
    "data": {
        "aliyunOldIm": {
            "accessToken": "eyJlbmRwb2ludHMiOlsid3NzOi*******eXVuY3MuY29tL3dzIl0sImFwcElkIjoiMzhXWUg3RlQiLCJ0b2tlbiI6Im1wLmV5SjBlWEFpT2lKS1YxUWlMQ0poYkdjaU9pSklVekkxTmlKOS5leUoxYVdRaU9pSXhNak0wTlRZM09Ea3dJaXdpWlhod0lqb3hOekEwT1RVNU9EY3lMQ0poYVdRaU9pSXpPRmRaU0RkR1ZDSXNJbVJwWkNJNkltWjNabmR4WlhGbGNYZGxkM0VpTENKamFXUWlPaUl4TkRJNE16WTNPVGd6T0RrMU5UVTJJbjAuRTR2TlRvT3FsLVllanJfb3VlZUloblVEaDR4TzhGSUxTd09PMDl*******",
            "refreshToken": "eyJlbmRwb2ludHMiOlsid3NzOi*********GguYWxpeXVuY3MuY29tL3dzIl0sImFwcElkIjoiMzhXWUg3RlQiLCJ0b2tlbiI6Im1wLmV5SjBlWEFpT2lKS1YxUWlMQ0poYkdjaU9pSklVekkxTmlKOS5leUoxYVdRaU9pSXhNak0wTlRZM09Ea3dJaXdpWlhod0lqb3hOekEwT1RVNU9EY3lMQ0poYVdRaU9pSXpPRmRaU0RkR1ZDSXNJbVJwWkNJNkltWjNabmR4WlhGbGNYZGxkM0VpTENKamFXUWlPaUl4TkRJNE16WTNPVGd6T0RrMU5UVTJJbjAuRTR2TlRvT3FsLVllanJfb3VlZUloblVEaDR4TzhGSUxTd09PMD********"
        },
        "aliyunNewIm": {
            "auth": {
                "nonce": "20d3acba-b4d4-4940-abb1-9e908813****",
                "timestamp": 1702371472,
                "role": "",
                "userId": "123456****"
            },
            "appId": "0c826fdeb1c5",
            "appSign": "H4sIAAAAAAAE/wBgAJ//zguHB+lYCilkv7diSkk4GgjFw0Ka520mdSvKR1g6pC4Y3s/sSRMZR8HgSaLZHP5mcR95bdEfWhnB2Br1efpa62ZdKcr5noeaExJXc1ZVZUGP6ZY2yOklt/1uAIlPpOn7AAAA//8BAAD///ZbnP*******",
            "appToken": "42e96eeede710b738a561b9edcfac3507eae7036cf10fb7ed4b059a*******"
        }
    }
}

获取OSS配置

请参考使用STS临时访问凭证访问OSS实现,目前开源的Appserver源码中暂未实现,请自行实现。

Path:/exam/getOssConfig

Method:GET

Query:

name

type

required

desc

examId

考试ID

YES

考试ID。

Body:

name

type

desc

success

boolean

是否成功。

errorCode

string

异常码。

errorMsg

string

异常信息。

data

object

数据。

  |─region

string

以华东1(杭州)为例,yourRegion填写为oss-cn-hangzhou。

  |─accessKeyId

string

从STS服务获取的AccessKey IDAccessKey Secret。

  |─accessKeySecret

string

从STS服务获取的AccessKey Secret。

  |─stsToken

string

从STS服务获取的安全令牌(SecurityToken)。

  |─bucket

string

填写Bucket名称。

Response Demo:

{
 "success": true,
 "errorCode": "",
 "errorMsg": "",
 "data": {
 "region": "",
 "accessKeyId": "",
 "accessKeySecret": "",
 "stsToken": "",
 "bucket": ""
 }
}

查询系统音频列表

Path:/exam/selectAudio

Method:POST

Request Body:

name

type

desc

pageSize

integer

页面大小。

pageNum

integer

页数。

name

string

筛选音频名称(非必填)。

classify

integer

分类。

Request Demo:

{
 "pageSize": 0,
 "pageNum": 0,
 "name": "",
 "classify": 0
}

Body:

name

type

desc

success

boolean

是否成功。

errorCode

string

异常码。

errorMsg

string

异常信息。

data

object

数据。

  |─pageNum

integer

分页。

  |─pageSize

integer

一页条数。

  |─total

integer

总数。

  |─list

array

    |─

object

      |─id

string

ID。

      |─classify

integer

分类字典。

      |─name

string

音频名字。

      |─url

string

音频地址。

      |─ossUrl

string

OSS地址(非必需)。

Response Demo:

{
 "success": true,
 "errorCode": "",
 "errorMsg": "",
 "data": {
 "pageNum": 1,
 "pageSize": 10,
 "total": 14,
 "list": [
 {
 "id": "11111",
 "classify": 0,
 "name": "audio",
 "url": "",
 "ossUrl": "",
 }
 ]
 }
}

更新考场口播状态

Path:/exam/updateRoomAudioStatus

Method:POST

Query:

name

value

required

desc

id

string

YES

考场ID。

audioStatus

int

YES

考场口播状态。

  • 0:未口播。

  • 1:正在口播。

Body:

name

type

desc

success

boolean

是否成功。

errorCode

string

异常码。

errorMsg

string

异常信息。

data

boolean

数据。

Response Demo:

{
 "success": true,
 "errorCode": "",
 "errorMsg": "",
 "data": true
}

设置防作弊配置

  • 请求协议:http/https

  • 请求Path:/exam/cheat/setCheatConfig

  • 是否需要授权:是

  • 请求Method:POST

  • 请求ContentType:JSON

请求参数

名称

类型

是否必填

示例值

描述

examId

String

useridxxxx

考试ID

data

String

xxxx

作弊的配置信息 cheatConfig。由端自定义,服务器只管存储及返回

cheatConfig对象中有pc、mobile两个对象,每项的类型均为Boolean ,含义如下所示:

// 配置项为 true 时代表开启此项检测
const cheatConfig = {
  pc: {
    scenePersonExit: true, // 人物离开
    manyPeople: true, // 多人
    actionPoseStandup: true, // 起立
    actionPoseHandup: true, // 举手
    actionHeadUpDown: true, // 点头
    headShaking: true, // 摇头/转头
    objectDetect: true, // 携带电子设备
    actionPersonSpeech: true, // 识别到人声
  },
  mobile: {
    scenePersonExit: true, // 人物离开
    manyPeople: true, // 多人
    actionPoseStandup: true, // 起立
    actionPoseHandup: true, // 举手
    actionHeadUpDown: true, // 点头
    headShaking: true, // 摇头/转头
    objectDetect: true, // 携带电子设备
    actionPersonSpeech: true, // 识别到人声
  }
};

// 将 cheatConfig 对象转为 JSONString 后传给服务端保存
const data = JSON.stringify(cheatConfig);

返回数据

名称

类型

示例值

描述

success

Boolean

true

操作结果

  • true:成功

  • false:失败

示例

请求示例

{
    "examId": "11111111111",
    "data":"{xxxx}"
}

正常返回示例

{
    "success": true
}

获取考试防作弊配置

  • 请求协议:http/https

  • 请求Path:/exam/cheat/getCheatConfig

  • 是否需要授权:是

  • 请求Method:POST

  • 请求ContentType:JSON

请求参数

名称

类型

是否必填

示例值

描述

examId

String

useridxxxx

考试ID

返回数据

名称

类型

示例值

描述

success

Boolean

true

操作结果

  • true:成功

  • false:失败

data

JsonObject

结果,以JSON对象返回

data.examId

String

2023-02-27T17:34:00.592750182+08:00

考试ID

data.data

String

2023-02-27T17:34:00.592750182+08:00

作弊的配置信息

data.createdAt

String

2024-03-18T16:56:11+08:00

创建时间

data.updatedAt

String

2024-03-18T16:56:11+08:00

修改时间

示例

请求示例

{
    "examId": "11111111111"
}

返回示例

{
    "success": true,
    "data": {
        "examId": "11111111111",
        "data": "[xxxxxx]",
        "createdAt": "2024-03-18T16:56:11+08:00",
        "updatedAt": "2024-03-18T16:56:11+08:00"
    }
}

添加考场作弊信息

  • 请求协议:http/https

  • 请求Path:/exam/cheat/addCheatRecord

  • 是否需要授权:是

  • 请求Method:POST

  • 请求ContentType:JSON

请求参数

名称

类型

是否必填

示例值

描述

examId

String

examidxxxx

考试ID

roomId

String

roomIdxxxx

考场ID

data

String

[{\"detectTime\":232323,\"isMainMonitor\":true,\"detectType\":\"11\",\"userId\":\"userewexx\",\"extraInfo\":\"{222}2\"},{\"detectTime\":232324,\"isMainMonitor\":true,\"detectType\":\"12\",\"userId\":\"userewexx\",\"extraInfo\":\"{222}2\"}]

学生作弊信息cheatRecord,由端自定义

cheatRecord对象的定义说明如下,提交至服务端前要先转为JSONString。

interface CheatRecord {
  isMainMonitor: boolean; // 是否是主机位
  userId:string; // 用户id
  detectTime: number; // 检测时间,单位毫秒
  detectType: string; // 检测类型
  extraInfo: {
    message: string; // 提示信息
  };
}

返回数据

名称

类型

示例值

描述

success

Boolean

true

操作结果

  • true:成功

  • false:失败

示例

请求示例

{
    "examId": "333333",
    "roomId":"roomIdtest",
    "data":"[{\"detectTime\":232323,\"isMainMonitor\":true,\"detectType\":\"11\",\"userId\":\"userewexx\",\"extraInfo\":\"{222}2\"},{\"detectTime\":232324,\"isMainMonitor\":true,\"detectType\":\"12\",\"userId\":\"userewexx\",\"extraInfo\":\"{222}2\"}]"
}

正常返回示例

{
    "success": true
}

获取考场作弊信息

  • 请求协议:http/https

  • 请求Path:/exam/cheat/listCheatRecord

  • 是否需要授权:是

  • 请求Method:POST

  • 请求ContentType:JSON

请求参数

名称

类型

是否必填

示例值

描述

examId

String

examidxxxx

考试ID

roomId

String

roomIdxxxx

考场ID

pageSize

String

10

分页大小

scrollToken

String

分页标识,用于标识下一页的起始位。通过传该标识可以检索下一页数据

返回数据

名称

类型

示例值

描述

success

Boolean

true

操作结果

  • true:成功

  • false:失败

data

JsonObject

结果,以JSON对象返回

data.cheatRecordEntitys

JsonArray

作弊信息。由端自定义,服务器结构化输出。见参考示例

示例

请求示例

{
    "examId": "333333",
    "roomId": "roomIdtest",
    "pageSize":10,
    "scrollToken":""
}

正常返回示例

{
    "success": true,
    "data": {
        "cheatRecordEntitys": [
            {
                "id": 16666,
                "examId": "333333",
                "roomId": "roomIdtest",
                "userId": "userewexx",
                "detectType": "12",
                "isMainMonitor": "true",
                "detectTime": "1970-01-01T08:03:52+08:00",
                "extraInfo": "{222}2",
                "createdAt": "2024-03-18T17:00:53+08:00",
                "updatedAt": "2024-03-18T17:00:53+08:00"
            },
            {
                "id": 16665,
                "examId": "333333",
                "roomId": "roomIdtest",
                "userId": "userewexx",
                "detectType": "11",
                "isMainMonitor": "true",
                "detectTime": "1970-01-01T08:03:52+08:00",
                "extraInfo": "{222}2",
                "createdAt": "2024-03-18T17:00:53+08:00",
                "updatedAt": "2024-03-18T17:00:53+08:00"
            },
            {
                "id": 8346,
                "examId": "333333",
                "roomId": "roomIdtest",
                "userId": "userewexx",
                "detectType": "12",
                "isMainMonitor": "true",
                "detectTime": "1970-01-01T08:03:52+08:00",
                "extraInfo": "{222}2",
                "createdAt": "2023-11-14T15:55:25+08:00",
                "updatedAt": "2023-11-14T15:55:25+08:00"
            },
            {
                "id": 8345,
                "examId": "333333",
                "roomId": "roomIdtest",
                "userId": "userewexx",
                "detectType": "11",
                "isMainMonitor": "true",
                "detectTime": "1970-01-01T08:03:52+08:00",
                "extraInfo": "{222}2",
                "createdAt": "2023-11-14T15:55:25+08:00",
                "updatedAt": "2023-11-14T15:55:25+08:00"
            },
            {
                "id": 8342,
                "examId": "333333",
                "roomId": "roomIdtest",
                "userId": "userewexx",
                "detectType": "12",
                "isMainMonitor": "true",
                "detectTime": "1970-01-01T08:03:52+08:00",
                "extraInfo": "{222}2",
                "createdAt": "2023-11-14T15:46:48+08:00",
                "updatedAt": "2023-11-14T15:46:48+08:00"
            },
            {
                "id": 8341,
                "examId": "333333",
                "roomId": "roomIdtest",
                "userId": "userewexx",
                "detectType": "11",
                "isMainMonitor": "true",
                "detectTime": "1970-01-01T08:03:52+08:00",
                "extraInfo": "{222}2",
                "createdAt": "2023-11-14T15:46:44+08:00",
                "updatedAt": "2023-11-14T15:46:44+08:00"
            },
            {
                "id": 8340,
                "examId": "333333",
                "roomId": "roomIdtest",
                "userId": "userewexx",
                "detectType": "12",
                "isMainMonitor": "true",
                "detectTime": "1970-01-01T08:03:52+08:00",
                "extraInfo": "{222}2",
                "createdAt": "2023-11-14T15:45:40+08:00",
                "updatedAt": "2023-11-14T15:45:40+08:00"
            },
            {
                "id": 8339,
                "examId": "333333",
                "roomId": "roomIdtest",
                "userId": "userewexx",
                "detectType": "11",
                "isMainMonitor": "true",
                "detectTime": "1970-01-01T08:03:52+08:00",
                "extraInfo": "{222}2",
                "createdAt": "2023-11-14T15:45:40+08:00",
                "updatedAt": "2023-11-14T15:45:40+08:00"
            }
        ],
        "scrollToken": "8339"
    }
}

结束考场

Path:/exam/endRoom

Method:GET

Query:

name

type

required

desc

roomId

string

YES

考场ID,通过页面URL参数传入。

Body:

name

type

desc

success

boolean

是否成功。

errorCode

string

异常码。

errorMsg

string

异常信息。

data

boolean

数据。

Response Demo:

{
 "success": true,
 "errorCode": "",
 "errorMsg": "",
 "data": true
}