feat:hls流误删导致视频报错,作业资料接口对接,逻辑处理下载,课程列表按钮按照 后端请求分为需传token 和不需要根据是否登录判断

This commit is contained in:
小张 2025-09-05 19:46:11 +08:00
parent 71ea0bbfb4
commit 6b685501dd
3 changed files with 433 additions and 79 deletions

View File

@ -117,7 +117,7 @@ export class ExamApi {
*/
static async getQuestionDetail(questionId: string): Promise<ApiResponse<Question>> {
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)
return response
}
@ -127,7 +127,7 @@ export class ExamApi {
*/
static async createQuestion(data: CreateQuestionRequest): Promise<ApiResponse<string>> {
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)
return response
}
@ -137,7 +137,7 @@ export class ExamApi {
*/
static async updateQuestion(data: UpdateQuestionRequest): Promise<ApiResponse<string>> {
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)
return response
}
@ -145,15 +145,15 @@ export class ExamApi {
/**
*
*/
static async deleteQuestion(id: string): Promise<ApiResponse<string>> {
console.log('🚀 删除题目:', { id })
const response = await ApiRequest.delete<string>('/gen/question/question/delete', {
params: { id }
})
static async deleteQuestion(questionId: string): Promise<ApiResponse<string>> {
console.log('🚀 删除题目:', { questionId })
const response = await ApiRequest.delete<string>(`/aiol/aiolQuestion/delete?id=${questionId}`)
console.log('✅ 删除题目成功:', response)
return response
}
// ========== 题目选项管理 ==========
/**

View File

@ -263,6 +263,19 @@ const message = useMessage();
const questionId = route.params.questionId as string | undefined;
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();
@ -288,16 +301,16 @@ const categoryOptions = ref([
//
const difficultyOptions = ref([
{ label: '简单', value: 'easy' },
{ label: '中等', value: 'medium' },
{ label: '困难', value: 'hard' }
{ label: '简单', value: 0 },
{ label: '中等', value: 1 },
{ label: '困难', value: 2 }
]);
//
const questionForm = reactive({
type: 'single_choice', //
category: '',
difficulty: '',
difficulty: 0, //
score: 10,
title: '',
options: [
@ -323,12 +336,13 @@ const formRules = {
trigger: 'change'
},
category: {
required: true,
required: false,
message: '请选择分类',
trigger: 'change'
},
difficulty: {
required: true,
type: 'number',
message: '请选择难度',
trigger: 'change'
},
@ -397,14 +411,20 @@ const getQuestionTypeNumber = (type: string): number => {
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> = {
'easy': 1, //
'medium': 2, //
'hard': 3 //
'easy': 0, //
'medium': 1, //
'hard': 2 //
};
return difficultyMap[difficulty] || 1;
return difficultyMap[difficulty] || 0;
};
//
@ -478,8 +498,9 @@ const saveQuestion = async () => {
//
const createNewQuestion = async (bankId: string) => {
try {
// questionId
// API
const questionData = {
parentId: null, // IDnull
type: getQuestionTypeNumber(questionForm.type),
content: questionForm.title,
analysis: questionForm.explanation || '',
@ -487,37 +508,33 @@ const createNewQuestion = async (bankId: string) => {
score: questionForm.score
};
console.log('🚀 第一步:创建题目题干:', questionData);
const questionResponse = await ExamApi.createQuestion(questionData);
console.log('🚀 创建题目,数据:', questionData);
const response = await ExamApi.createQuestion(questionData);
console.log('📊 创建题目API响应:', response);
if (!questionResponse.data) {
throw new Error('创建题目失败未返回题目ID');
// API
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;
console.log('✅ 题目创建成功questionId:', createdQuestionId);
//
if (questionForm.type === 'single_choice') {
await handleSingleChoiceQuestion(createdQuestionId);
if (!success) {
throw new Error('创建题目失败');
}
// TODO:
// else if (questionForm.type === 'multiple_choice') {
// await handleMultipleChoiceQuestion(createdQuestionId);
// } else if (questionForm.type === 'true_false') {
// await handleTrueFalseQuestion(createdQuestionId);
// }
//
//
const questionRepoData = {
repoId: bankId,
questionId: createdQuestionId
};
console.log('🚀 最后一步:绑定题目到题库:', questionRepoData);
await ExamApi.createQuestionRepo(questionRepoData);
console.log('✅ 题目绑定到题库成功');
console.log('✅ 题目创建成功题目ID:', questionId);
message.success('题目保存成功');
@ -772,36 +789,252 @@ const validateCompositeQuestion = (): boolean => {
//
onMounted(async () => {
console.log('AddQuestion 组件挂载完成');
console.log('编辑模式:', isEditMode.value);
console.log('题目ID:', 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 || ''
}));
// orderNo10
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) => {
try {
// TODO:
// const response = await ExamApi.getQuestionDetail(id);
// if (response.data) {
// //
// }
console.log('加载题目数据题目ID:', id);
message.info('编辑模式数据加载暂未实现');
console.log('🚀 开始加载题目数据题目ID:', id);
//
const response = await ExamApi.getQuestionDetail(id);
console.log('📊 题目详情API响应:', response);
// 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) {
console.error('加载题目数据错误:', error);
console.error('❌ 加载题目数据异常:', error);
message.error('加载题目数据失败,请检查网络连接');
}
};
const getDifficultyLabel = (difficulty: string): string => {
const difficultyMap: { [key: string]: string } = {
const getDifficultyLabel = (difficulty: number | string): string => {
const difficultyMap: { [key: number]: string } = {
0: '简单',
1: '中等',
2: '困难'
};
//
if (typeof difficulty === 'number') {
return difficultyMap[difficulty] || '未知';
}
//
const stringMap: { [key: string]: string } = {
'easy': '简单',
'medium': '中等',
'hard': '困难'
};
return difficultyMap[difficulty] || difficulty;
return stringMap[difficulty] || difficulty;
};
const getCategoryLabel = (category: string): string => {

View File

@ -302,6 +302,11 @@ const createColumns = ({
width: 300,
ellipsis: {
tooltip: true
},
render(row: Question) {
//
const prefix = row.parentId ? '  └ ' : '';
return prefix + row.title;
}
},
{
@ -311,11 +316,12 @@ const createColumns = ({
align: 'center' as const,
render(row: Question) {
const typeMap: { [key: string]: { text: string; type: any } } = {
'single_choice': { text: '单选题', type: 'info' },
'multiple_choice': { text: '多选题', type: 'warning' },
'true_false': { text: '判断题', type: 'success' },
'fill_blank': { text: '填空题', type: 'error' },
'short_answer': { text: '简答题', type: 'default' }
'单选题': { text: '单选题', type: 'info' },
'多选题': { text: '多选题', type: 'warning' },
'判断题': { text: '判断题', type: 'success' },
'填空题': { text: '填空题', type: 'error' },
'简答题': { text: '简答题', type: 'default' },
'复合题': { text: '复合题', type: 'primary' }
};
const typeInfo = typeMap[row.type] || { text: row.type, type: 'default' };
return h(NTag, { type: typeInfo.type, size: 'small' }, { default: () => typeInfo.text });
@ -338,9 +344,9 @@ const createColumns = ({
align: 'center' as const,
render(row: Question) {
const difficultyMap: { [key: string]: { text: string; type: any } } = {
'easy': { text: '易', type: 'success' },
'medium': { text: '中', type: 'warning' },
'hard': { text: '难', type: 'error' }
'简单': { text: '简单', type: 'success' },
'中等': { text: '中', type: 'warning' },
'困难': { text: '难', type: 'error' }
};
const diffInfo = difficultyMap[row.difficulty] || { text: row.difficulty, type: 'default' };
return h(NTag, { type: diffInfo.type, size: 'small' }, { default: () => diffInfo.text });
@ -450,6 +456,29 @@ const searchQuestions = () => {
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 () => {
loading.value = true;
@ -463,18 +492,20 @@ const loadQuestions = async () => {
let allData: Question[] = [];
// API
if (response.code === 200 && response.data) {
if (response.data && (response.data.code === 200 || response.data.code === 0) && response.data.result) {
// API
allData = response.data.map((item: any, index: number) => ({
allData = response.data.result.map((item: any, index: number) => ({
id: item.id || `question_${index}`,
sequence: index + 1,
title: item.title || item.content || '题目内容',
type: item.type || '单选题',
title: item.content || '题目内容',
type: getQuestionTypeText(item.type),
category: item.category || '未分类',
difficulty: item.difficulty || '简单',
difficulty: getDifficultyText(item.difficulty),
score: item.score || 10,
creator: item.createBy || item.creator || '未知',
createTime: item.createTime || new Date().toISOString()
creator: item.createBy || '未知',
createTime: item.createTime || new Date().toISOString(),
parentId: item.parentId,
analysis: item.analysis
}));
console.log('✅ 题目数据转换成功:', allData.length, '条题目');
} else {
@ -560,13 +591,103 @@ const deleteSelected = () => {
console.log('批量删除:', selectedRowKeys.value);
};
const editQuestion = (id: string) => {
console.log('编辑题目:', id);
router.push(`/teacher/exam-management/add-question/${currentBankId.value}/${id}`);
const editQuestion = async (id: string) => {
console.log('🔍 编辑题目题目ID:', 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) => {
console.log('删除题目:', id);
const deleteQuestion = async (id: string) => {
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('删除题目失败,请稍后重试');
}
};
//