🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
207 lines
5.7 KiB
TypeScript
207 lines
5.7 KiB
TypeScript
import { request } from '../utils/request'
|
||
import type {
|
||
Question,
|
||
SubmitAnswer,
|
||
AnswerResult,
|
||
Statistics,
|
||
ApiResponse,
|
||
WrongQuestion,
|
||
WrongQuestionStats,
|
||
WrongQuestionFilter
|
||
} from '../types/question'
|
||
|
||
// 获取题目列表
|
||
export const getQuestions = (params?: { type?: string; search?: string }) => {
|
||
return request.get<ApiResponse<Question[]>>('/practice/questions', { params })
|
||
}
|
||
|
||
// 获取指定题目
|
||
export const getQuestionById = (id: number) => {
|
||
return request.get<ApiResponse<Question>>(`/practice/questions/${id}`)
|
||
}
|
||
|
||
// 提交答案
|
||
export const submitAnswer = (data: SubmitAnswer) => {
|
||
return request.post<ApiResponse<AnswerResult>>('/practice/submit', data)
|
||
}
|
||
|
||
// 获取统计数据
|
||
export const getStatistics = () => {
|
||
return request.get<ApiResponse<Statistics>>('/practice/statistics')
|
||
}
|
||
|
||
// ========== 练习进度相关 API ==========
|
||
|
||
// 答题记录
|
||
export interface AnsweredQuestion {
|
||
question_id: number
|
||
record_id: number
|
||
is_correct: boolean
|
||
user_answer: any
|
||
correct_answer: any // 正确答案
|
||
answered_at: string
|
||
// AI 评分相关(仅简答题有值)
|
||
ai_score?: number
|
||
ai_feedback?: string
|
||
ai_suggestion?: string
|
||
}
|
||
|
||
// 进度数据(按题目类型)
|
||
export interface PracticeProgressData {
|
||
type: string
|
||
current_question_id: number
|
||
answered_questions: AnsweredQuestion[]
|
||
}
|
||
|
||
// 获取练习进度(可选type参数)
|
||
export const getPracticeProgress = (type?: string) => {
|
||
const params = type ? { type } : undefined
|
||
return request.get<ApiResponse<PracticeProgressData[]>>('/practice/progress', { params })
|
||
}
|
||
|
||
// 清除练习进度(可选type参数,指定类型则只清除该类型的进度)
|
||
export const clearPracticeProgress = (type?: string) => {
|
||
const params = type ? { type } : undefined
|
||
return request.delete<ApiResponse<null>>('/practice/progress', { params })
|
||
}
|
||
|
||
// 重置进度 (暂时返回模拟数据,后续实现)
|
||
export const resetProgress = async () => {
|
||
// TODO: 实现真实的重置接口
|
||
return {
|
||
success: true,
|
||
data: null
|
||
}
|
||
}
|
||
|
||
// ========== 错题本相关 API ==========
|
||
|
||
// 获取错题列表(支持筛选和排序)
|
||
export const getWrongQuestions = (filter?: WrongQuestionFilter) => {
|
||
const params: Record<string, string> = {}
|
||
if (filter?.is_mastered !== undefined) {
|
||
params.is_mastered = filter.is_mastered ? 'true' : 'false'
|
||
}
|
||
if (filter?.tag) params.tag = filter.tag
|
||
if (filter?.type) params.type = filter.type
|
||
if (filter?.sort) params.sort = filter.sort
|
||
|
||
return request.get<ApiResponse<WrongQuestion[]>>('/wrong-questions', { params })
|
||
}
|
||
|
||
// 获取错题详情(包含完整历史)
|
||
export const getWrongQuestionDetail = (id: number) => {
|
||
return request.get<ApiResponse<WrongQuestion>>(`/wrong-questions/${id}`)
|
||
}
|
||
|
||
// 获取错题统计(含趋势数据)
|
||
export const getWrongQuestionStats = () => {
|
||
return request.get<ApiResponse<WrongQuestionStats>>('/wrong-questions/stats')
|
||
}
|
||
|
||
// 获取推荐练习的错题(智能推荐)
|
||
export const getRecommendedWrongQuestions = (limit: number = 10, excludeQuestionID?: number) => {
|
||
const params: Record<string, any> = { limit }
|
||
if (excludeQuestionID) {
|
||
params.exclude = excludeQuestionID
|
||
}
|
||
return request.get<ApiResponse<WrongQuestion[]>>('/wrong-questions/recommended', {
|
||
params
|
||
})
|
||
}
|
||
|
||
// 删除错题
|
||
export const deleteWrongQuestion = (id: number) => {
|
||
return request.delete<ApiResponse<null>>(`/wrong-questions/${id}`)
|
||
}
|
||
|
||
// 清空错题本
|
||
export const clearWrongQuestions = () => {
|
||
return request.delete<ApiResponse<null>>('/wrong-questions')
|
||
}
|
||
|
||
// ========== 题库管理相关 API ==========
|
||
|
||
// 创建题目
|
||
export const createQuestion = (data: {
|
||
type: string
|
||
type_name?: string
|
||
question: string
|
||
answer: any
|
||
options?: Record<string, string>
|
||
}) => {
|
||
return request.post<ApiResponse<Question>>('/practice/questions', data)
|
||
}
|
||
|
||
// 更新题目
|
||
export const updateQuestion = (id: number, data: {
|
||
type?: string
|
||
type_name?: string
|
||
question?: string
|
||
answer?: any
|
||
options?: Record<string, string>
|
||
}) => {
|
||
return request.put<ApiResponse<Question>>(`/practice/questions/${id}`, data)
|
||
}
|
||
|
||
// 删除题目
|
||
export const deleteQuestion = (id: number) => {
|
||
return request.delete<ApiResponse<null>>(`/practice/questions/${id}`)
|
||
}
|
||
|
||
// 获取题目解析(AI)
|
||
export const explainQuestion = (questionId: number) => {
|
||
return request.post<ApiResponse<{ explanation: string }>>('/practice/explain', { question_id: questionId })
|
||
}
|
||
|
||
// ========== 用户管理相关 API(仅管理员) ==========
|
||
|
||
// 用户统计信息
|
||
export interface UserStats {
|
||
user_id: number
|
||
username: string
|
||
nickname: string
|
||
avatar: string
|
||
user_type: string
|
||
total_answers: number
|
||
correct_count: number
|
||
wrong_count: number
|
||
accuracy: number
|
||
created_at: string
|
||
last_answer_at?: string
|
||
}
|
||
|
||
// 用户详细统计
|
||
export interface UserDetailStats {
|
||
user_info: UserStats
|
||
type_stats: Array<{
|
||
question_type: string
|
||
question_type_name: string
|
||
total_answers: number
|
||
correct_count: number
|
||
accuracy: number
|
||
}>
|
||
}
|
||
|
||
// 获取所有用户及统计(仅yanlongqi用户可访问)
|
||
export const getAllUsersWithStats = () => {
|
||
return request.get<ApiResponse<UserStats[]>>('/admin/users')
|
||
}
|
||
|
||
// 获取用户详细统计(仅yanlongqi用户可访问)
|
||
export const getUserDetailStats = (userId: number) => {
|
||
return request.get<ApiResponse<UserDetailStats>>(`/admin/users/${userId}`)
|
||
}
|
||
|
||
// ========== 排行榜相关 API ==========
|
||
|
||
// 获取今日排行榜
|
||
export const getDailyRanking = (limit: number = 10) => {
|
||
return request.get<ApiResponse<UserStats[]>>('/ranking/daily', { params: { limit } })
|
||
}
|
||
|
||
// 获取总排行榜
|
||
export const getTotalRanking = (limit: number = 10) => {
|
||
return request.get<ApiResponse<UserStats[]>>('/ranking/total', { params: { limit } })
|
||
}
|