feat:练习讨论对接接口
This commit is contained in:
parent
7aa5257cbd
commit
ce54a41f4a
@ -176,6 +176,7 @@ export class AIApi {
|
||||
|
||||
const decoder = new TextDecoder()
|
||||
let buffer = ''
|
||||
// @ts-ignore
|
||||
let messageEndReceived = false
|
||||
let endTimeout: NodeJS.Timeout | null = null
|
||||
|
||||
@ -330,20 +331,21 @@ export class AIApi {
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
static async sendChatMessageWithEventSource(
|
||||
content: string,
|
||||
// @ts-ignore
|
||||
content: string, // TODO: 需要在实际实现中使用此参数
|
||||
onMessage: (chunk: string) => void,
|
||||
onComplete?: () => void,
|
||||
onError?: (error: any) => void
|
||||
): Promise<void> {
|
||||
const request: AIChatRequest = {
|
||||
appId: "1970031066993217537",
|
||||
content: content,
|
||||
responseMode: "streaming"
|
||||
}
|
||||
// const request: AIChatRequest = {
|
||||
// appId: "1970031066993217537",
|
||||
// content: content,
|
||||
// responseMode: "streaming"
|
||||
// } // 暂时未使用
|
||||
|
||||
try {
|
||||
// 获取token
|
||||
const token = localStorage.getItem('token')
|
||||
// const token = localStorage.getItem('token') // 暂时未使用
|
||||
|
||||
// 构建URL参数
|
||||
const url = new URL(`${import.meta.env.VITE_API_BASE_URL}/airag/chat/send`)
|
||||
|
@ -916,6 +916,40 @@ export class CourseApi {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取考试题目列表
|
||||
static async getExamQuestions(examId: string, studentId: string): Promise<ApiResponse<any>> {
|
||||
try {
|
||||
console.log('🚀 调用获取考试题目API,考试ID:', examId, '学生ID:', studentId)
|
||||
|
||||
// 直接在URL中添加studentId参数
|
||||
const url = `/aiol/aiolExam/getExamQuestions/${examId}?studentId=${studentId}`
|
||||
console.log('🔍 请求URL:', url)
|
||||
|
||||
const response = await ApiRequest.get<any>(url)
|
||||
console.log('🔍 考试题目API响应:', response)
|
||||
|
||||
return response
|
||||
} catch (error) {
|
||||
console.error('❌ 获取考试题目失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 获取题目详情
|
||||
static async getQuestionDetail(questionId: string): Promise<ApiResponse<any>> {
|
||||
try {
|
||||
console.log('🚀 调用获取题目详情API,题目ID:', questionId)
|
||||
|
||||
const response = await ApiRequest.get<any>(`/aiol/aiolRepo/repoList/${questionId}`)
|
||||
console.log('🔍 题目详情API响应:', response)
|
||||
|
||||
return response
|
||||
} catch (error) {
|
||||
console.error('❌ 获取题目详情失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 获取章节讨论
|
||||
static async getSectionDiscussion(courseId: string, sectionId: string): Promise<ApiResponse<any>> {
|
||||
try {
|
||||
|
@ -220,7 +220,7 @@ const categoryList = ref<CourseCategory[]>([]);
|
||||
const repoOptions = computed(() => [
|
||||
{ label: '全部题库', value: '' },
|
||||
...repoList.value.map((repo: Repo) => ({
|
||||
label: `${repo.title} (${repo.questionCount || 0}题)`,
|
||||
label: `${repo.title} (${repo.question_count || 0}题)`,
|
||||
value: repo.id
|
||||
}))
|
||||
]);
|
||||
|
@ -664,6 +664,9 @@ const createManualQualityButton = () => {
|
||||
option.addEventListener('mouseleave', () => {
|
||||
if (quality.value !== props.currentQuality) {
|
||||
option.style.backgroundColor = 'transparent'
|
||||
} else {
|
||||
// 如果是当前选中的清晰度,保持蓝色背景
|
||||
option.style.backgroundColor = '#007bff'
|
||||
}
|
||||
})
|
||||
|
||||
@ -698,6 +701,11 @@ const createManualQualityButton = () => {
|
||||
// 标记按钮已创建
|
||||
qualityButtonCreated.value = true
|
||||
|
||||
// 初始化菜单选项样式
|
||||
setTimeout(() => {
|
||||
updateQualityMenuStyles(props.currentQuality)
|
||||
}, 100)
|
||||
|
||||
console.log('✅ 手动清晰度按钮创建完成')
|
||||
}
|
||||
|
||||
@ -707,6 +715,68 @@ const getCurrentQualityLabel = () => {
|
||||
return current ? current.label : '360p'
|
||||
}
|
||||
|
||||
// 更新清晰度菜单选项的样式
|
||||
const updateQualityMenuStyles = (currentQualityValue: string) => {
|
||||
const qualityMenu = dplayerContainer.value?.querySelector('.manual-quality .dplayer-quality-list')
|
||||
if (qualityMenu) {
|
||||
const qualityItems = qualityMenu.querySelectorAll('.dplayer-quality-item')
|
||||
qualityItems.forEach((item, index) => {
|
||||
const quality = props.videoQualities[index]
|
||||
if (quality) {
|
||||
const isActive = quality.value === currentQualityValue
|
||||
const itemElement = item as HTMLElement
|
||||
|
||||
// 设置基础样式
|
||||
itemElement.style.cssText = `
|
||||
padding: 8px 12px;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
text-align: center;
|
||||
${isActive ? 'background: #007bff;' : 'background: transparent;'}
|
||||
`
|
||||
|
||||
// 重新绑定鼠标事件,确保当前选中项的样式正确
|
||||
const newItemElement = itemElement.cloneNode(true) as HTMLElement
|
||||
itemElement.parentNode?.replaceChild(newItemElement, itemElement)
|
||||
|
||||
// 重新绑定事件
|
||||
newItemElement.addEventListener('mouseenter', () => {
|
||||
if (quality.value !== currentQualityValue) {
|
||||
newItemElement.style.backgroundColor = 'rgba(255, 255, 255, 0.1)'
|
||||
}
|
||||
})
|
||||
|
||||
newItemElement.addEventListener('mouseleave', () => {
|
||||
if (quality.value !== currentQualityValue) {
|
||||
newItemElement.style.backgroundColor = 'transparent'
|
||||
} else {
|
||||
// 如果是当前选中的清晰度,保持蓝色背景
|
||||
newItemElement.style.backgroundColor = '#007bff'
|
||||
}
|
||||
})
|
||||
|
||||
newItemElement.addEventListener('click', () => {
|
||||
console.log('🔄 手动切换清晰度到:', quality.label)
|
||||
switchQuality(quality)
|
||||
;(qualityMenu as HTMLElement).style.display = 'none'
|
||||
|
||||
// 更新按钮文字
|
||||
const qualityButton = dplayerContainer.value?.querySelector('.manual-quality .dplayer-quality-button')
|
||||
if (qualityButton) {
|
||||
qualityButton.textContent = quality.label
|
||||
}
|
||||
|
||||
// 不需要在这里再次调用updateQualityMenuStyles,因为switchQuality会处理
|
||||
})
|
||||
|
||||
console.log(`🎨 更新清晰度选项样式: ${quality.label} - ${isActive ? '激活' : '未激活'}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const switchQuality = (quality: any) => {
|
||||
console.log('🔄 开始切换清晰度:', {
|
||||
quality: quality,
|
||||
@ -814,6 +884,9 @@ const switchQuality = (quality: any) => {
|
||||
existingButton.textContent = quality.label
|
||||
console.log('✅ 清晰度按钮文字已立即更新为:', quality.label)
|
||||
}
|
||||
|
||||
// 更新清晰度菜单选项的样式
|
||||
updateQualityMenuStyles(quality.value)
|
||||
}
|
||||
|
||||
|
||||
|
@ -345,13 +345,13 @@
|
||||
<div class="discussion-container">
|
||||
<!-- 讨论标题行 -->
|
||||
<div class="discussion-title-row">
|
||||
<h2 class="discussion-title">讨论</h2>
|
||||
<h2 class="discussion-title">{{ discussionTitle }}</h2>
|
||||
<span class="participation-status">未参与</span>
|
||||
</div>
|
||||
|
||||
<!-- 讨论描述 -->
|
||||
<div class="discussion-description">
|
||||
如何理解学风与科研诚信?如何理解优良学风与科研诚信之间的关系?各位同学大家好,欢迎加入本学期的课程学习,在学习过程有任何问题困惑和不同见解,都欢迎同学在讨论区积极交流,踊跃回复老师留在讨论区的问题。
|
||||
{{ discussionDescription }}
|
||||
</div>
|
||||
|
||||
<!-- 评论统计 -->
|
||||
@ -1347,6 +1347,7 @@ import { useMessage } from 'naive-ui'
|
||||
import { CourseApi } from '@/api/modules/course'
|
||||
import { CommentApi } from '@/api/modules/comment'
|
||||
import { AIApi } from '@/api/modules/ai'
|
||||
import { AuthApi } from '@/api/modules/auth'
|
||||
import type { Course, CourseSection, CourseComment } from '@/api/types'
|
||||
import QuillEditor from '@/components/common/QuillEditor.vue'
|
||||
import DPlayerVideo from '@/components/course/DPlayerVideo.vue'
|
||||
@ -1580,6 +1581,8 @@ const practiceFinished = ref(false)
|
||||
const discussionMode = ref(false)
|
||||
const currentDiscussionSection = ref<CourseSection | null>(null)
|
||||
const discussionList = ref<any[]>([])
|
||||
const discussionTitle = ref('讨论')
|
||||
const discussionDescription = ref('')
|
||||
const newComment = ref('')
|
||||
const replyingTo = ref<any>(null)
|
||||
|
||||
@ -2124,71 +2127,13 @@ const loadCourseSections = async () => {
|
||||
console.log('✅ API返回的原始章节数据:', response.data.list)
|
||||
console.log('✅ 章节数据数量:', response.data.list.length)
|
||||
|
||||
// 添加模拟练习章节
|
||||
const sectionsWithPractice = [...response.data.list]
|
||||
|
||||
// 添加一个练习章节到第一章
|
||||
const practiceSection: CourseSection = {
|
||||
id: '999999', // 使用一个特殊的ID
|
||||
lessonId: '999999',
|
||||
name: 'JavaScript基础练习',
|
||||
type: 5, // 练习类型
|
||||
level: 2, // 二级章节
|
||||
parentId: sectionsWithPractice.find(s => s.level === 1)?.id || '1', // 找到第一个父章节
|
||||
duration: '30分钟',
|
||||
completed: false,
|
||||
outline: '',
|
||||
sort: 999,
|
||||
revision: 1,
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
deletedAt: null
|
||||
}
|
||||
|
||||
// 将练习章节插入到合适的位置(第一章的最后)
|
||||
const firstChapterSections = sectionsWithPractice.filter(s => s.level === 2 && s.parentId === practiceSection.parentId)
|
||||
if (firstChapterSections.length > 0) {
|
||||
// 插入到第一章的最后一个章节后面
|
||||
const insertIndex = sectionsWithPractice.findIndex(s => s.id === firstChapterSections[firstChapterSections.length - 1].id) + 1
|
||||
sectionsWithPractice.splice(insertIndex, 0, practiceSection)
|
||||
} else {
|
||||
// 如果没有找到合适位置,就添加到最后
|
||||
sectionsWithPractice.push(practiceSection)
|
||||
}
|
||||
|
||||
// 添加一个讨论章节
|
||||
const discussionSection: CourseSection = {
|
||||
id: '999998', // 使用另一个特殊的ID
|
||||
lessonId: '999998',
|
||||
name: '机器学习与科研流程讨论',
|
||||
type: 6, // 讨论类型(自定义)
|
||||
level: 2, // 二级章节
|
||||
parentId: sectionsWithPractice.find(s => s.level === 1)?.id || '1', // 找到第一个父章节
|
||||
duration: '讨论',
|
||||
completed: false,
|
||||
outline: '',
|
||||
sort: 998,
|
||||
revision: 1,
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
deletedAt: null
|
||||
}
|
||||
|
||||
// 将讨论章节插入到练习章节后面
|
||||
const practiceIndex = sectionsWithPractice.findIndex(s => s.id === practiceSection.id)
|
||||
if (practiceIndex !== -1) {
|
||||
sectionsWithPractice.splice(practiceIndex + 1, 0, discussionSection)
|
||||
} else {
|
||||
sectionsWithPractice.push(discussionSection)
|
||||
}
|
||||
|
||||
courseSections.value = sectionsWithPractice
|
||||
groupedSections.value = groupSectionsByChapter(sectionsWithPractice)
|
||||
// 直接使用API返回的章节数据
|
||||
courseSections.value = response.data.list
|
||||
groupedSections.value = groupSectionsByChapter(response.data.list)
|
||||
|
||||
console.log('✅ 设置后的courseSections:', courseSections.value)
|
||||
console.log('✅ 设置后的groupedSections:', groupedSections.value)
|
||||
console.log('✅ groupedSections长度:', groupedSections.value.length)
|
||||
console.log('✅ 已添加练习章节:', practiceSection)
|
||||
} else {
|
||||
console.log('❌ API返回的章节数据为空或格式错误')
|
||||
console.log('❌ response.data:', response.data)
|
||||
@ -2499,7 +2444,20 @@ const handlePractice = async (section: CourseSection) => {
|
||||
}
|
||||
|
||||
try {
|
||||
// 调用章节练习API
|
||||
// 第一步:获取用户信息
|
||||
console.log('👤 获取用户信息...')
|
||||
const userInfoResponse = await AuthApi.getUserInfo()
|
||||
|
||||
if (!userInfoResponse.success || !userInfoResponse.result?.baseInfo?.id) {
|
||||
console.error('❌ 获取用户信息失败:', userInfoResponse)
|
||||
message.error('获取用户信息失败,请重新登录')
|
||||
return
|
||||
}
|
||||
|
||||
const studentId = userInfoResponse.result.baseInfo.id
|
||||
console.log('✅ 获取用户信息成功,学生ID:', studentId)
|
||||
|
||||
// 第二步:调用章节练习API获取考试信息
|
||||
const response = await CourseApi.getSectionExercise(courseId.value, section.id.toString())
|
||||
|
||||
if (response.data && (response.data.code === 200 || response.data.code === 0)) {
|
||||
@ -2507,21 +2465,120 @@ const handlePractice = async (section: CourseSection) => {
|
||||
|
||||
// 处理练习数据
|
||||
const exerciseData = response.data.result
|
||||
if (exerciseData && Array.isArray(exerciseData)) {
|
||||
// 设置练习数据
|
||||
practiceQuestions.value = exerciseData
|
||||
currentPracticeSection.value = section
|
||||
practiceMode.value = true
|
||||
practiceStarted.value = true // 直接开始练习,不需要点击开始按钮
|
||||
practiceFinished.value = false
|
||||
currentQuestionIndex.value = 0
|
||||
if (exerciseData && Array.isArray(exerciseData) && exerciseData.length > 0) {
|
||||
// 获取第一个考试的ID
|
||||
const firstExam = exerciseData[0]
|
||||
const examId = firstExam.id
|
||||
|
||||
// 初始化答案数组
|
||||
practiceAnswers.value = new Array(exerciseData.length).fill(null).map(() => [])
|
||||
fillAnswers.value = new Array(exerciseData.length).fill(null).map(() => [])
|
||||
essayAnswers.value = new Array(exerciseData.length).fill('')
|
||||
console.log('🔍 获取到考试信息:', firstExam)
|
||||
console.log('📋 开始获取考试题目,考试ID:', examId, '学生ID:', studentId)
|
||||
|
||||
console.log('✅ 练习模式已启动,题目数量:', practiceQuestions.value.length)
|
||||
// 第三步:根据考试ID和学生ID获取题目列表
|
||||
const questionsResponse = await CourseApi.getExamQuestions(examId, studentId)
|
||||
|
||||
if (questionsResponse.data && (questionsResponse.data.code === 200 || questionsResponse.data.code === 0)) {
|
||||
console.log('✅ 获取考试题目成功:', questionsResponse.data)
|
||||
|
||||
const questionsList = questionsResponse.data.result
|
||||
if (questionsList && Array.isArray(questionsList) && questionsList.length > 0) {
|
||||
console.log('📝 题目列表:', questionsList)
|
||||
|
||||
// 第四步:根据每个题目ID获取详细信息
|
||||
const detailedQuestions = []
|
||||
|
||||
for (const questionItem of questionsList) {
|
||||
try {
|
||||
console.log('🔍 获取题目详情,题目ID:', questionItem.id)
|
||||
const detailResponse = await CourseApi.getQuestionDetail(questionItem.id)
|
||||
|
||||
if (detailResponse.data && (detailResponse.data.code === 200 || detailResponse.data.code === 0)) {
|
||||
const questionDetail = detailResponse.data.result
|
||||
console.log('✅ 获取题目详情成功:', questionDetail)
|
||||
detailedQuestions.push(questionDetail)
|
||||
} else {
|
||||
console.warn('⚠️ 获取题目详情失败:', questionItem.id, detailResponse.data?.message)
|
||||
}
|
||||
} catch (detailError) {
|
||||
console.error('❌ 获取题目详情异常:', questionItem.id, detailError)
|
||||
}
|
||||
}
|
||||
|
||||
if (detailedQuestions.length > 0) {
|
||||
// 处理题目数据格式,确保符合前端显示要求
|
||||
const processedQuestions = detailedQuestions.map((questionData, index) => {
|
||||
console.log(`🔍 处理题目 ${index + 1}:`, questionData)
|
||||
|
||||
// 解析API返回的数据结构
|
||||
const question = questionData.question
|
||||
const answers = questionData.answer || []
|
||||
|
||||
// 题目类型映射:0=单选题,1=多选题,2=判断题,3=填空题,4=简答题
|
||||
const typeMap: { [key: number]: string } = {
|
||||
0: '单选题',
|
||||
1: '多选题',
|
||||
2: '判断题',
|
||||
3: '填空题',
|
||||
4: '简答题'
|
||||
}
|
||||
|
||||
// 提取选项内容
|
||||
const options = answers
|
||||
.sort((a: any, b: any) => a.orderNo - b.orderNo) // 按orderNo排序
|
||||
.map((answer: any) => answer.content)
|
||||
|
||||
// 找出正确答案的索引
|
||||
const correctAnswers = answers
|
||||
.filter((answer: any) => answer.izCorrent === 1)
|
||||
.map((answer: any) => answer.orderNo - 1) // orderNo从1开始,转换为从0开始的索引
|
||||
|
||||
console.log(`📝 题目选项:`, options)
|
||||
console.log(`✅ 正确答案索引:`, correctAnswers)
|
||||
|
||||
// 根据API返回的数据结构适配前端需要的格式
|
||||
const processedQuestion = {
|
||||
id: question.id,
|
||||
title: question.content || `题目 ${index + 1}`,
|
||||
type: typeMap[question.type] || '单选题',
|
||||
score: question.score || 5,
|
||||
options: options,
|
||||
correctAnswer: correctAnswers.length === 1 ? correctAnswers[0] : correctAnswers,
|
||||
analysis: question.analysis || '',
|
||||
difficulty: question.difficulty || 0,
|
||||
// 保留原始数据以备后用
|
||||
originalData: questionData
|
||||
}
|
||||
|
||||
console.log(`✅ 处理后的题目 ${index + 1}:`, processedQuestion)
|
||||
return processedQuestion
|
||||
})
|
||||
|
||||
// 设置练习数据
|
||||
practiceQuestions.value = processedQuestions
|
||||
currentPracticeSection.value = section
|
||||
practiceMode.value = true
|
||||
practiceStarted.value = true // 直接开始练习,不需要点击开始按钮
|
||||
practiceFinished.value = false
|
||||
currentQuestionIndex.value = 0
|
||||
|
||||
// 初始化答案数组
|
||||
practiceAnswers.value = new Array(processedQuestions.length).fill(null).map(() => [])
|
||||
fillAnswers.value = new Array(processedQuestions.length).fill(null).map(() => [])
|
||||
essayAnswers.value = new Array(processedQuestions.length).fill('')
|
||||
|
||||
console.log('✅ 练习模式已启动,题目数量:', practiceQuestions.value.length)
|
||||
console.log('✅ 处理后的题目列表:', practiceQuestions.value)
|
||||
} else {
|
||||
console.warn('⚠️ 没有获取到有效的题目详情')
|
||||
message.warning('没有获取到有效的题目详情')
|
||||
}
|
||||
} else {
|
||||
console.warn('⚠️ 考试题目列表为空:', questionsList)
|
||||
message.warning('考试题目列表为空')
|
||||
}
|
||||
} else {
|
||||
console.error('❌ 获取考试题目失败:', questionsResponse.data?.message || questionsResponse.message)
|
||||
message.error(questionsResponse.data?.message || questionsResponse.message || '获取考试题目失败')
|
||||
}
|
||||
} else {
|
||||
console.warn('⚠️ 练习数据格式异常:', exerciseData)
|
||||
message.warning('练习数据格式异常')
|
||||
@ -2791,17 +2848,40 @@ const loadDiscussionData = async (section: CourseSection) => {
|
||||
|
||||
// 处理讨论数据
|
||||
const discussionData = response.data.result
|
||||
if (discussionData && Array.isArray(discussionData)) {
|
||||
// 为每个评论添加点赞状态字段
|
||||
discussionList.value = discussionData.map(comment => ({
|
||||
...comment,
|
||||
isLiked: false, // 默认未点赞
|
||||
likes: comment.likes || 0 // 确保有点赞数字段
|
||||
}))
|
||||
console.log('✅ 讨论数据加载完成,讨论数量:', discussionList.value.length)
|
||||
if (discussionData && Array.isArray(discussionData) && discussionData.length > 0) {
|
||||
// 获取第一个讨论项的标题和描述
|
||||
const firstDiscussion = discussionData[0]
|
||||
console.log('🔍 讨论数据详情:', firstDiscussion)
|
||||
|
||||
if (firstDiscussion.title) {
|
||||
discussionTitle.value = firstDiscussion.title
|
||||
console.log('✅ 设置讨论标题:', firstDiscussion.title)
|
||||
}
|
||||
|
||||
if (firstDiscussion.description) {
|
||||
// 去掉HTML标签,但保留文本内容
|
||||
const originalDescription = firstDiscussion.description
|
||||
const strippedDescription = stripHtmlTags(originalDescription)
|
||||
discussionDescription.value = strippedDescription
|
||||
console.log('✅ 原始描述:', originalDescription)
|
||||
console.log('✅ 处理后描述:', strippedDescription)
|
||||
}
|
||||
|
||||
// 这个API返回的是讨论主题信息,不是评论列表
|
||||
// 评论列表可能需要另外的API调用
|
||||
// 暂时初始化为空的评论列表
|
||||
discussionList.value = []
|
||||
console.log('✅ 讨论主题数据加载完成')
|
||||
|
||||
// TODO: 这里可能需要调用另一个API来获取评论列表
|
||||
// 例如: loadDiscussionComments(firstDiscussion.id)
|
||||
|
||||
} else {
|
||||
console.warn('⚠️ 讨论数据格式异常:', discussionData)
|
||||
discussionList.value = []
|
||||
// 重置标题和描述
|
||||
discussionTitle.value = '讨论'
|
||||
discussionDescription.value = ''
|
||||
}
|
||||
} else {
|
||||
console.error('❌ 获取章节讨论失败:', response.data?.message || response.message)
|
||||
@ -2815,11 +2895,25 @@ const loadDiscussionData = async (section: CourseSection) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 工具函数:去掉HTML标签,保留文本内容
|
||||
const stripHtmlTags = (html: string): string => {
|
||||
if (!html) return ''
|
||||
|
||||
// 创建一个临时的DOM元素来解析HTML
|
||||
const tempDiv = document.createElement('div')
|
||||
tempDiv.innerHTML = html
|
||||
|
||||
// 获取纯文本内容
|
||||
return tempDiv.textContent || tempDiv.innerText || ''
|
||||
}
|
||||
|
||||
const exitDiscussion = () => {
|
||||
console.log('🚪 正在退出讨论模式...')
|
||||
discussionMode.value = false
|
||||
currentDiscussionSection.value = null
|
||||
discussionList.value = []
|
||||
discussionTitle.value = '讨论'
|
||||
discussionDescription.value = ''
|
||||
newComment.value = ''
|
||||
replyingTo.value = null
|
||||
console.log('✅ 已退出讨论模式,discussionMode:', discussionMode.value)
|
||||
|
@ -133,9 +133,9 @@ const examName = ref(route.query.examName as string || '考试')
|
||||
// const viewCount = ref(1024) // 暂时注释,后续需要时再启用
|
||||
|
||||
// 返回上级
|
||||
const goBack = () => {
|
||||
router.push(`/course/${courseId.value}`)
|
||||
}
|
||||
// const goBack = () => {
|
||||
// router.push(`/course/${courseId.value}`)
|
||||
// } // 暂时未使用
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user