Просмотр исходного кода

1、课程数据、问题弹框、ai答案,数据接口前端重新定义

liyanbo 9 месяцев назад
Родитель
Сommit
eafd84e67f
4 измененных файлов с 208 добавлено и 400 удалено
  1. 1 1
      index.html
  2. 11 2
      src/components/HomePage.vue
  3. 194 393
      src/views/AIDevelop.vue
  4. 2 4
      src/views/AIGeneralCourse.vue

+ 1 - 1
index.html

@@ -4,7 +4,7 @@
     <meta charset="UTF-8" />
     <link rel="icon" type="image/svg+xml" href="/vite.svg" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>Vite + Vue</title>
+    <title>ai通识课程平台</title>
   </head>
   <body>
     <div id="app"></div>

+ 11 - 2
src/components/HomePage.vue

@@ -37,14 +37,14 @@
             round
             class="top-right-btn"
             :class="{ 'is-active': selectedButton === 'AI写作课' }"
-            @click="selectedButton = 'AI写作课'"
+            @click="selectedButton = 'AI通识课'; Message().notifyWarning('演示版未开放此功能!!', true); "
             >AI写作课</el-button
           >
           <el-button
             round
             class="top-right-btn"
             :class="{ 'is-active': selectedButton === 'AI艺术课' }"
-            @click="selectedButton = 'AI艺术课'"
+            @click="selectedButton = 'AI通识课'; Message().notifyWarning('演示版未开放此功能!', true); "
             >AI艺术课</el-button
           >
         </div>
@@ -79,12 +79,14 @@
         <div
           class="top-sub-box"
           :style="{ backgroundImage: `url(${indexImages[2]})` }"
+          @click="notOpen()"
         >
           <span>能力测评</span>
         </div>
         <div
           class="bottom-sub-box"
           :style="{ backgroundImage: `url(${indexImages[3]})` }"
+          @click="notOpen()"
         >
           <span>个性化学习</span>
         </div>
@@ -109,6 +111,7 @@ import studyImg from '@/assets/images/study.png'
 
 // 退出图标
 import logoutIcon from '@/assets/icon/logout.png'
+import {Message} from "@/utils/message/Message.js";
 // 获取当前路由对象
 const router = useRouter()
 // 退出
@@ -154,6 +157,12 @@ const fetchCtTypes = async () => {
   }
 }
 
+
+//AI实验室
+const notOpen = () => {
+  Message().notifyWarning(localStorage.getItem('userName') === "aiTest" ? '您的账号并未开放此功能!' : '演示版未开放此功能!', true)
+}
+
 // 添加 watch 监听 selectedGrade 的变化
 watch(selectedGrade, newValue => {
   // 根据 id 切换高年级或低年级

+ 194 - 393
src/views/AIDevelop.vue

@@ -4,8 +4,8 @@
     <!-- 展开收起侧边栏 -->
     <div class="icon-expand">
       <el-icon
-        @click="toggleDrawer"
-        :style="{ color: drawerVisible ? 'white' : '#B6B0D8' }"
+          @click="toggleDrawer"
+          :style="{ color: drawerVisible ? 'white' : '#B6B0D8' }"
       >
         <component :is="drawerVisible ? Fold : Expand" />
         <!-- <Tickets /> -->
@@ -23,28 +23,28 @@
                 课程小节
               </h3>
               <el-menu
-                :default-active="activeMenuIndex"
+                :default-active="course.key"
                 @open="handleOpen"
                 @close="handleClose"
                 @select="handleSelect"
                 :default-openeds="['3']"
               >
-                <template v-for="item in menuItems" :key="item.index">
-                  <el-menu-item v-if="!item.children" :index="item.index">{{
-                    item.title
-                  }}</el-menu-item>
+                <template v-for="item in menuItems" :key="item.key">
+                  <el-menu-item v-if="!item.children" :index="item.key">{{
+                      item.title
+                    }}</el-menu-item>
                   <el-sub-menu v-else :index="item.index">
                     <template #title>
                       <span>{{ item.title }}</span>
                     </template>
                     <el-menu-item-group v-if="item.children">
                       <template
-                        v-for="child in item.children"
-                        :key="child.index"
+                          v-for="child in item.children"
+                          :key="child.index"
                       >
                         <el-menu-item :index="child.index">{{
-                          child.title
-                        }}</el-menu-item>
+                            child.title
+                          }}</el-menu-item>
                       </template>
                     </el-menu-item-group>
                   </el-sub-menu>
