feat:hls流误删导致视频报错,作业资料接口对接,逻辑处理下载,课程列表按钮按照 后端请求分为需传token 和不需要根据是否登录判断
This commit is contained in:
parent
71ea0bbfb4
commit
6b685501dd
@ -117,7 +117,7 @@ export class ExamApi {
|
|||||||
*/
|
*/
|
||||||
static async getQuestionDetail(questionId: string): Promise<ApiResponse<Question>> {
|
static async getQuestionDetail(questionId: string): Promise<ApiResponse<Question>> {
|
||||||
console.log('🚀 查询题目详情:', { questionId })
|
console.log('🚀 查询题目详情:', { questionId })
|
||||||
const response = await ApiRequest.get<Question>(`/biz/repo/repoList/${questionId}`)
|
const response = await ApiRequest.get<Question>(`/aiol/aiolRepo/repoList/${questionId}`)
|
||||||
console.log('✅ 查询题目详情成功:', response)
|
console.log('✅ 查询题目详情成功:', response)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ export class ExamApi {
|
|||||||
*/
|
*/
|
||||||
static async createQuestion(data: CreateQuestionRequest): Promise<ApiResponse<string>> {
|
static async createQuestion(data: CreateQuestionRequest): Promise<ApiResponse<string>> {
|
||||||
console.log('🚀 添加题目:', data)
|
console.log('🚀 添加题目:', data)
|
||||||
const response = await ApiRequest.post<string>('/gen/question/question/add', data)
|
const response = await ApiRequest.post<string>('/aiol/aiolQuestion/add', data)
|
||||||
console.log('✅ 添加题目成功:', response)
|
console.log('✅ 添加题目成功:', response)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ export class ExamApi {
|
|||||||
*/
|
*/
|
||||||
static async updateQuestion(data: UpdateQuestionRequest): Promise<ApiResponse<string>> {
|
static async updateQuestion(data: UpdateQuestionRequest): Promise<ApiResponse<string>> {
|
||||||
console.log('🚀 编辑题目:', data)
|
console.log('🚀 编辑题目:', data)
|
||||||
const response = await ApiRequest.put<string>('/gen/question/question/edit', data)
|
const response = await ApiRequest.put<string>('/aiol/aiolQuestion/edit', data)
|
||||||
console.log('✅ 编辑题目成功:', response)
|
console.log('✅ 编辑题目成功:', response)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
@ -145,15 +145,15 @@ export class ExamApi {
|
|||||||
/**
|
/**
|
||||||
* 删除题目
|
* 删除题目
|
||||||
*/
|
*/
|
||||||
static async deleteQuestion(id: string): Promise<ApiResponse<string>> {
|
static async deleteQuestion(questionId: string): Promise<ApiResponse<string>> {
|
||||||
console.log('🚀 删除题目:', { id })
|
console.log('🚀 删除题目:', { questionId })
|
||||||
const response = await ApiRequest.delete<string>('/gen/question/question/delete', {
|
const response = await ApiRequest.delete<string>(`/aiol/aiolQuestion/delete?id=${questionId}`)
|
||||||
params: { id }
|
|
||||||
})
|
|
||||||
console.log('✅ 删除题目成功:', response)
|
console.log('✅ 删除题目成功:', response)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ========== 题目选项管理 ==========
|
// ========== 题目选项管理 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,6 +263,19 @@ const message = useMessage();
|
|||||||
const questionId = route.params.questionId as string | undefined;
|
const questionId = route.params.questionId as string | undefined;
|
||||||
const isEditMode = ref(!!questionId);
|
const isEditMode = ref(!!questionId);
|
||||||
|
|
||||||
|
// 题目类型映射
|
||||||
|
const getQuestionTypeKey = (type: number): string => {
|
||||||
|
const typeMap: { [key: number]: string } = {
|
||||||
|
0: 'single_choice', // 单选题
|
||||||
|
1: 'multiple_choice', // 多选题
|
||||||
|
2: 'true_false', // 判断题
|
||||||
|
3: 'fill_blank', // 填空题
|
||||||
|
4: 'short_answer', // 简答题
|
||||||
|
5: 'composite' // 复合题
|
||||||
|
};
|
||||||
|
return typeMap[type] || 'single_choice';
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// 表单引用
|
// 表单引用
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
@ -288,16 +301,16 @@ const categoryOptions = ref([
|
|||||||
|
|
||||||
// 难度选项
|
// 难度选项
|
||||||
const difficultyOptions = ref([
|
const difficultyOptions = ref([
|
||||||
{ label: '简单', value: 'easy' },
|
{ label: '简单', value: 0 },
|
||||||
{ label: '中等', value: 'medium' },
|
{ label: '中等', value: 1 },
|
||||||
{ label: '困难', value: 'hard' }
|
{ label: '困难', value: 2 }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 试题表单数据
|
// 试题表单数据
|
||||||
const questionForm = reactive({
|
const questionForm = reactive({
|
||||||
type: 'single_choice', // 默认单选题
|
type: 'single_choice', // 默认单选题
|
||||||
category: '',
|
category: '',
|
||||||
difficulty: '',
|
difficulty: 0, // 默认简单
|
||||||
score: 10,
|
score: 10,
|
||||||
title: '',
|
title: '',
|
||||||
options: [
|
options: [
|
||||||
@ -323,12 +336,13 @@ const formRules = {
|
|||||||
trigger: 'change'
|
trigger: 'change'
|
||||||
},
|
},
|
||||||
category: {
|
category: {
|
||||||
required: true,
|
required: false,
|
||||||
message: '请选择分类',
|
message: '请选择分类',
|
||||||
trigger: 'change'
|
trigger: 'change'
|
||||||
},
|
},
|
||||||
difficulty: {
|
difficulty: {
|
||||||
required: true,
|
required: true,
|
||||||
|
type: 'number',
|
||||||
message: '请选择难度',
|
message: '请选择难度',
|
||||||
trigger: 'change'
|
trigger: 'change'
|
||||||
},
|
},
|
||||||
@ -397,14 +411,20 @@ const getQuestionTypeNumber = (type: string): number => {
|
|||||||
return typeMap[type] || 0;
|
return typeMap[type] || 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 难度映射函数:将字符串难度转换为数字
|
// 难度映射函数:将数字难度转换为数字(保持原值)
|
||||||
const getDifficultyNumber = (difficulty: string): number => {
|
const getDifficultyNumber = (difficulty: number | string): number => {
|
||||||
|
// 如果已经是数字,直接返回
|
||||||
|
if (typeof difficulty === 'number') {
|
||||||
|
return difficulty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是字符串,进行转换
|
||||||
const difficultyMap: Record<string, number> = {
|
const difficultyMap: Record<string, number> = {
|
||||||
'easy': 1, // 简单
|
'easy': 0, // 简单
|
||||||
'medium': 2, // 中等
|
'medium': 1, // 中等
|
||||||
'hard': 3 // 困难
|
'hard': 2 // 困难
|
||||||
};
|
};
|
||||||
return difficultyMap[difficulty] || 1;
|
return difficultyMap[difficulty] || 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 保存试题
|
// 保存试题
|
||||||
@ -478,8 +498,9 @@ const saveQuestion = async () => {
|
|||||||
// 创建新题目的完整流程
|
// 创建新题目的完整流程
|
||||||
const createNewQuestion = async (bankId: string) => {
|
const createNewQuestion = async (bankId: string) => {
|
||||||
try {
|
try {
|
||||||
// 第一步:添加题干,获取questionId
|
// 只调用一次API创建题目
|
||||||
const questionData = {
|
const questionData = {
|
||||||
|
parentId: null, // 父题目ID,普通题目为null
|
||||||
type: getQuestionTypeNumber(questionForm.type),
|
type: getQuestionTypeNumber(questionForm.type),
|
||||||
content: questionForm.title,
|
content: questionForm.title,
|
||||||
analysis: questionForm.explanation || '',
|
analysis: questionForm.explanation || '',
|
||||||
@ -487,37 +508,33 @@ const createNewQuestion = async (bankId: string) => {
|
|||||||
score: questionForm.score
|
score: questionForm.score
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('🚀 第一步:创建题目题干:', questionData);
|
console.log('🚀 创建题目,数据:', questionData);
|
||||||
const questionResponse = await ExamApi.createQuestion(questionData);
|
const response = await ExamApi.createQuestion(questionData);
|
||||||
|
console.log('📊 创建题目API响应:', response);
|
||||||
|
|
||||||
if (!questionResponse.data) {
|
// 处理API响应
|
||||||
throw new Error('创建题目失败,未返回题目ID');
|
let success = false;
|
||||||
|
let questionId = null;
|
||||||
|
|
||||||
|
if (response.data) {
|
||||||
|
const apiResponse = response.data as any;
|
||||||
|
|
||||||
|
// 检查是否是包装格式 {success, code, result}
|
||||||
|
if (typeof apiResponse === 'object' && ('success' in apiResponse || 'code' in apiResponse)) {
|
||||||
|
success = apiResponse.success === true || apiResponse.code === 200 || apiResponse.code === 0;
|
||||||
|
questionId = apiResponse.result || apiResponse.data;
|
||||||
|
} else {
|
||||||
|
// 直接是题目ID
|
||||||
|
success = true;
|
||||||
|
questionId = apiResponse;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const createdQuestionId = questionResponse.data;
|
if (!success) {
|
||||||
console.log('✅ 题目创建成功,questionId:', createdQuestionId);
|
throw new Error('创建题目失败');
|
||||||
|
|
||||||
// 第二步:根据题型添加选项和答案
|
|
||||||
if (questionForm.type === 'single_choice') {
|
|
||||||
await handleSingleChoiceQuestion(createdQuestionId);
|
|
||||||
}
|
}
|
||||||
// TODO: 处理其他题型
|
|
||||||
// else if (questionForm.type === 'multiple_choice') {
|
|
||||||
// await handleMultipleChoiceQuestion(createdQuestionId);
|
|
||||||
// } else if (questionForm.type === 'true_false') {
|
|
||||||
// await handleTrueFalseQuestion(createdQuestionId);
|
|
||||||
// }
|
|
||||||
// 其他题型暂不处理
|
|
||||||
|
|
||||||
// 最后一步:将题目绑定到题库
|
console.log('✅ 题目创建成功,题目ID:', questionId);
|
||||||
const questionRepoData = {
|
|
||||||
repoId: bankId,
|
|
||||||
questionId: createdQuestionId
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('🚀 最后一步:绑定题目到题库:', questionRepoData);
|
|
||||||
await ExamApi.createQuestionRepo(questionRepoData);
|
|
||||||
console.log('✅ 题目绑定到题库成功');
|
|
||||||
|
|
||||||
message.success('题目保存成功');
|
message.success('题目保存成功');
|
||||||
|
|
||||||
@ -772,36 +789,252 @@ const validateCompositeQuestion = (): boolean => {
|
|||||||
|
|
||||||
// 组件挂载
|
// 组件挂载
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
console.log('AddQuestion 组件挂载完成');
|
||||||
|
console.log('编辑模式:', isEditMode.value);
|
||||||
|
console.log('题目ID:', questionId);
|
||||||
|
|
||||||
// 如果是编辑模式,加载题目数据
|
// 如果是编辑模式,加载题目数据
|
||||||
if (isEditMode.value && questionId) {
|
if (isEditMode.value && questionId) {
|
||||||
await loadQuestionData(questionId);
|
// 优先从路由参数中获取数据
|
||||||
|
if (route.query.questionData) {
|
||||||
|
try {
|
||||||
|
const questionData = JSON.parse(route.query.questionData as string);
|
||||||
|
console.log('📊 从路由参数获取题目数据:', questionData);
|
||||||
|
renderQuestionData(questionData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ 解析路由参数中的题目数据失败:', error);
|
||||||
|
// 如果解析失败,尝试从API加载
|
||||||
|
await loadQuestionData(questionId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果没有路由参数,从API加载
|
||||||
|
await loadQuestionData(questionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 渲染题目数据
|
||||||
|
const renderQuestionData = (questionData: any) => {
|
||||||
|
console.log('🎨 开始渲染题目数据:', questionData);
|
||||||
|
|
||||||
|
if (!questionData) return;
|
||||||
|
|
||||||
|
const { question, answer = [], children = [] } = questionData;
|
||||||
|
|
||||||
|
if (question) {
|
||||||
|
// 设置基本信息
|
||||||
|
questionForm.type = getQuestionTypeKey(question.type);
|
||||||
|
questionForm.title = question.content || '';
|
||||||
|
questionForm.explanation = question.analysis || '';
|
||||||
|
questionForm.score = question.score || 10;
|
||||||
|
questionForm.difficulty = question.difficulty || 0;
|
||||||
|
|
||||||
|
console.log('📝 题目基本信息:', {
|
||||||
|
type: questionForm.type,
|
||||||
|
title: questionForm.title,
|
||||||
|
explanation: questionForm.explanation,
|
||||||
|
score: questionForm.score
|
||||||
|
});
|
||||||
|
|
||||||
|
// 根据题目类型处理选项和答案
|
||||||
|
if (question.type === 0) { // 单选题
|
||||||
|
renderSingleChoiceData(answer);
|
||||||
|
} else if (question.type === 1) { // 多选题
|
||||||
|
renderMultipleChoiceData(answer);
|
||||||
|
} else if (question.type === 2) { // 判断题
|
||||||
|
renderTrueFalseData(answer);
|
||||||
|
} else if (question.type === 3) { // 填空题
|
||||||
|
renderFillBlankData(answer);
|
||||||
|
} else if (question.type === 4) { // 简答题
|
||||||
|
renderShortAnswerData(answer);
|
||||||
|
} else if (question.type === 5) { // 复合题
|
||||||
|
renderCompositeData(children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 渲染单选题数据
|
||||||
|
const renderSingleChoiceData = (answers: any[]) => {
|
||||||
|
console.log('🔘 渲染单选题数据:', answers);
|
||||||
|
|
||||||
|
if (answers && answers.length > 0) {
|
||||||
|
// 按orderNo排序
|
||||||
|
const sortedAnswers = answers.sort((a, b) => a.orderNo - b.orderNo);
|
||||||
|
|
||||||
|
// 设置选项
|
||||||
|
questionForm.options = sortedAnswers.map(answer => ({
|
||||||
|
content: answer.content || ''
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 设置正确答案(orderNo从1开始,数组索引从0开始)
|
||||||
|
const correctAnswer = sortedAnswers.find(answer => answer.izCorrent === 1);
|
||||||
|
if (correctAnswer) {
|
||||||
|
questionForm.correctAnswer = correctAnswer.orderNo - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ 单选题渲染完成:', {
|
||||||
|
options: questionForm.options,
|
||||||
|
correctAnswer: questionForm.correctAnswer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 渲染多选题数据
|
||||||
|
const renderMultipleChoiceData = (answers: any[]) => {
|
||||||
|
console.log('☑️ 渲染多选题数据:', answers);
|
||||||
|
|
||||||
|
if (answers && answers.length > 0) {
|
||||||
|
// 按orderNo排序
|
||||||
|
const sortedAnswers = answers.sort((a, b) => a.orderNo - b.orderNo);
|
||||||
|
|
||||||
|
// 设置选项
|
||||||
|
questionForm.options = sortedAnswers.map(answer => ({
|
||||||
|
content: answer.content || ''
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 设置正确答案(可能有多个)
|
||||||
|
questionForm.correctAnswers = sortedAnswers
|
||||||
|
.filter(answer => answer.izCorrent === 1)
|
||||||
|
.map(answer => answer.orderNo - 1);
|
||||||
|
|
||||||
|
console.log('✅ 多选题渲染完成:', {
|
||||||
|
options: questionForm.options,
|
||||||
|
correctAnswers: questionForm.correctAnswers
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 渲染判断题数据
|
||||||
|
const renderTrueFalseData = (answers: any[]) => {
|
||||||
|
console.log('✔️ 渲染判断题数据:', answers);
|
||||||
|
|
||||||
|
if (answers && answers.length > 0) {
|
||||||
|
const correctAnswer = answers.find(answer => answer.izCorrent === 1);
|
||||||
|
if (correctAnswer) {
|
||||||
|
// 假设判断题的正确答案content为"正确"或"错误"
|
||||||
|
questionForm.trueFalseAnswer = correctAnswer.content === '正确' || correctAnswer.content === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ 判断题渲染完成:', {
|
||||||
|
trueFalseAnswer: questionForm.trueFalseAnswer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 渲染填空题数据
|
||||||
|
const renderFillBlankData = (answers: any[]) => {
|
||||||
|
console.log('📝 渲染填空题数据:', answers);
|
||||||
|
|
||||||
|
if (answers && answers.length > 0) {
|
||||||
|
questionForm.fillBlankAnswers = answers.map(answer => ({
|
||||||
|
content: answer.content || '',
|
||||||
|
score: 1,
|
||||||
|
caseSensitive: false
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.log('✅ 填空题渲染完成:', {
|
||||||
|
fillBlankAnswers: questionForm.fillBlankAnswers
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 渲染简答题数据
|
||||||
|
const renderShortAnswerData = (answers: any[]) => {
|
||||||
|
console.log('📄 渲染简答题数据:', answers);
|
||||||
|
|
||||||
|
if (answers && answers.length > 0) {
|
||||||
|
questionForm.shortAnswer = answers[0]?.content || '';
|
||||||
|
|
||||||
|
console.log('✅ 简答题渲染完成:', {
|
||||||
|
shortAnswer: questionForm.shortAnswer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 渲染复合题数据
|
||||||
|
const renderCompositeData = (children: any[]) => {
|
||||||
|
console.log('🔗 渲染复合题数据:', children);
|
||||||
|
|
||||||
|
if (children && children.length > 0) {
|
||||||
|
questionForm.compositeData = {
|
||||||
|
subQuestions: children.map((child: any) => ({
|
||||||
|
id: child.question?.id,
|
||||||
|
type: getQuestionTypeKey(child.question?.type || 0),
|
||||||
|
title: child.question?.content || '',
|
||||||
|
explanation: child.question?.analysis || '',
|
||||||
|
score: child.question?.score || 1,
|
||||||
|
options: child.answer || [],
|
||||||
|
correctAnswer: null,
|
||||||
|
correctAnswers: []
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('✅ 复合题渲染完成:', {
|
||||||
|
subQuestions: questionForm.compositeData.subQuestions.length
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 加载题目数据(编辑模式使用)
|
// 加载题目数据(编辑模式使用)
|
||||||
const loadQuestionData = async (id: string) => {
|
const loadQuestionData = async (id: string) => {
|
||||||
try {
|
try {
|
||||||
// TODO: 实现编辑模式的数据加载
|
console.log('🚀 开始加载题目数据,题目ID:', id);
|
||||||
// const response = await ExamApi.getQuestionDetail(id);
|
|
||||||
// if (response.data) {
|
// 调用题目详情接口
|
||||||
// // 根据返回的数据回显表单
|
const response = await ExamApi.getQuestionDetail(id);
|
||||||
// }
|
console.log('📊 题目详情API响应:', response);
|
||||||
console.log('加载题目数据,题目ID:', id);
|
|
||||||
message.info('编辑模式数据加载暂未实现');
|
// 处理API响应
|
||||||
|
let questionData = null;
|
||||||
|
let success = false;
|
||||||
|
|
||||||
|
if (response.data) {
|
||||||
|
const apiResponse = response.data as any;
|
||||||
|
|
||||||
|
// 检查是否是包装格式 {success, code, result}
|
||||||
|
if (typeof apiResponse === 'object' && 'result' in apiResponse) {
|
||||||
|
success = apiResponse.success === true || apiResponse.code === 200 || apiResponse.code === 0;
|
||||||
|
questionData = apiResponse.result;
|
||||||
|
} else {
|
||||||
|
// 直接是题目数据
|
||||||
|
success = true;
|
||||||
|
questionData = apiResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success && questionData) {
|
||||||
|
console.log('✅ 获取题目详情成功,开始渲染数据');
|
||||||
|
renderQuestionData(questionData);
|
||||||
|
} else {
|
||||||
|
console.error('❌ 获取题目详情失败');
|
||||||
|
message.error('获取题目详情失败');
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载题目数据错误:', error);
|
console.error('❌ 加载题目数据异常:', error);
|
||||||
message.error('加载题目数据失败,请检查网络连接');
|
message.error('加载题目数据失败,请检查网络连接');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const getDifficultyLabel = (difficulty: string): string => {
|
const getDifficultyLabel = (difficulty: number | string): string => {
|
||||||
const difficultyMap: { [key: string]: string } = {
|
const difficultyMap: { [key: number]: string } = {
|
||||||
|
0: '简单',
|
||||||
|
1: '中等',
|
||||||
|
2: '困难'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果是数字,直接映射
|
||||||
|
if (typeof difficulty === 'number') {
|
||||||
|
return difficultyMap[difficulty] || '未知';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是字符串,先转换为数字再映射
|
||||||
|
const stringMap: { [key: string]: string } = {
|
||||||
'easy': '简单',
|
'easy': '简单',
|
||||||
'medium': '中等',
|
'medium': '中等',
|
||||||
'hard': '困难'
|
'hard': '困难'
|
||||||
};
|
};
|
||||||
return difficultyMap[difficulty] || difficulty;
|
return stringMap[difficulty] || difficulty;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCategoryLabel = (category: string): string => {
|
const getCategoryLabel = (category: string): string => {
|
||||||
|
@ -302,6 +302,11 @@ const createColumns = ({
|
|||||||
width: 300,
|
width: 300,
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
tooltip: true
|
tooltip: true
|
||||||
|
},
|
||||||
|
render(row: Question) {
|
||||||
|
// 如果是子题目,添加缩进显示
|
||||||
|
const prefix = row.parentId ? ' └ ' : '';
|
||||||
|
return prefix + row.title;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -311,11 +316,12 @@ const createColumns = ({
|
|||||||
align: 'center' as const,
|
align: 'center' as const,
|
||||||
render(row: Question) {
|
render(row: Question) {
|
||||||
const typeMap: { [key: string]: { text: string; type: any } } = {
|
const typeMap: { [key: string]: { text: string; type: any } } = {
|
||||||
'single_choice': { text: '单选题', type: 'info' },
|
'单选题': { text: '单选题', type: 'info' },
|
||||||
'multiple_choice': { text: '多选题', type: 'warning' },
|
'多选题': { text: '多选题', type: 'warning' },
|
||||||
'true_false': { text: '判断题', type: 'success' },
|
'判断题': { text: '判断题', type: 'success' },
|
||||||
'fill_blank': { text: '填空题', type: 'error' },
|
'填空题': { text: '填空题', type: 'error' },
|
||||||
'short_answer': { text: '简答题', type: 'default' }
|
'简答题': { text: '简答题', type: 'default' },
|
||||||
|
'复合题': { text: '复合题', type: 'primary' }
|
||||||
};
|
};
|
||||||
const typeInfo = typeMap[row.type] || { text: row.type, type: 'default' };
|
const typeInfo = typeMap[row.type] || { text: row.type, type: 'default' };
|
||||||
return h(NTag, { type: typeInfo.type, size: 'small' }, { default: () => typeInfo.text });
|
return h(NTag, { type: typeInfo.type, size: 'small' }, { default: () => typeInfo.text });
|
||||||
@ -338,9 +344,9 @@ const createColumns = ({
|
|||||||
align: 'center' as const,
|
align: 'center' as const,
|
||||||
render(row: Question) {
|
render(row: Question) {
|
||||||
const difficultyMap: { [key: string]: { text: string; type: any } } = {
|
const difficultyMap: { [key: string]: { text: string; type: any } } = {
|
||||||
'easy': { text: '易', type: 'success' },
|
'简单': { text: '简单', type: 'success' },
|
||||||
'medium': { text: '中', type: 'warning' },
|
'中等': { text: '中等', type: 'warning' },
|
||||||
'hard': { text: '难', type: 'error' }
|
'困难': { text: '困难', type: 'error' }
|
||||||
};
|
};
|
||||||
const diffInfo = difficultyMap[row.difficulty] || { text: row.difficulty, type: 'default' };
|
const diffInfo = difficultyMap[row.difficulty] || { text: row.difficulty, type: 'default' };
|
||||||
return h(NTag, { type: diffInfo.type, size: 'small' }, { default: () => diffInfo.text });
|
return h(NTag, { type: diffInfo.type, size: 'small' }, { default: () => diffInfo.text });
|
||||||
@ -450,6 +456,29 @@ const searchQuestions = () => {
|
|||||||
loadQuestions();
|
loadQuestions();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 题目类型转换函数
|
||||||
|
const getQuestionTypeText = (type: number): string => {
|
||||||
|
const typeMap: { [key: number]: string } = {
|
||||||
|
0: '单选题',
|
||||||
|
1: '多选题',
|
||||||
|
2: '判断题',
|
||||||
|
3: '填空题',
|
||||||
|
4: '简答题',
|
||||||
|
5: '复合题'
|
||||||
|
};
|
||||||
|
return typeMap[type] || '未知类型';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 难度转换函数
|
||||||
|
const getDifficultyText = (difficulty: number): string => {
|
||||||
|
const difficultyMap: { [key: number]: string } = {
|
||||||
|
0: '简单',
|
||||||
|
1: '中等',
|
||||||
|
2: '困难'
|
||||||
|
};
|
||||||
|
return difficultyMap[difficulty] || '未知';
|
||||||
|
};
|
||||||
|
|
||||||
// 加载题目列表
|
// 加载题目列表
|
||||||
const loadQuestions = async () => {
|
const loadQuestions = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
@ -463,18 +492,20 @@ const loadQuestions = async () => {
|
|||||||
let allData: Question[] = [];
|
let allData: Question[] = [];
|
||||||
|
|
||||||
// 处理API响应数据
|
// 处理API响应数据
|
||||||
if (response.code === 200 && response.data) {
|
if (response.data && (response.data.code === 200 || response.data.code === 0) && response.data.result) {
|
||||||
// 将API返回的数据转换为前端格式
|
// 将API返回的数据转换为前端格式
|
||||||
allData = response.data.map((item: any, index: number) => ({
|
allData = response.data.result.map((item: any, index: number) => ({
|
||||||
id: item.id || `question_${index}`,
|
id: item.id || `question_${index}`,
|
||||||
sequence: index + 1,
|
sequence: index + 1,
|
||||||
title: item.title || item.content || '题目内容',
|
title: item.content || '题目内容',
|
||||||
type: item.type || '单选题',
|
type: getQuestionTypeText(item.type),
|
||||||
category: item.category || '未分类',
|
category: item.category || '未分类',
|
||||||
difficulty: item.difficulty || '简单',
|
difficulty: getDifficultyText(item.difficulty),
|
||||||
score: item.score || 10,
|
score: item.score || 10,
|
||||||
creator: item.createBy || item.creator || '未知',
|
creator: item.createBy || '未知',
|
||||||
createTime: item.createTime || new Date().toISOString()
|
createTime: item.createTime || new Date().toISOString(),
|
||||||
|
parentId: item.parentId,
|
||||||
|
analysis: item.analysis
|
||||||
}));
|
}));
|
||||||
console.log('✅ 题目数据转换成功:', allData.length, '条题目');
|
console.log('✅ 题目数据转换成功:', allData.length, '条题目');
|
||||||
} else {
|
} else {
|
||||||
@ -560,13 +591,103 @@ const deleteSelected = () => {
|
|||||||
console.log('批量删除:', selectedRowKeys.value);
|
console.log('批量删除:', selectedRowKeys.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const editQuestion = (id: string) => {
|
const editQuestion = async (id: string) => {
|
||||||
console.log('编辑题目:', id);
|
console.log('🔍 编辑题目,题目ID:', id);
|
||||||
router.push(`/teacher/exam-management/add-question/${currentBankId.value}/${id}`);
|
|
||||||
|
try {
|
||||||
|
// 先调用题目详情接口获取完整信息
|
||||||
|
console.log('🚀 调用题目详情接口...');
|
||||||
|
const response = await ExamApi.getQuestionDetail(id);
|
||||||
|
console.log('📊 题目详情API响应:', response);
|
||||||
|
|
||||||
|
// 处理API响应,支持不同的响应格式
|
||||||
|
let questionData = null;
|
||||||
|
let success = false;
|
||||||
|
|
||||||
|
if (response.data) {
|
||||||
|
// 使用类型断言处理API响应
|
||||||
|
const apiResponse = response.data as any;
|
||||||
|
|
||||||
|
// 检查是否是包装格式 {success, code, result}
|
||||||
|
if (typeof apiResponse === 'object' && 'result' in apiResponse) {
|
||||||
|
success = apiResponse.success === true || apiResponse.code === 200 || apiResponse.code === 0;
|
||||||
|
questionData = apiResponse.result;
|
||||||
|
} else {
|
||||||
|
// 直接是题目数据
|
||||||
|
success = true;
|
||||||
|
questionData = apiResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success && questionData) {
|
||||||
|
console.log('✅ 获取题目详情成功:', questionData);
|
||||||
|
|
||||||
|
// 跳转到编辑页面,并传递题目详情数据
|
||||||
|
router.push({
|
||||||
|
path: `/teacher/exam-management/add-question/${currentBankId.value}/${id}`,
|
||||||
|
query: {
|
||||||
|
questionData: JSON.stringify(questionData),
|
||||||
|
mode: 'edit'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('❌ 获取题目详情失败:', response);
|
||||||
|
message.error('获取题目详情失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ 获取题目详情异常:', error);
|
||||||
|
message.error('获取题目详情失败,请稍后重试');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteQuestion = (id: string) => {
|
const deleteQuestion = async (id: string) => {
|
||||||
console.log('删除题目:', id);
|
console.log('🗑️ 删除题目,题目ID:', id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 确认删除
|
||||||
|
const confirmed = await new Promise((resolve) => {
|
||||||
|
const dialog = window.confirm('确定要删除这道题目吗?删除后将无法恢复!');
|
||||||
|
resolve(dialog);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!confirmed) {
|
||||||
|
console.log('用户取消删除');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🚀 调用删除题目API...');
|
||||||
|
const response = await ExamApi.deleteQuestion(id);
|
||||||
|
console.log('📊 删除题目API响应:', response);
|
||||||
|
|
||||||
|
// 处理API响应
|
||||||
|
let success = false;
|
||||||
|
|
||||||
|
if (response.data) {
|
||||||
|
const apiResponse = response.data as any;
|
||||||
|
|
||||||
|
// 检查是否是包装格式 {success, code, result}
|
||||||
|
if (typeof apiResponse === 'object' && ('success' in apiResponse || 'code' in apiResponse)) {
|
||||||
|
success = apiResponse.success === true || apiResponse.code === 200 || apiResponse.code === 0;
|
||||||
|
} else {
|
||||||
|
// 直接成功
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
console.log('✅ 删除题目成功');
|
||||||
|
message.success('题目删除成功');
|
||||||
|
|
||||||
|
// 重新加载题目列表
|
||||||
|
await loadQuestions();
|
||||||
|
} else {
|
||||||
|
console.error('❌ 删除题目失败');
|
||||||
|
message.error('删除题目失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ 删除题目异常:', error);
|
||||||
|
message.error('删除题目失败,请稍后重试');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 组件挂载时加载数据
|
// 组件挂载时加载数据
|
||||||
|
Loading…
x
Reference in New Issue
Block a user