feat: 初始化考培练系统项目
- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
447
frontend/src/api/trainee/index.ts
Normal file
447
frontend/src/api/trainee/index.ts
Normal file
@@ -0,0 +1,447 @@
|
||||
/**
|
||||
* 学员功能模块 API
|
||||
*/
|
||||
import request from '../request'
|
||||
|
||||
// 课程信息
|
||||
export interface CourseInfo {
|
||||
id: number
|
||||
title: string
|
||||
name?: string // 与title兼容
|
||||
description?: string
|
||||
coverImage?: string
|
||||
category: string
|
||||
difficulty: 'beginner' | 'intermediate' | 'advanced'
|
||||
difficulty_level?: string // 与difficulty的字符串版本兼容
|
||||
duration: number // 分钟
|
||||
duration_hours?: number // 与duration的小时版本兼容
|
||||
learner_count?: number // 学习人数
|
||||
materialCount: number
|
||||
progress: number // 0-100
|
||||
rating: number
|
||||
status: 'published' | 'draft' | 'archived'
|
||||
tags: string[]
|
||||
allow_download?: boolean // 是否允许下载资料
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
// 课程材料
|
||||
export interface CourseMaterial {
|
||||
id: number
|
||||
courseId: number
|
||||
title: string
|
||||
type: 'video' | 'audio' | 'document' | 'pdf' | 'ppt' | 'image' | 'text' | 'download' | 'html' | 'other'
|
||||
url: string
|
||||
duration?: number
|
||||
size?: number
|
||||
order: number
|
||||
isCompleted: boolean
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
// 成长路径节点
|
||||
export interface GrowthPathNode {
|
||||
id: number
|
||||
courseId: number
|
||||
courseName: string
|
||||
courseDescription?: string
|
||||
isRequired: boolean
|
||||
isCompleted: boolean
|
||||
progress: number
|
||||
prerequisiteIds: number[]
|
||||
estimatedDays: number
|
||||
order: number
|
||||
}
|
||||
|
||||
// 成长路径
|
||||
export interface GrowthPath {
|
||||
id: number
|
||||
name: string
|
||||
description?: string
|
||||
positionId: number
|
||||
positionName: string
|
||||
totalCourses: number
|
||||
completedCourses: number
|
||||
requiredCourses: number
|
||||
optionalCourses: number
|
||||
estimatedDays: number
|
||||
progress: number
|
||||
nodes: GrowthPathNode[]
|
||||
}
|
||||
|
||||
// 能力评估数据
|
||||
export interface AbilityAssessment {
|
||||
categories: Array<{
|
||||
name: string
|
||||
score: number
|
||||
maxScore: number
|
||||
skills: Array<{
|
||||
name: string
|
||||
score: number
|
||||
maxScore: number
|
||||
}>
|
||||
}>
|
||||
overallScore: number
|
||||
maxOverallScore: number
|
||||
lastUpdated: string
|
||||
}
|
||||
|
||||
// AI陪练场景
|
||||
export interface PracticeScene {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
category: string
|
||||
difficulty: 'easy' | 'medium' | 'hard'
|
||||
estimatedDuration: number // 分钟
|
||||
usageCount: number
|
||||
averageRating: number
|
||||
status: 'active' | 'inactive'
|
||||
tags: string[]
|
||||
aiRole: string
|
||||
objectives: string[]
|
||||
keywords: string[]
|
||||
backgroundInfo: string
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
// 陪练记录
|
||||
export interface PracticeRecord {
|
||||
id: string
|
||||
sceneId: number
|
||||
sceneName: string
|
||||
sceneCategory: string
|
||||
duration: number // 秒
|
||||
messageCount: number
|
||||
overallScore: number
|
||||
result: 'excellent' | 'good' | 'average' | 'needs_improvement'
|
||||
startTime: string
|
||||
endTime: string
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
// 陪练会话消息
|
||||
export interface PracticeMessage {
|
||||
id: string
|
||||
role: 'user' | 'assistant'
|
||||
content: string
|
||||
timestamp: string
|
||||
audioUrl?: string
|
||||
}
|
||||
|
||||
// 陪练分析报告
|
||||
export interface PracticeReport {
|
||||
id: string
|
||||
recordId: string
|
||||
overallScore: number
|
||||
detailedScores: {
|
||||
communication: number
|
||||
professionalism: number
|
||||
problemSolving: number
|
||||
knowledge: number
|
||||
}
|
||||
strengths: string[]
|
||||
improvements: string[]
|
||||
suggestions: string[]
|
||||
keyMoments: Array<{
|
||||
timestamp: string
|
||||
description: string
|
||||
score: number
|
||||
}>
|
||||
summary: string
|
||||
nextSteps: string[]
|
||||
}
|
||||
|
||||
// 考试记录
|
||||
export interface ExamRecord {
|
||||
id: string
|
||||
examName: string
|
||||
examType: string
|
||||
subject: string
|
||||
totalScore: number
|
||||
userScore: number
|
||||
accuracy: number
|
||||
duration: number // 秒
|
||||
status: 'completed' | 'in_progress' | 'abandoned'
|
||||
startTime: string
|
||||
endTime?: string
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
// 错题信息
|
||||
export interface MistakeQuestion {
|
||||
id: string
|
||||
questionId: string
|
||||
question: string
|
||||
questionType: 'single' | 'multiple' | 'judge' | 'fill'
|
||||
correctAnswer: string
|
||||
userAnswer: string
|
||||
explanation: string
|
||||
mistakeCount: number
|
||||
lastMistakeTime: string
|
||||
isMastered: boolean
|
||||
subject: string
|
||||
difficulty: string
|
||||
tags: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取课程列表
|
||||
*/
|
||||
export const getCourseList = (params: {
|
||||
page?: number
|
||||
size?: number
|
||||
category?: string
|
||||
difficulty?: string
|
||||
keyword?: string
|
||||
} = {}) => {
|
||||
return request.get<{
|
||||
items: CourseInfo[]
|
||||
total: number
|
||||
page: number
|
||||
size: number
|
||||
}>('/api/v1/courses', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取课程详情
|
||||
*/
|
||||
export const getCourseDetail = (courseId: number) => {
|
||||
return request.get<CourseInfo>(`/api/v1/courses/${courseId}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取课程材料列表
|
||||
*/
|
||||
export const getCourseMaterials = (courseId: number) => {
|
||||
return request.get<CourseMaterial[]>(`/api/v1/trainee/courses/${courseId}/materials`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记材料为已完成
|
||||
*/
|
||||
export const markMaterialCompleted = (materialId: number) => {
|
||||
return request.post(`/api/v1/trainee/materials/${materialId}/complete`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取成长路径
|
||||
*/
|
||||
export const getGrowthPath = () => {
|
||||
return request.get<GrowthPath>('/api/v1/trainee/growth-path')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取能力评估数据
|
||||
*/
|
||||
export const getAbilityAssessment = () => {
|
||||
return request.get<AbilityAssessment>('/api/v1/trainee/ability-assessment')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取AI陪练场景列表
|
||||
*/
|
||||
export const getPracticeScenes = (params: {
|
||||
category?: string
|
||||
difficulty?: string
|
||||
keyword?: string
|
||||
} = {}) => {
|
||||
return request.get<PracticeScene[]>('/api/v1/trainee/practice-scenes', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取陪练场景详情
|
||||
*/
|
||||
export const getPracticeSceneDetail = (sceneId: number) => {
|
||||
return request.get<PracticeScene>(`/api/v1/trainee/practice-scenes/${sceneId}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始AI陪练
|
||||
*/
|
||||
export const startPractice = (sceneId: number) => {
|
||||
return request.post<{ sessionId: string }>('/api/v1/trainee/practice/start', { sceneId })
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束AI陪练
|
||||
*/
|
||||
export const endPractice = (sessionId: string) => {
|
||||
return request.post<{ recordId: string }>('/api/v1/trainee/practice/end', { sessionId })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取陪练记录列表
|
||||
*/
|
||||
export const getPracticeRecords = (params: {
|
||||
page?: number
|
||||
size?: number
|
||||
sceneId?: number
|
||||
result?: string
|
||||
startDate?: string
|
||||
endDate?: string
|
||||
keyword?: string
|
||||
} = {}) => {
|
||||
return request.get<{
|
||||
items: PracticeRecord[]
|
||||
total: number
|
||||
page: number
|
||||
size: number
|
||||
statistics: {
|
||||
totalSessions: number
|
||||
averageScore: number
|
||||
totalDuration: number
|
||||
monthlyProgress: number
|
||||
}
|
||||
}>('/api/v1/trainee/practice-records', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取陪练记录详情(对话回放)
|
||||
*/
|
||||
export const getPracticeRecordDetail = (recordId: string) => {
|
||||
return request.get<{
|
||||
record: PracticeRecord
|
||||
messages: PracticeMessage[]
|
||||
}>(`/api/v1/trainee/practice-records/${recordId}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取陪练分析报告
|
||||
*/
|
||||
export const getPracticeReport = (recordId: string) => {
|
||||
return request.get<PracticeReport>(`/api/v1/trainee/practice-reports/${recordId}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考试记录列表
|
||||
*/
|
||||
export const getExamRecords = (params: {
|
||||
page?: number
|
||||
size?: number
|
||||
examType?: string
|
||||
subject?: string
|
||||
minScore?: number
|
||||
maxScore?: number
|
||||
startDate?: string
|
||||
endDate?: string
|
||||
} = {}) => {
|
||||
return request.get<{
|
||||
items: ExamRecord[]
|
||||
total: number
|
||||
page: number
|
||||
size: number
|
||||
statistics: {
|
||||
totalExams: number
|
||||
averageScore: number
|
||||
passRate: number
|
||||
ranking: number
|
||||
}
|
||||
}>('/api/v1/trainee/exam-records', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取考试记录详情
|
||||
*/
|
||||
export const getExamRecordDetail = (recordId: string) => {
|
||||
return request.get<{
|
||||
record: ExamRecord
|
||||
questions: Array<{
|
||||
questionId: string
|
||||
question: string
|
||||
options?: string[]
|
||||
correctAnswer: string
|
||||
userAnswer: string
|
||||
isCorrect: boolean
|
||||
score: number
|
||||
}>
|
||||
scoreByType: Array<{
|
||||
type: string
|
||||
totalQuestions: number
|
||||
correctAnswers: number
|
||||
accuracy: number
|
||||
score: number
|
||||
}>
|
||||
}>(`/api/v1/trainee/exam-records/${recordId}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错题列表
|
||||
*/
|
||||
export const getMistakeQuestions = (params: {
|
||||
page?: number
|
||||
size?: number
|
||||
subject?: string
|
||||
difficulty?: string
|
||||
isMastered?: boolean
|
||||
keyword?: string
|
||||
} = {}) => {
|
||||
return request.get<{
|
||||
items: MistakeQuestion[]
|
||||
total: number
|
||||
page: number
|
||||
size: number
|
||||
statistics: {
|
||||
totalMistakes: number
|
||||
masteredCount: number
|
||||
recentMistakes: number
|
||||
}
|
||||
}>('/api/v1/trainee/mistakes', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记错题为已掌握
|
||||
*/
|
||||
export const markQuestionMastered = (questionId: string) => {
|
||||
return request.post(`/api/v1/trainee/mistakes/${questionId}/mastered`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 错题重练
|
||||
*/
|
||||
export const practicemistake = (questionIds: string[]) => {
|
||||
return request.post<{ examId: string }>('/api/v1/trainee/mistakes/practice', { questionIds })
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建课程对话会话
|
||||
*/
|
||||
export const createCourseChat = (courseId: number) => {
|
||||
return request.post<{ sessionId: string }>('/api/v1/trainee/course-chat/sessions', { courseId })
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送课程对话消息
|
||||
*/
|
||||
export const sendCourseMessage = (sessionId: string, content: string) => {
|
||||
return request.post<{ messageId: string; response: string }>('/api/v1/trainee/course-chat/messages', {
|
||||
sessionId,
|
||||
content
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 分析智能工牌数据
|
||||
* 调用后端API分析言迹智能工牌的录音数据,生成能力评估报告和课程推荐
|
||||
*/
|
||||
export const analyzeYanjiBadge = () => {
|
||||
return request.post<{
|
||||
assessment_id: number
|
||||
total_score: number
|
||||
dimensions: Array<{
|
||||
name: string
|
||||
score: number
|
||||
feedback: string
|
||||
}>
|
||||
recommended_courses: Array<{
|
||||
course_id: number
|
||||
course_name: string
|
||||
recommendation_reason: string
|
||||
priority: string
|
||||
match_score: number
|
||||
}>
|
||||
conversation_count: number
|
||||
analyzed_at: string
|
||||
}>('/api/v1/ability/analyze-yanji')
|
||||
}
|
||||
Reference in New Issue
Block a user