@@ -67,9 +67,9 @@
         <div class="inner-box right-box">
           <div class="top-right-box">
             <el-input
-              v-model="SearchInput"
-              class="search-input"
-              placeholder="搜索"
+                v-model="SearchInput"
+                class="search-input"
+                placeholder="搜索"
             >
               <template #prefix>
                 <el-icon class="el-input__icon"><search /></el-icon>
@@ -79,23 +79,23 @@
         </div>
       </div>
 
-      
+
       <div class="box-2">
         <!-- 课程标题 autoplay自动播放   @ended="playNextVideo"-->
         <div class="small-title">
-          <span>{{ smallTitle }}</span>
+          <span>{{ course.courseName }}</span>
         </div>
         <div class="box-video">
           <video
-            class="full-box-video"
-            :src="videoSrc"
-            controlsList="nodownload"
-            controls
-            @timeupdate="handleTimeUpdate"
-            @play="checkVideoPermission"
-            ref="videoRef"
+              class="full-box-video"
+              :src="course.courseVideoPath"
+              controlsList="nodownload"
+              controls
+              @timeupdate="handleTimeUpdate"
+              @play="checkVideoPermission"
+              ref="videoRef"
           >
-            <source :src="videoSrc" type="video/mp4" />
+            <source :src="course.courseVideoPath" type="video/mp4" />
             您的浏览器不支持视频播放。
           </video>
         </div>
@@ -115,32 +115,32 @@
       <!-- 添加试题弹框 -->
       <transition name="fade-scale">
         <div
-          v-show="questionDialogVisible"
-          class="child-dialog-wrapper"
-          @click.self="handleCloseQuestionDialog"
+            v-show="questionDialogVisible"
+            class="child-dialog-wrapper"
+            @click.self="handleCloseQuestionDialog"
         >
           <div class="child-dialog">
             <div class="question-title">
               <span class="question-icon">?</span>
-              {{ currentQuestion.title }}
+              <span v-html="courseConfig.ccQuestContent"></span>
             </div>
             <!-- 选项区域 -->
             <div
-              v-if="
-                currentQuestion.options && currentQuestion.options.length > 0
+                v-if="
+                courseConfig.ccQuestOption && courseConfig.ccQuestOption.length > 0
               "
-              class="options-container"
+                class="options-container"
             >
               <div
-                v-for="(option, index) in currentQuestion.options"
-                :key="index"
-                class="question-option"
+                  v-for="(option, index) in courseConfig.ccQuestOption"
+                  :key="index"
+                  class="question-option"
               >
                 <el-radio
-                  v-model="selectedOption"
-                  :label="index"
-                  :value="option"
-                  v-cloak="(selectedOption = option)"
+                    v-model="selectedOption"
+                    :label="index"
+                    :value="option"
+                    v-cloak="(selectedOption = option)"
                 >
                   <span>{{ option }}</span>
                 </el-radio>
@@ -153,17 +153,17 @@
             <div class="dialog-footer">
               <!--          <el-button class="child-button cancel" @click="questionDialogVisible = false; showAIDialog = false">取消</el-button>-->
               <el-button
-                class="child-button confirm"
-                @click="handleSubmitAnswer"
-                >确定</el-button
+                  class="child-button confirm"
+                  @click="handleSubmitAnswer"
+              >确定</el-button
               >
             </div>
             <!-- 右侧小图标 -->
             <div class="ai-icon-container" @click="handleAIClick">
               <img
-                src="@/assets/images/xiaozhi.png"
-                alt="AI对话"
-                class="ai-icon"
+                  src="@/assets/images/xiaozhi.png"
+                  alt="AI对话"
+                  class="ai-icon"
               />
               <span class="ai-text">AI助手</span>
             </div>
