524 lines
13 KiB
Markdown
524 lines
13 KiB
Markdown
![]() |
# 考试信息API使用文档
|
|||
|
|
|||
|
## 接口概述
|
|||
|
|
|||
|
`/aiol/aiolExam/getExamInfo` 接口用于获取教师名下的考试信息列表。
|
|||
|
|
|||
|
## 接口定义
|
|||
|
|
|||
|
### 请求方式
|
|||
|
- **方法**: GET
|
|||
|
- **路径**: `/aiol/aiolExam/getExamInfo`
|
|||
|
- **参数**: `userId` (查询参数)
|
|||
|
|
|||
|
### 请求参数
|
|||
|
|
|||
|
| 参数名 | 类型 | 必选 | 说明 |
|
|||
|
|--------|------|------|------|
|
|||
|
| userId | string | 是 | 教师用户ID |
|
|||
|
|
|||
|
### 响应格式
|
|||
|
|
|||
|
```typescript
|
|||
|
{
|
|||
|
"success": boolean,
|
|||
|
"message": string,
|
|||
|
"code": number,
|
|||
|
"result": ExamInfo[],
|
|||
|
"timestamp": number
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### ExamInfo 数据结构
|
|||
|
|
|||
|
```typescript
|
|||
|
interface ExamInfo {
|
|||
|
id: string // 考试ID
|
|||
|
name: string // 考试名称
|
|||
|
paperId: string // 试卷ID
|
|||
|
startTime: string // 开始时间
|
|||
|
endTime: string // 结束时间
|
|||
|
totalTime: number // 考试时长(分钟)
|
|||
|
type: number // 考试类型:0=练习,1=考试
|
|||
|
status: number // 状态:0=未发布,1=发布中,2=已结束
|
|||
|
createBy: string // 创建人
|
|||
|
createTime: string // 创建时间
|
|||
|
updateBy: string // 更新人
|
|||
|
updateTime: string // 更新时间
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 使用示例
|
|||
|
|
|||
|
### 1. 在API模块中调用
|
|||
|
|
|||
|
```typescript
|
|||
|
import { ExamApi } from '@/api/modules/exam'
|
|||
|
|
|||
|
// 获取教师考试信息
|
|||
|
const response = await ExamApi.getExamInfo('teacher_user_id')
|
|||
|
console.log('考试信息:', response.data)
|
|||
|
```
|
|||
|
|
|||
|
### 2. 在Vue组件中使用
|
|||
|
|
|||
|
```typescript
|
|||
|
import { ExamApi } from '@/api/modules/exam'
|
|||
|
import { useUserStore } from '@/stores/user'
|
|||
|
|
|||
|
export default {
|
|||
|
setup() {
|
|||
|
const userStore = useUserStore()
|
|||
|
|
|||
|
const loadExamInfo = async () => {
|
|||
|
if (!userStore.user?.id) {
|
|||
|
console.error('请先登录')
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
const response = await ExamApi.getExamInfo(userStore.user.id.toString())
|
|||
|
return response.data || []
|
|||
|
} catch (error) {
|
|||
|
console.error('加载考试信息失败:', error)
|
|||
|
return []
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return {
|
|||
|
loadExamInfo
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 3. 在试卷管理页面中使用
|
|||
|
|
|||
|
```typescript
|
|||
|
// 在 ExamLibrary.vue 中
|
|||
|
import { ExamApi } from '@/api/modules/exam'
|
|||
|
import { useUserStore } from '@/stores/user'
|
|||
|
import type { ExamInfo } from '@/api/types'
|
|||
|
|
|||
|
const userStore = useUserStore()
|
|||
|
|
|||
|
const loadExamInfo = async () => {
|
|||
|
loading.value = true
|
|||
|
try {
|
|||
|
const currentUser = userStore.user
|
|||
|
if (!currentUser?.id) {
|
|||
|
message.error('请先登录')
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
const response = await ExamApi.getExamInfo(currentUser.id.toString())
|
|||
|
|
|||
|
if (response.data && Array.isArray(response.data)) {
|
|||
|
// 数据映射和显示逻辑
|
|||
|
const mappedList = response.data.map((item: ExamInfo) => {
|
|||
|
// 映射逻辑...
|
|||
|
return {
|
|||
|
id: item.id,
|
|||
|
name: item.name,
|
|||
|
// ... 其他字段映射
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
examData.value = mappedList
|
|||
|
}
|
|||
|
} catch (error) {
|
|||
|
console.error('加载考试信息失败:', error)
|
|||
|
message.error('加载考试信息失败')
|
|||
|
} finally {
|
|||
|
loading.value = false
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 数据映射说明
|
|||
|
|
|||
|
### 状态映射
|
|||
|
```typescript
|
|||
|
const statusMap: { [key: number]: string } = {
|
|||
|
0: '未发布',
|
|||
|
1: '发布中',
|
|||
|
2: '已结束'
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 类型映射
|
|||
|
```typescript
|
|||
|
const categoryMap: { [key: number]: string } = {
|
|||
|
0: '练习',
|
|||
|
1: '考试'
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 难度映射
|
|||
|
```typescript
|
|||
|
const difficultyMap: { [key: number]: string } = {
|
|||
|
0: '易',
|
|||
|
1: '中',
|
|||
|
2: '难'
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 错误处理
|
|||
|
|
|||
|
接口可能返回以下错误:
|
|||
|
|
|||
|
1. **401 Unauthorized**: 用户未登录或token过期
|
|||
|
2. **403 Forbidden**: 没有权限访问
|
|||
|
3. **500 Internal Server Error**: 服务器内部错误
|
|||
|
|
|||
|
建议在调用时添加适当的错误处理:
|
|||
|
|
|||
|
```typescript
|
|||
|
try {
|
|||
|
const response = await ExamApi.getExamInfo(userId)
|
|||
|
// 处理成功响应
|
|||
|
} catch (error) {
|
|||
|
if (error.response?.status === 401) {
|
|||
|
// 处理认证错误
|
|||
|
console.error('登录已过期,请重新登录')
|
|||
|
} else {
|
|||
|
// 处理其他错误
|
|||
|
console.error('获取考试信息失败:', error.message)
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 注意事项
|
|||
|
|
|||
|
1. 调用此接口前需要确保用户已登录
|
|||
|
2. 只有教师用户才能调用此接口
|
|||
|
3. 返回的考试信息按创建时间倒序排列
|
|||
|
4. 建议在组件挂载时调用此接口加载数据
|
|||
|
5. 可以根据需要添加分页、搜索等参数(需要后端支持)
|
|||
|
|
|||
|
## 相关文件
|
|||
|
|
|||
|
- API实现: `src/api/modules/exam.ts`
|
|||
|
- 类型定义: `src/api/types.ts`
|
|||
|
- 使用示例: `src/api/examples/getExamInfo-example.ts`
|
|||
|
- 页面实现: `src/views/teacher/ExamPages/ExamLibrary.vue`
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
# 创建试卷API使用文档
|
|||
|
|
|||
|
## 接口概述
|
|||
|
|
|||
|
`POST /aiol/aiolPaper/add` 接口用于创建新的试卷。
|
|||
|
|
|||
|
## 接口定义
|
|||
|
|
|||
|
### 请求方式
|
|||
|
- **方法**: POST
|
|||
|
- **路径**: `/aiol/aiolPaper/add`
|
|||
|
- **Content-Type**: `application/json`
|
|||
|
|
|||
|
### 请求参数
|
|||
|
|
|||
|
| 参数名 | 类型 | 必选 | 说明 |
|
|||
|
|--------|------|------|------|
|
|||
|
| title | string | 是 | 试卷标题 |
|
|||
|
| generateMode | number | 否 | 组卷模式:0=固定试卷组,1=随机抽题组卷 |
|
|||
|
| rules | string | 否 | 组卷规则(随机抽题时使用) |
|
|||
|
| repoId | string | 否 | 题库ID(随机抽题时使用) |
|
|||
|
| totalScore | number | 是 | 试卷总分 |
|
|||
|
| passScore | number | 否 | 及格分数(默认总分的60%) |
|
|||
|
| requireReview | number | 否 | 是否需要批阅:0=不需要,1=需要 |
|
|||
|
|
|||
|
### 响应格式
|
|||
|
|
|||
|
```typescript
|
|||
|
{
|
|||
|
"success": boolean,
|
|||
|
"message": string,
|
|||
|
"code": number,
|
|||
|
"result": string, // 试卷ID
|
|||
|
"timestamp": number
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 使用示例
|
|||
|
|
|||
|
### 1. 在API模块中调用
|
|||
|
|
|||
|
```typescript
|
|||
|
import { ExamApi } from '@/api/modules/exam'
|
|||
|
|
|||
|
// 创建固定试卷组
|
|||
|
const response = await ExamApi.createExamPaper({
|
|||
|
title: '数学期末考试试卷',
|
|||
|
generateMode: 0,
|
|||
|
totalScore: 100,
|
|||
|
passScore: 60,
|
|||
|
requireReview: 0
|
|||
|
})
|
|||
|
console.log('试卷ID:', response.data)
|
|||
|
```
|
|||
|
|
|||
|
### 2. 在Vue组件中使用
|
|||
|
|
|||
|
```typescript
|
|||
|
// 在 AddExam.vue 中
|
|||
|
const saveExam = async () => {
|
|||
|
try {
|
|||
|
const apiData = {
|
|||
|
title: examForm.title,
|
|||
|
generateMode: examForm.type === 1 ? 0 : 1,
|
|||
|
rules: '',
|
|||
|
repoId: '',
|
|||
|
totalScore: examForm.totalScore,
|
|||
|
passScore: examForm.passScore || Math.floor(examForm.totalScore * 0.6),
|
|||
|
requireReview: examForm.useAIGrading ? 1 : 0
|
|||
|
}
|
|||
|
|
|||
|
const response = await ExamApi.createExamPaper(apiData)
|
|||
|
console.log('创建试卷成功:', response.data)
|
|||
|
} catch (error) {
|
|||
|
console.error('创建试卷失败:', error)
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 3. 不同组卷模式示例
|
|||
|
|
|||
|
```typescript
|
|||
|
// 固定试卷组
|
|||
|
const fixedPaper = {
|
|||
|
title: '固定试卷组示例',
|
|||
|
generateMode: 0,
|
|||
|
rules: '',
|
|||
|
repoId: '',
|
|||
|
totalScore: 100,
|
|||
|
passScore: 60,
|
|||
|
requireReview: 0
|
|||
|
}
|
|||
|
|
|||
|
// 随机抽题组卷
|
|||
|
const randomPaper = {
|
|||
|
title: '随机抽题组卷示例',
|
|||
|
generateMode: 1,
|
|||
|
rules: '{"difficulty": [1, 2, 3], "types": [0, 1, 2], "count": 20}',
|
|||
|
repoId: 'repo_123',
|
|||
|
totalScore: 100,
|
|||
|
passScore: 60,
|
|||
|
requireReview: 1
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 相关文件
|
|||
|
|
|||
|
- API实现: `src/api/modules/exam.ts`
|
|||
|
- 页面实现: `src/views/teacher/ExamPages/AddExam.vue`
|
|||
|
- 使用示例: `src/api/examples/createPaper-example.ts`
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
# 删除试卷API使用文档
|
|||
|
|
|||
|
## 接口概述
|
|||
|
|
|||
|
删除试卷相关的API接口包括单个删除和批量删除功能。
|
|||
|
|
|||
|
## 接口定义
|
|||
|
|
|||
|
### 1. 删除单个试卷
|
|||
|
|
|||
|
- **方法**: DELETE
|
|||
|
- **路径**: `/aiol/aiolPaper/delete?id={paperId}`
|
|||
|
- **参数**: `id` (查询参数) - 试卷ID
|
|||
|
|
|||
|
### 2. 批量删除试卷
|
|||
|
|
|||
|
- **实现方式**: 循环调用单个删除接口(因为后端可能不支持批量删除接口)
|
|||
|
- **方法**: 内部调用多个 `DELETE /aiol/aiolPaper/delete?id={paperId}`
|
|||
|
- **参数**: `ids: string[]` - 试卷ID数组
|
|||
|
|
|||
|
### 响应格式
|
|||
|
|
|||
|
**单个删除响应**:
|
|||
|
```typescript
|
|||
|
{
|
|||
|
"success": boolean,
|
|||
|
"message": string,
|
|||
|
"code": number,
|
|||
|
"result": string,
|
|||
|
"timestamp": number
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**批量删除响应**:
|
|||
|
```typescript
|
|||
|
{
|
|||
|
"success": boolean,
|
|||
|
"message": string,
|
|||
|
"code": number,
|
|||
|
"result": {
|
|||
|
"success": number, // 成功删除的数量
|
|||
|
"failed": number, // 失败删除的数量
|
|||
|
"total": number, // 总数量
|
|||
|
"errors": string[] // 错误信息数组
|
|||
|
},
|
|||
|
"timestamp": number
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 使用示例
|
|||
|
|
|||
|
### 1. 删除单个试卷
|
|||
|
|
|||
|
```typescript
|
|||
|
import { ExamApi } from '@/api/modules/exam'
|
|||
|
|
|||
|
// 删除单个试卷
|
|||
|
const response = await ExamApi.deleteExamPaper('1962379646322384897')
|
|||
|
console.log('删除结果:', response.data)
|
|||
|
```
|
|||
|
|
|||
|
### 2. 批量删除试卷
|
|||
|
|
|||
|
```typescript
|
|||
|
// 批量删除试卷
|
|||
|
const paperIds = ['1962379646322384897', '1966450638717292545']
|
|||
|
const response = await ExamApi.batchDeleteExamPapers(paperIds)
|
|||
|
console.log('批量删除结果:', response.data)
|
|||
|
```
|
|||
|
|
|||
|
### 3. 在Vue组件中使用(使用 Naive UI 对话框组件)
|
|||
|
|
|||
|
```typescript
|
|||
|
// 在 ExamLibrary.vue 中
|
|||
|
import { useDialog, useMessage } from 'naive-ui'
|
|||
|
|
|||
|
const dialog = useDialog()
|
|||
|
const message = useMessage()
|
|||
|
|
|||
|
const handleDeletePaper = async (row: any) => {
|
|||
|
try {
|
|||
|
// 使用 Naive UI 对话框组件
|
|||
|
dialog.warning({
|
|||
|
title: '确认删除',
|
|||
|
content: `确定要删除试卷"${row.name}"吗?此操作不可撤销。`,
|
|||
|
positiveText: '确定删除',
|
|||
|
negativeText: '取消',
|
|||
|
onPositiveClick: async () => {
|
|||
|
try {
|
|||
|
// 调用删除API
|
|||
|
const response = await ExamApi.deleteExamPaper(row.id)
|
|||
|
|
|||
|
// 显示成功消息
|
|||
|
message.success('试卷删除成功!')
|
|||
|
|
|||
|
// 重新加载试卷列表
|
|||
|
await loadExamPaperList()
|
|||
|
} catch (error) {
|
|||
|
console.error('删除试卷失败:', error)
|
|||
|
message.error('删除试卷失败,请重试')
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
} catch (error) {
|
|||
|
console.error('删除试卷失败:', error)
|
|||
|
message.error('删除试卷失败,请重试')
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 批量删除示例
|
|||
|
const handleBatchDelete = async () => {
|
|||
|
if (checkedRowKeys.value.length === 0) {
|
|||
|
message.warning('请先选择要删除的试卷')
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
// 使用 Naive UI 对话框组件
|
|||
|
dialog.error({
|
|||
|
title: '确认批量删除',
|
|||
|
content: `确定要删除选中的 ${checkedRowKeys.value.length} 个试卷吗?此操作不可撤销。`,
|
|||
|
positiveText: '确定删除',
|
|||
|
negativeText: '取消',
|
|||
|
onPositiveClick: async () => {
|
|||
|
try {
|
|||
|
// 调用批量删除API
|
|||
|
const response = await ExamApi.batchDeleteExamPapers(checkedRowKeys.value as string[])
|
|||
|
|
|||
|
// 显示成功消息
|
|||
|
message.success(`成功删除 ${checkedRowKeys.value.length} 个试卷!`)
|
|||
|
|
|||
|
// 清空选中状态
|
|||
|
checkedRowKeys.value = []
|
|||
|
|
|||
|
// 重新加载试卷列表
|
|||
|
await loadExamPaperList()
|
|||
|
} catch (error) {
|
|||
|
console.error('批量删除试卷失败:', error)
|
|||
|
message.error('批量删除试卷失败,请重试')
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
} catch (error) {
|
|||
|
console.error('批量删除试卷失败:', error)
|
|||
|
message.error('批量删除试卷失败,请重试')
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 4. 错误处理
|
|||
|
|
|||
|
```typescript
|
|||
|
const deletePaperWithErrorHandling = async (paperId: string) => {
|
|||
|
try {
|
|||
|
const response = await ExamApi.deleteExamPaper(paperId)
|
|||
|
|
|||
|
if (response.data === 'success') {
|
|||
|
return { success: true, message: '删除成功' }
|
|||
|
} else {
|
|||
|
return { success: false, message: '删除失败,请重试' }
|
|||
|
}
|
|||
|
|
|||
|
} catch (error: any) {
|
|||
|
if (error.response?.status === 404) {
|
|||
|
return { success: false, message: '试卷不存在' }
|
|||
|
} else if (error.response?.status === 403) {
|
|||
|
return { success: false, message: '没有权限删除此试卷' }
|
|||
|
}
|
|||
|
|
|||
|
return { success: false, message: '删除失败,请检查网络连接' }
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 功能特性
|
|||
|
|
|||
|
### 单个删除
|
|||
|
- 支持删除单个试卷
|
|||
|
- 使用 Naive UI 警告对话框组件
|
|||
|
- 删除成功后自动刷新列表
|
|||
|
- 完整的错误处理
|
|||
|
|
|||
|
### 批量删除
|
|||
|
- 支持同时删除多个试卷
|
|||
|
- 循环调用单个删除接口(避免后端接口不存在的问题)
|
|||
|
- 逐个删除,避免对服务器造成过大压力
|
|||
|
- 详细的删除结果反馈(成功/失败数量)
|
|||
|
- 使用 Naive UI 错误对话框组件(更醒目的警告)
|
|||
|
- 删除后清空选中状态
|
|||
|
|
|||
|
### 用户体验
|
|||
|
- **美观的确认对话框**: 使用 Naive UI 组件,样式统一美观
|
|||
|
- **不同类型的对话框**: 单个删除使用 warning,批量删除使用 error
|
|||
|
- **成功/失败消息提示**: 使用 Naive UI 的 message 组件
|
|||
|
- **按钮状态管理**: 批量删除按钮在未选中时禁用
|
|||
|
- **实时更新选中数量显示**: 动态显示选中的试卷数量
|
|||
|
- **异步操作处理**: 在对话框确认后才执行删除操作
|
|||
|
|
|||
|
## 相关文件
|
|||
|
|
|||
|
- API实现: `src/api/modules/exam.ts`
|
|||
|
- 页面实现: `src/views/teacher/ExamPages/ExamLibrary.vue`
|
|||
|
- 使用示例: `src/api/examples/deletePaper-example.ts`
|