@@ -172,52 +172,50 @@
       </transition>
       <!-- AI对话弹框 -->
       <div
-        v-show="showAIDialog"
-        class="ai-dialog-wrapper"
-        @click.self="showAIDialog = false"
+          v-show="showAIDialog"
+          class="ai-dialog-wrapper"
+          @click.self="showAIDialog = false"
       >
         <div class="ai-dialog">
           <div class="ai-dialog-header">
             <h3>小智智能助手</h3>
             <el-button @click="showAIDialog = false" class="close-btn"
-              >×</el-button
+            >×</el-button
             >
           </div>
           <div class="ai-dialog-content">
             <div class="ai-message-history">
               <div
-                v-for="(message, index) in messageHistory"
-                :key="index"
-                :class="['message', message.type]"
+                  v-for="(message, index) in messageHistory"
+                  :key="index"
+                  :class="['message', message.type]"
               >
                 <img
-                  v-if="message.type === 'user'"
-                  src="@/assets/images/user.png"
-                  class="avatar user"
+                    v-if="message.type === 'user'"
+                    src="@/assets/images/user.png"
+                    class="avatar user"
                 />
                 <img v-else src="@/assets/images/xiaozhi.png" class="avatar" />
-                <div class="message-content">
-                  {{ message.content }}
+                <div class="message-content" v-html="message.content">
                 </div>
               </div>
             </div>
             <el-input
-              v-model="userMessage"
-              placeholder="输入问题..."
-              class="user-input"
-              @keyup.enter="sendMessage"
+                v-model="userMessage"
+                placeholder="输入问题..."
+                class="user-input"
+                @keyup.enter="sendMessage"
             >
               <template #append class="flex flex-wrap items-center mb-4">
                 <!--              <el-button @click="sendMessage" class="child-button confirm">发送</el-button>-->
-                <el-button @click="sendMessage" size="large" round
-                  >发送</el-button
-                >
+                <el-button @click="sendMessage" size="large" round>发送</el-button>
               </template>
             </el-input>
           </div>
         </div>
       </div>
     </div>
+
   </div>
 </template>
 
@@ -225,46 +223,14 @@
 import { ref, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
 import {
-  ArrowDown,
-  ArrowRightBold,
   Expand,
-  Reading,
   Fold,
-  Tickets,
   Memo
 } from '@element-plus/icons-vue'
-import {
-  Document,
-  Menu as IconMenu,
-  Location,
-  Setting
-} from '@element-plus/icons-vue'
 import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
-import {
-  ElMessage,
-  ElMessageBox,
-  ElNotification,
-  valueEquals
-} from 'element-plus'
-// 引入视频
-import video1 from '@/assets/02video/01video.mp4'
-import video2 from '@/assets/02video/02video.mp4'
-import video3 from '@/assets/02video/03video.mp4'
-import video4 from '@/assets/02video/04video.mp4'
-import video5 from '@/assets/02video/05video.mp4'
-import video6 from '@/assets/02video/06video.mp4'
-import video7 from '@/assets/02video/07video.mp4'
-import video8 from '@/assets/02video/08video.mp4'
-import video9 from '@/assets/02video/09video.mp4'
-import video10 from '@/assets/02video/10video.mp4'
-import video11 from '@/assets/02video/11video.mp4'
-import video12 from '@/assets/02video/12video.mp4'
-import video13 from '@/assets/02video/13video.mp4'
-import video14 from '@/assets/02video/14video.mp4'
-import video15 from '@/assets/02video/15video.mp4'
-
-import { ClassType } from '@/api/class.js'
-import { Message } from '@/utils/message/Message.js'
+
+import {ClassType} from "@/api/class.js";
+import {Message} from "@/utils/message/Message.js";
 
 const router = useRouter() // 获取当前路由对象
 // 搜索框
@@ -278,7 +244,6 @@ const toggleDrawer = () => {
   drawerVisible.value = !drawerVisible.value
 }
 
-const activeMenuIndex = ref('1-1')
 
 // 返回上一页
 const goBack = () => {
@@ -287,15 +252,24 @@ const goBack = () => {
 
 // 渲染页面标题
 const boxIconTitle = ref('')
-// 课程数据
+
+// 课程集合数据
 const courseList = ref([])
+//当前课程
+const course = ref({})
 // 菜单数据
 const menuItems = ref([])
-
-// 定义视频源
-const videoSrc = ref('')
-// 新增视频路径映射
-const videoPathMap = ref({})
+// 课程集合数据
+const videoPathMap  = ref({})
+
+//课程小节字典(需要新加接口调取字典)
+const menuDict = ref({
+  "1": "课前回顾",
+  "2": "课程引入",
+  "3": "知识讲解",
+  "4": "趣味实操",
+  "5": "课程总结",
+})
 
 // 渲染 课程数据结构 以及 视频
 onMounted(async () => {
@@ -304,78 +278,41 @@ onMounted(async () => {
     try {
       // 取接口课程数据
       const res = await ClassType(typeId)
-      console.log(res);
-      
       courseList.value = res.data
 
-      // 初始化第一个视频源和标题
-      if (courseList.value.length > 0 && courseList.value[0].courseVideoPath) {
-        videoSrc.value = courseList.value[0].courseVideoPath
-        currentIndex.value = '1-1'
-        smallTitle.value = courseList.value[0].courseName
-      }
-
-      // 按 courseLabel 分组
-      const groupedByLabel = {}
-      courseList.value.forEach(item => {
-        if (!groupedByLabel[item.courseLabel]) {
-          groupedByLabel[item.courseLabel] = []
+      //课程数据
+      courseList.value.forEach((courseTemp,index) => {
+        let menuIndex = courseTemp.courseLabel + '-' + (index+1);
+        //填充大纲小节
+        let menu = menuItems.value.find(menu => courseTemp.courseLabel === menu.index);
+        if (menu){//小节
+          menu.children = menu.children || [];
+          menu.children.push({
+            key: menuIndex,
+            index: menuIndex,
+            title: courseTemp.courseName
+          })
+        }else {//大节
+          menuItems.value.push({
+            key: menuIndex,
+            index: courseTemp.courseLabel,
+            title: menuDict.value[courseTemp.courseLabel]
+          })
         }
-        groupedByLabel[item.courseLabel].push(item)
-      })
 
-      // 对每个组按 courseOrder 排序
-      Object.keys(groupedByLabel).forEach(label => {
-        groupedByLabel[label].sort((a, b) => a.courseOrder - b.courseOrder)
-      })
+        courseTemp["key"] = menuIndex;
+        videoPathMap.value[menuIndex] = courseTemp
 
-      // 构建视频路径映射
-      videoPathMap.value = {}
-      let labelIndex = 0
-      Object.keys(groupedByLabel).forEach(label => {
-        const groupItems = groupedByLabel[label]
-        groupItems.forEach((item, indexInGroup) => {
-          const idx = `${labelIndex + 1}-${indexInGroup + 1}`
-          if (item.courseVideoPath) {
-            videoPathMap.value[idx] = item.courseVideoPath
-          }
-        })
-        labelIndex++
-      })
-
-      // 构建新的 menuItems 结构
-      menuItems.value = []
-      Object.keys(groupedByLabel).forEach((label, labelIndex) => {
-        const groupItems = groupedByLabel[label]
-        // 检查是否是知识分解组(图灵测试到大模型时代)
-        const isKnowledgeGroup = groupItems.some(item =>
-          ['图灵测试', '大模型时代'].includes(item.courseName)
-        )
-        if (isKnowledgeGroup) {
-          // 构建知识分解组的树型结构
-          menuItems.value.push({
-            index: `${labelIndex + 1}`,
-            title: '知识讲解',
-            children: groupItems.map((item, index) => ({
-              index: `${labelIndex + 1}-${index + 1}`,
-              title: item.courseName
-            }))
-          })
-        } else {
-          // 普通组直接添加菜单项
-          groupItems.forEach((item, index) => {
-            const idx = `${labelIndex + 1}-${index + 1}`
-            menuItems.value.push({
-              index: idx,
-              title: item.courseName
-            })
-          })
+        //确定默认课程
+        if (index === 0) {
+          course.value = courseTemp;
         }
       })
     } catch (error) {
       console.error('获取课程数据失败:', error)
     }
   }
+
   const title = router.currentRoute.value.query.typeName
   if (title) {
     boxIconTitle.value = String(title)
@@ -386,12 +323,11 @@ onMounted(async () => {
 const handleOpen = () => {}
 const handleClose = () => {}
 
-// 当前播放的索引
-const currentIndex = ref('1-1')
-
-// 渲染课程标题到视频上方
-const smallTitle = ref('课前回顾')
+// 菜单选择的处理函数
 const handleSelect = index => {
+  //测试账号禁用视频
+  if (disableVideo(index))return;
+
   const findTitle = items => {
     for (const item of items) {
       if (item.index === index) {
@@ -406,15 +342,14 @@ const handleSelect = index => {
     }
     return null
   }
-  const title = findTitle(menuItems.value)
-  if (title) {
-    smallTitle.value = title
-  }
   // 根据索引切换视频,使用新的 videoPathMap
   if (videoPathMap.value[index]) {
-    videoSrc.value = videoPathMap.value[index]
-    currentIndex.value = index
+    course.value = videoPathMap.value[index]
+  }else {
+    //视频不存在
+    Message().notifyWarning('视频不存在!', true);
   }
+
   //测试账号禁用视频
   if (disableVideo()) return
 }
@@ -425,7 +360,7 @@ const flattenMenuItems = () => {
   const traverse = items => {
     for (const item of items) {
       if (!item.children) {
-        indices.push(item.index)
+        indices.push(item.key)
       } else {
         traverse(item.children)
       }
@@ -438,9 +373,10 @@ const flattenMenuItems = () => {
 // 播放下一个视频
 const playNextVideo = () => {
   //测试账号禁用视频
-  if (disableVideo()) return
+  if (disableVideo())return;
+
   const allIndices = flattenMenuItems()
-  const currentIndexInList = allIndices.indexOf(currentIndex.value)
+  const currentIndexInList = allIndices.indexOf(course.value.key)
   if (currentIndexInList !== -1 && currentIndexInList < allIndices.length - 1) {
     const nextIndex = allIndices[currentIndexInList + 1]
     handleSelect(nextIndex)
@@ -450,23 +386,21 @@ const playNextVideo = () => {
         once: true
       })
     }
-      // 更新侧边栏选中状态
-  activeMenuIndex.value = nextIndex
   }
   // 重置
-  pausedIndices = ref([])
+  pausedIndices = ref({time: [], newTime: []})
   userMessage = ref('')
   messageHistory = ref([])
-  
 }
 
 // 切换视频
 // 播放上一个视频
 const playPreviousVideo = () => {
   //测试账号禁用视频
-  if (disableVideo()) return
+  if (disableVideo())return;
+
   const allIndices = flattenMenuItems()
-  const currentIndexInList = allIndices.indexOf(currentIndex.value)
+  const currentIndexInList = allIndices.indexOf(course.value.key)
   if (currentIndexInList > 0) {
     const previousIndex = allIndices[currentIndexInList - 1]
     handleSelect(previousIndex)
@@ -476,16 +410,14 @@ const playPreviousVideo = () => {
         once: true
       })
     }
-    // 更新侧边栏选中状态
-  activeMenuIndex.value = nextIndex 
   }
-  
 }
 
 // 尝试播放视频,处理浏览器自动播放限制
 const tryPlayVideo = () => {
   //测试账号禁用视频
-  if (disableVideo()) return
+  if (disableVideo())return;
+
   const playPromise = videoRef.value.play()
   if (playPromise !== undefined) {
     playPromise.catch(error => {
@@ -493,78 +425,50 @@ const tryPlayVideo = () => {
     })
   }
 }
+
 // 检查视频播放权限
 const checkVideoPermission = () => {
-  if (disableVideo()) {
+  if (disableVideo() || questionDialogVisible.value) {
     if (videoRef.value) {
       videoRef.value.pause()
     }
   }
-}
+
+  //记录已暂停的内容
+  setVideoStop();
+};
 
 //禁用视频
-const disableVideo = () => {
-  let dis = [
-    '3-4',
-    '3-5',
-    '3-6',
-    '3-7',
-    '3-8',
-    '3-9',
-    '3-10',
-    '3-11',
-    '4-1',
-    '5-1'
-  ]
-  if (
-    localStorage.getItem('userName') === 'aiTest' &&
-    dis.indexOf(currentIndex.value) !== -1
-  ) {
+const disableVideo = (index = course.value.key) => {
+  let dis = ["1-6","1-7","1-8","1-9","1-10","1-11","1-12","1-13","1-14","1-15"]
+
+  if (localStorage.getItem('userName') === "aiTest" &&
+      dis.indexOf(index) !== -1) {
+
     if (videoRef.value) {
+      // 记录当前播放时间
       videoRef.value.pause()
-      // 禁用视频进度条拖拽功能
-      const handleSeeking = () => {
-        videoRef.value.pause()
-        Message().notifyWarning(
-          '您的账号并未开放此课程,禁止拖动进度条!',
-          true
-        )
-      }
-      // 添加 seeking 事件监听器
-      videoRef.value.addEventListener('seeking', handleSeeking)
-      // 当视频源改变时,移除事件监听器,避免影响其他视频
-      const removeListener = () => {
-        videoRef.value.removeEventListener('seeking', handleSeeking)
-        videoRef.value.removeEventListener('loadedmetadata', removeListener)
-      }
-      videoRef.value.addEventListener('loadedmetadata', removeListener)
+      // 阻止用户跳转到新的时间点,将播放时间重置为之前的时间
+      videoRef.value.currentTime = 0;
     }
     //提示禁用// 显示消息框
-    Message().notifyWarning('您的账号并未开放此课程!', true)
-    return true
-  } else {
-    // 若不符合禁用条件,移除事件监听器
-    if (videoRef.value) {
-      videoRef.value.removeEventListener('seeking', e => {
-        e.preventDefault()
-      })
-    }
-    return false
+    Message().notifyWarning('您的账号并未开放此课程!', true);
+    return true;
   }
+  return false;
 }
 
 // 视频 ref
 const videoRef = ref(null)
 // 记录已经暂停过的时间点索引
-let pausedIndices = ref([])
+let pausedIndices = ref({time: [], newTime: []})
 // 试题弹框显示状态
 const questionDialogVisible = ref(false)
 // 当前显示的试题
-const currentQuestion = ref({ title: '', options: [] })
+const courseConfig = ref({})
 // 用户选择的选项
 const selectedOption = ref(null)
 
-
 // AI对话弹出框显示状态
 let showAIDialog = ref(false)
 // 用户输入的消息
@@ -572,155 +476,37 @@ let userMessage = ref('')
 // 消息历史记录
 let messageHistory = ref([])
 
-// 定义每个视频对应的暂停时间和问题
-const videoPauseTimes = {
-  [video2]: {
-    pauseTimes: [30],
-    questions: [
-      {
-        title: '视频当中发生了什么事情呢?',
-        options: [],
-        aiQuestion: '视频当中发生了什么事情呢',
-        aiAnswer:
-          '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
-      }
-    ]
-  },
-  [video3]: {
-    pauseTimes: [49],
-    questions: [
-      {
-        title: '同学们,大家了解图灵测试了吗?',
-        options: [],
-        aiQuestion: '视频当中发生了什么事情呢',
-        aiAnswer:
-          '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
-      }
-    ]
-  },
-  [video4]: {
-    pauseTimes: [2],
-    questions: [
-      {
-        title: '你觉得deepseek、豆包等大模型可以通过图灵测试吗?为什么?',
-        options: [],
-        aiQuestion: '你觉得deepseek、豆包等大模型可以通过图灵测试吗?为什么?',
-        aiAnswer:
-          '大模型已缩短与图灵测试的标志距离,尤其在表面对话层面,但因缺乏深层次理解、逻辑一致性与真实认知,仍无法在严格测试中稳定通过。'
-      }
-    ]
-  },
-  [video5]: {
-    pauseTimes: [49],
-    questions: []
-  },
-  [video6]: {
-    pauseTimes: [5]
-  },
-  [video7]: {
-    pauseTimes: [64.5, 91],
-    questions: [
-      {
-        title: '如果你是聊天机器人,你会怎么回答用户呢?',
-        options: [],
-        aiQuestion: '',
-        aiAnswer: ''
-      },
-      {
-        title:
-          '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
-        options: [],
-        aiQuestion:
-          '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
-        aiAnswer:
-          '与聊天机器人的对话被人类查看时,隐私泄露风险客\n' +
-          '观存在,尤其是人类介入或安全漏洞场景下。建议优先选择支持本地'
-      }
-    ]
-  },
-  [video8]: {
-    pauseTimes: [72],
-    questions: [
-      {
-        title: '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
-        options: [],
-        aiQuestion:
-          '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
-        aiAnswer: '这题没给答案,你自己去查吧!'
-      }
-    ]
-  },
-  [video9]: {
-    pauseTimes: [2],
-    questions: [
-      {
-        title: '在生活中,有哪些正在使用的专家系统呢?',
-        options: [],
-        aiQuestion: '在生活中,有哪些正在使用的专家系统呢?',
-        aiAnswer:
-          '在医疗健康领域有复杂疾病协同决策和Ai医生分身与诊断辅助;在水利交通领域的水利厅专家库系统用于项目验收和抢险督查'
-      }
-    ]
-  },
-  [video11]: {
-    pauseTimes: [1, 90, 176],
-    questions: [
-      {
-        title: '怎么会有爆炸声?泡泡怪在这里吗?',
-        options: [],
-        aiQuestion: '',
-        aiAnswer: ''
-      },
-      {
-        title: '同学们喜欢下围棋吗?',
-        options: [],
-        aiQuestion: '',
-        aiAnswer: ''
-      },
-      {
-        title: '为什么AlphaGo要在围棋上攻克真人冠军呢?',
-        options: [],
-        aiQuestion: '为什么AlphaGo要在围棋上攻克真人冠军呢?',
-        aiAnswer:
-          '围棋是人类智力游戏的巅峰,拥有天文数字级的可能性,每颗棋子价值由全局态势动态决定,所以当前一手可能百步之后才显现价值。AlphaGo战胜人类顶尖选手,它证明了Ai不仅能处理规则明确的事物,更能攻克依赖直觉、策略的“人类专属领域”'
-      }
-    ]
-  },
-  [video12]: {
-    pauseTimes: [1]
-  },
-  [video13]: {
-    pauseTimes: [62],
-    questions: [
-      {
-        title: '我们一起来感受一下大模型吧!',
-        options: [],
-        aiQuestion: '',
-        aiAnswer: ''
-      }
-    ]
-  }
-}
-
 // 处理视频时间更新事件
 const handleTimeUpdate = () => {
+  //测试账号禁用视频
   if (!videoRef.value) return
-  const currentTime = videoRef.value.currentTime
-  const currentPauseTimes = videoPauseTimes[videoSrc.value]
-  if (currentPauseTimes) {
-    currentPauseTimes.pauseTimes.forEach((time, index) => {
-      // 检查是否到达时间点且还未暂停过
-      if (currentTime >= time && !pausedIndices.value.includes(index)) {
-        videoRef.value.pause()
-        pausedIndices.value.push(index)
-        // 显示对应的问题
-        if (currentPauseTimes.questions[index]) {
-          currentQuestion.value = currentPauseTimes.questions[index]
-          questionDialogVisible.value = true
+
+  const currentTime = parseInt(videoRef.value.currentTime)
+
+  if (!course.value.courseConfigList) return
+  course.value.courseConfigList.forEach(courseCofig => {
+
+    //暂停时间
+    let time = courseCofig.ccTime
+    // 检查是否到达时间点且还未暂停过
+    let timeIndex = pausedIndices.value.time.indexOf(time);
+
+    if (currentTime === time && (timeIndex === -1 || Date.now() - pausedIndices.value.newTime[timeIndex] > 1000) ) {
+
+      videoRef.value.pause()
+
+      // 显示对应的问题
+      if (courseCofig.ccQuestContent) {
+        questionDialogVisible.value = true
+        courseConfig.value = courseCofig
+
+        //解析选项
+        if (courseCofig.ccQuestOption) {
+          courseConfig.courseQuestion = courseCofig.ccQuestOption.split(',')
         }
       }
-    })
-  }
+    }
+  })
 }
 
 // 关闭试题弹框
@@ -728,6 +514,22 @@ const handleCloseQuestionDialog = () => {
   questionDialogVisible.value = false
   // 继续播放视频
   videoRef.value.play()
+
+  //记录已暂停的内容
+  setVideoStop();
+}
+
+//记录已暂停的内容
+const setVideoStop = () => {
+  const currentTime = parseInt(videoRef.value.currentTime)
+  let timeIndex = pausedIndices.value.time.indexOf(currentTime);
+  if (timeIndex === -1) {
+    pausedIndices.value.time.push(currentTime)
+    pausedIndices.value.newTime.push(Date.now())
+  }else{
+    pausedIndices.value.time[timeIndex] = currentTime
+    pausedIndices.value.newTime[timeIndex] = Date.now()
+  }
 }
 
 // 提交答案
@@ -737,6 +539,9 @@ const handleSubmitAnswer = () => {
   // 继续播放视频
   videoRef.value.play()
   selectedOption.value = null
+
+  //记录已暂停的内容
+  setVideoStop();
 }
 
 // 发送消息
@@ -764,11 +569,12 @@ const sendMessage = async () => {
 const handleAIClick = () => {
   // 清空输入框
   messageHistory = ref([])
-  if (currentQuestion.value.aiQuestion) {
-    userMessage.value = currentQuestion.value.aiQuestion
+  if (courseConfig.value.ccQuestContent) {
+    userMessage.value = courseConfig.value.ccQuestContent
     sendMessage()
     userMessage.value = ''
   }
+
   showAIDialog.value = true
 }
 
@@ -776,15 +582,9 @@ const handleAIClick = () => {
 const simulateAIResponse = question => {
   return new Promise(resolve => {
     setTimeout(() => {
-      const currentVideoInfo = videoPauseTimes[videoSrc.value]
-      if (currentVideoInfo) {
-        const currentQuestionObj = currentVideoInfo.questions.find(
-          q => q.aiQuestion === question
-        )
-        if (currentQuestionObj && currentQuestionObj.aiAnswer) {
-          resolve(currentQuestionObj.aiAnswer)
-          return
-        }
+      if (courseConfig.value.ccAiAnswer) {
+        resolve(courseConfig.value.ccAiAnswer)
+        return
       }
       // 若未匹配到自定义回复,给出默认回复
       resolve(`您的问题是:${question},这是 AI 的回复示例。`)
@@ -796,6 +596,7 @@ const simulateAIResponse = question => {
 const handleCloseAIDialog = () => {
   showAIDialog.value = false
 }
+
 </script>
 
 <style scoped lang="scss">

+ 2 - 4
src/views/AIGeneralCourse.vue

@@ -157,7 +157,7 @@ watch(selectedGrade, newValue => {
   const selectedItem = classData.value.find(item => item.ctType === newValue)
   if (selectedItem) {
     if (selectedItem.id === 1) {
-      selectedGrade.value = '小学年级'
+      selectedGrade.value = '小学年级'
     } else if (selectedItem.id === 3) {
       selectedGrade.value = '小学高年级'
     }
@@ -250,10 +250,8 @@ const goToAIExperience = outlineData => {
       query: { typeId: outlineData.id, typeName: outlineData.ctType }
     })
   }else {
-    if (localStorage.getItem('userName') === "aiTest") {
       //提示禁用
-      Message().notifyWarning('您的账号并未开放此课程!', true)
-    }
+      Message().notifyWarning(localStorage.getItem('userName') === "aiTest" ? '您的账号并未开放此课程!' : '演示版未开放此课程!', true)
   }
 }