Bläddra i källkod

对AI实验功能组件保存进度方法抽出值传递类型和进度,在外面进行分别管理
课程中的智能问答保存进度同样抽出,只保留问答次数

liyanbo 5 månader sedan
förälder
incheckning
f999a6c4f5

+ 21 - 1
src/api/personalized/index.js

@@ -33,7 +33,27 @@ export function saveRecordBlockly (data) {
 // 获取评估报告数据(blockly编程)
 export function getReportBlockly (data) {
   return axios({
-    url: 'blocklyReport/progress/getReportProgress',
+    url: 'aiCourseReport/progress/getReportProgress',
+    method: 'get',
+    data: data
+  })
+}
+
+
+// 保存记录(AI实验课)
+export function saveRecordAiCourse (data) {
+  return axios({
+    url: 'aiCourseReport/progress/saveReportProgress',
+    method: 'post',
+    data: data
+  })
+}
+
+
+// 获取评估报告数据(AI实验课)
+export function getReportAiCourse (data) {
+  return axios({
+    url: 'aiCourseReport/progress/getReportProgress',
     method: 'get',
     data: data
   })

+ 1 - 1
src/components/Image/ImageView.vue

@@ -104,7 +104,7 @@ const saveProgress = throttle(async (progress) => {
     }
 
     // 通过emit事件通知父组件保存进度
-    emits('saveProgress', "image", progress)
+    emits('saveProgress', "course", progress)
     savedProgress.value.push(progress)
   } catch (error) {
     console.error(`保存进度失败:`, error)

+ 1 - 1
src/components/PPT/PptView.vue

@@ -97,7 +97,7 @@ const saveProgress = throttle(async (progress) => {
     }
 
     // 通过emit事件通知父组件保存进度
-    emits('saveProgress', "ppt", progress)
+    emits('saveProgress', "course", progress)
     savedProgress.value.push(progress)
   } catch (error) {
     console.error(`保存进度失败:`, error)

+ 12 - 47
src/components/ai/image/ImageToImage.vue

@@ -133,36 +133,12 @@
 </template>
 
 <script setup>
-import { ref, onMounted,onUnmounted} from 'vue'
+import {ref, onMounted, onUnmounted, defineEmits} from 'vue'
 import {AiImageStatusEnum, CreatePainting, PaintingGetMys} from '@/api/questions.js'
-import { useRouter, useRoute } from 'vue-router'
-import {
-  Document,
-  Menu as IconMenu,
-  Location,
-  Setting,
-  ArrowLeftBold,
-  Fold,
-  Expand,
-  ChatLineRound,
-  Picture,
-  MagicStick,
-  Tickets,
-  User,
-  Brush,
-  Check,
-  EditPen,
-  ArrowDown,
-  ArrowUp
-} from '@element-plus/icons-vue'
 import VoiceInput from '../voice/VoiceInput.vue'
 
-import { saveRecord } from '@/api/personalized/index.js'
-
 // 导入全局状态
 import { globalState } from '@/utils/globalState.js'
-// 语音图标
-import { Microphone, Mute } from "@element-plus/icons-vue";
 // 终止按钮
 import stopicon from "@/assets/icon/stopicon.png";
 // 消息组件
@@ -178,11 +154,16 @@ import { ModelTypeEnum } from '@/api/teachers.js'
 // 定义props
 const props = defineProps({
   //根据需求传输
+  isCourse: { type: Boolean, default: false},
   cacheDataKey: { type: String, default: localStorage.getItem('token') + "_imageToImage" },
   cacheDataHistoryKey: { type: String, default: localStorage.getItem('token') + "_imageToImage_history" },
   preDialogueList: { type: Array, default: () => []},
   replySupplement: { type: String, default: ''},
 })
+
+// 定义emits
+const emits = defineEmits(['saveProgress'])
+
 //历史记录缓存集合
 const cacheDataHistoryList = ref([]);
 
@@ -210,8 +191,6 @@ const drawerVisible = ref(true)
 
   // 年级ID相关
 const gradeId = ref('')
-// 添加消息计数器变量
-const messageCount = ref(0)
 // modelId响应式变量
 const modelId = ref(0)
 // 保存记录
@@ -219,12 +198,7 @@ onMounted(async () => {
     // 从全局状态初始化年级ID
   gradeId.value = globalState.initGradeId()
   try{
-    const res = await saveRecord({
-        brpNjId: gradeId.value,
-        brpType: "aiCount",
-        brpProgress: 1
-      });
-      // 获取modelId
+    // 获取modelId
     const modelRes = await getModelIdByType({ type: ModelTypeEnum.IMAGE_TO_IMAGE, platform: ModelPlatformEnum.DOUBAO })
     modelId.value = modelRes.data
   }catch(error){
@@ -298,20 +272,11 @@ const sendMessage = async() => {
       loading: true
     })
 
-    // 递增消息计数器
-    messageCount.value++
-    // 发送saveRecord请求 保存消息次数
-    try{
-      await saveRecord({
-         brpNjId: gradeId.value,
-         brpType: "aiCount",
-         brpProgress: messageCount.value
-       });
-       console.log('保存记录成功,消息次数:', messageCount.value);
-   }catch(error){
-     console.error('保存记录失败:', error);
-     conversationInProgress.value = false;
-   }
+    // 通过emit事件通知父组件保存进度
+    emits('saveProgress', "aiCount", 1)
+    if (props.isCourse){
+      emits('saveProgress', "course", 100)
+    }
 
 
     // 同步历史记录缓存

+ 12 - 73
src/components/ai/image/TextToImage.vue

@@ -135,39 +135,18 @@
 </template>
 
 <script setup>
-import { ref, onMounted,onUnmounted} from 'vue'
+import {ref, onMounted, onUnmounted, defineEmits} from 'vue'
 import {AiImageStatusEnum, CreatePainting, PaintingGetMys} from '@/api/questions.js'
-import { useRouter, useRoute } from 'vue-router'
 import demo1 from '@/assets/images/ai-demo/ai-image-demo1.png'
 import demo2 from '@/assets/images/ai-demo/ai-image-demo2.png'
 import demo3 from '@/assets/images/ai-demo/ai-image-demo3.png'
 import demo4 from '@/assets/images/ai-demo/ai-image-demo4.png'
-import {
-  Document,
-  Menu as IconMenu,
-  Location,
-  Setting,
-  ArrowLeftBold,
-  Fold,
-  Expand,
-  ChatLineRound,
-  Picture,
-  MagicStick,
-  Tickets,
-  User
-} from '@element-plus/icons-vue'
-
-import { saveRecord } from '@/api/personalized/index.js'
 
 // 导入全局状态
 import { globalState } from '@/utils/globalState.js'
-// 语音图标
-import { Microphone, Mute } from "@element-plus/icons-vue";
 import VoiceInput from '../voice/VoiceInput.vue'
 // 终止按钮
 import stopicon from "@/assets/icon/stopicon.png";
-// 消息组件
-import {Message} from "@/utils/message/Message.js";
 
 // 导入getModelIdByType接口
 import {getModelIdByType, ModelPlatformEnum} from '@/api/teachers.js'
@@ -176,11 +155,16 @@ import { ModelTypeEnum } from '@/api/teachers.js'
 // 定义props
 const props = defineProps({
   //根据需求传输
+  isCourse: { type: Boolean, default: false},
   cacheDataKey: { type: String, default: localStorage.getItem('token') + "_textToImage" },
   cacheDataHistoryKey: { type: String, default: localStorage.getItem('token') + "_textToImage_history" },
   preDialogueList: { type: Array, default: () => []},
   replySupplement: { type: String, default: ''},
 })
+
+// 定义emits
+const emits = defineEmits(['saveProgress'])
+
 //历史记录缓存集合
 const cacheDataHistoryList = ref([]);
 
@@ -188,40 +172,10 @@ const cacheDataHistoryList = ref([]);
 const conversationInProgress = ref(false); // 对话是否正在进行中
 const conversationInAbortController = ref(); // 对话进行中 abort 控制器
 
-
-// 返回上一页
-const goBack = () => {
-  router.push('/ai-laboratory')
-}
-const router = useRouter()
-const route = useRoute()
-
-// 导入图片
-import question from '@/assets/icon/question.png'
-import painting from '@/assets/icon/painting.png'
-import human from '@/assets/icon/human.png'
-
-import LeftPanel from '@/components/LeftPanel.vue'
-const leftPanelRef = ref(null)
-
-
-// tts 语音
-import { useAudioPlayer } from '@/api/tts/useAudioPlayer';
-const { playAudioChunk } = useAudioPlayer();
-
-// 添加抽屉显示状态
-const drawerVisible = ref(true)
-// 添加切换抽屉显示状态的函数
-const toggleDrawer = () => {
-  drawerVisible.value = !drawerVisible.value
-}
-
 const demoImageList = [demo1, demo2, demo3, demo4]
 
   // 年级ID相关
 const gradeId = ref('')
-// 添加消息计数器变量
-const messageCount = ref(0)
 // modelId响应式变量
 const modelId = ref(0)
 
@@ -230,12 +184,7 @@ onMounted(async () => {
     // 从全局状态初始化年级ID
   gradeId.value = globalState.initGradeId()
   try{
-    const res = await saveRecord({
-        brpNjId: gradeId.value,
-        brpType: "aiCount",
-        brpProgress: 1
-      });
-      // 获取modelId
+    // 获取modelId
     const modelRes = await getModelIdByType({ type: ModelTypeEnum.TEXT_TO_IMAGE, platform: ModelPlatformEnum.DOUBAO })
     modelId.value = modelRes.data
     
@@ -260,8 +209,6 @@ onMounted(async () => {
 const messages = ref([])
 const inputMessage = ref('')
 
-
-
 // 处理语音识别结果
 const handleVoiceRecognized = (transcript) => {
   inputMessage.value += transcript;
@@ -299,21 +246,13 @@ const sendMessage = async() => {
       loading: true
     })
 
-    // 递增消息计数器
-    messageCount.value++
-    // 发送saveRecord请求 保存消息次数
-     try{
-       await saveRecord({
-          brpNjId: gradeId.value,
-          brpType: "aiCount",
-          brpProgress: messageCount.value
-        });
-        console.log('保存记录成功,消息次数:', messageCount.value);
-    }catch(error){
-      console.error('保存记录失败:', error);
-      conversationInProgress.value = false;
+    // 通过emit事件通知父组件保存进度
+    emits('saveProgress', "aiCount", 1)
+    if (props.isCourse){
+      emits('saveProgress', "course", 100)
     }
 
+
     // 同步历史记录缓存
     cacheDataHistoryList.value.push(userMsg);
     localStorage.setItem(props.cacheDataHistoryKey, JSON.stringify(cacheDataHistoryList.value));

+ 14 - 38
src/components/ai/text/TextToText.vue

@@ -71,10 +71,9 @@
 </template>
 
 <script setup>
-import { ref, onMounted,onUnmounted, computed, watch, nextTick } from "vue";
+import {ref, onMounted, onUnmounted, computed, watch, nextTick, defineEmits} from "vue";
 import { CreateDialogue, sendChatMessageStream } from "@/api/questions.js";
 import { useRouter, useRoute } from "vue-router";
-import { saveRecord } from "@/api/personalized/index.js";
 import { teacherList } from '@/api/teachers.js'
 // 导入全局状态
 import { globalState } from "@/utils/globalState.js";
@@ -86,34 +85,13 @@ import VoiceInput from '../voice/VoiceInput.vue'
 import stopicon from "@/assets/icon/stopicon.png";
 
 import MarkdownView from "@/components/MarkdownView/index.vue";
-import {
-  Document,
-  Menu as IconMenu,
-  Location,
-  Setting,
-  ArrowLeftBold,
-  MagicStick,
-  ChatLineRound,
-  Fold,
-  Expand,
-  Picture,
-  Tickets,
-  User,
-  Search, // 使用Search图标作为替代
-} from "@element-plus/icons-vue";
 
 import DefaultMessage from "@/components/DefaultMessage/index.vue";
 
-
-// 语音图标
-import { Microphone, Mute } from "@element-plus/icons-vue";
-
-import LeftPanel from "@/components/LeftPanel.vue";
-const leftPanelRef = ref(null);
-
 // 定义props
 const props = defineProps({
   //根据需求传输
+  isCourse: { type: Boolean, default: false},
   cacheDataKey: { type: String, default: localStorage.getItem('token') + "_textToText" },
   cacheDataHistoryKey: { type: String, default: localStorage.getItem('token') + "_textToText_history" },
   preDialogueList: { type: Array, default: () => []},
@@ -124,6 +102,10 @@ const props = defineProps({
   personImage: { type: String},
   personIntroduce: { type: String},
 })
+
+// 定义emits
+const emits = defineEmits(['saveProgress'])
+
 //历史记录缓存集合
 const cacheDataHistoryList = ref([]);
 
@@ -294,8 +276,6 @@ const onCompositionend = () => {
 // 保存记录
 // 年级ID相关
 const gradeId = ref("");
-// 添加消息计数器变量
-const messageCount = ref(0);
 
 /** 真正执行【发送】消息操作 */
 const doSendMessage = async (content) => {
@@ -308,18 +288,14 @@ const doSendMessage = async (content) => {
     console.error("请刷新创建新对话!");
     return;
   }
-  // 递增消息计数器
-  messageCount.value++;
-  // 发送saveRecord请求 保存消息次数
-  try {
-    await saveRecord({
-      brpNjId: gradeId.value,
-      brpType: "aiCount",
-      brpProgress: messageCount.value,
-    });
-  } catch (error) {
-    console.error("保存记录失败:", error);
+
+  // 通过emit事件通知父组件保存进度
+  emits('saveProgress', "aiCount", 1)
+  console.log(props.isCourse);
+  if (props.isCourse){
+    emits('saveProgress', "course", 100)
   }
+
   // 清空输入框
   prompt.value = "";
 
@@ -636,7 +612,7 @@ onMounted(async () => {
           console.log("创建会话:", res);
           activeConversationId.value = res.data;
           //将会话存入会话缓存
-          if (props.cacheDataKey)localStorage.setItem(props.cacheDataKey, activeConversationId.value)
+          localStorage.setItem(props.cacheDataKey, activeConversationId.value)
         })
         .catch((error) => {
           console.error("请求出错:", error);

+ 13 - 73
src/components/ai/video/ImageToVideo.vue

@@ -98,33 +98,14 @@
 </template>
 
 <script setup>
-import { ref, onMounted,onUnmounted} from 'vue'
-import {AiImageStatusEnum, CreatePainting, PaintingGetMys,CreateVideo, VideoGetMys} from '@/api/questions.js'
-import { useRouter, useRoute } from 'vue-router'
-import {
-  Document,
-  Menu as IconMenu,
-  Location,
-  Setting,
-  ArrowLeftBold,
-  Fold,
-  Expand,
-  ChatLineRound,
-  Picture,
-  MagicStick,
-  Tickets,
-  User
-} from '@element-plus/icons-vue'
-
-import { saveRecord } from '@/api/personalized/index.js'
+import {ref, onMounted, onUnmounted, defineEmits} from 'vue'
+import {AiImageStatusEnum, CreateVideo, VideoGetMys} from '@/api/questions.js'
+import { useRouter } from 'vue-router'
 
 import VoiceInput from '../voice/VoiceInput.vue'
 
-
 // 导入全局状态
 import { globalState } from '@/utils/globalState.js'
-// 语音图标
-import { Microphone, Mute } from "@element-plus/icons-vue";
 // 终止按钮
 import stopicon from "@/assets/icon/stopicon.png";
 // 消息组件
@@ -139,11 +120,16 @@ import { ModelTypeEnum } from '@/api/teachers.js'
 // 定义props
 const props = defineProps({
   //根据需求传输
+  isCourse: { type: Boolean, default: false},
   cacheDataKey: { type: String, default: localStorage.getItem('token') + "_imageToVideo" },
   cacheDataHistoryKey: { type: String, default: localStorage.getItem('token') + "_imageToVideo_history" },
   preDialogueList: { type: Array, default: () => []},
   replySupplement: { type: String, default: ''},
 })
+
+// 定义emits
+const emits = defineEmits(['saveProgress'])
+
 //历史记录缓存集合
 const cacheDataHistoryList = ref([]);
 
@@ -151,45 +137,13 @@ const cacheDataHistoryList = ref([]);
 const uploadedImage = ref('');
 const imageUploadRef = ref(null);
 
-// 语音输入响应式变量
-
 // 对话状态变量
 const conversationInProgress = ref(false); // 对话是否正在进行中
 const conversationInAbortController = ref(); // 对话进行中 abort 控制器
-
-
-// 返回上一页
-const goBack = () => {
-  router.push('/ai-laboratory')
-}
 const router = useRouter()
-const route = useRoute()
-
-// 导入图片
-import question from '@/assets/icon/question.png'
-import painting from '@/assets/icon/painting.png'
-import human from '@/assets/icon/human.png'
-
-import LeftPanel from '@/components/LeftPanel.vue'
-const leftPanelRef = ref(null)
-
-
-// tts 语音
-import { useAudioPlayer } from '@/api/tts/useAudioPlayer';
-const { playAudioChunk } = useAudioPlayer();
-
-// 添加抽屉显示状态
-const drawerVisible = ref(true)
-// 添加切换抽屉显示状态的函数
-const toggleDrawer = () => {
-  drawerVisible.value = !drawerVisible.value
-}
-
 
   // 年级ID相关
 const gradeId = ref('')
-// 添加消息计数器变量
-const messageCount = ref(0)
 // modelId响应式变量
 const modelId = ref(0)
 // 保存记录
@@ -197,12 +151,7 @@ onMounted(async () => {
     // 从全局状态初始化年级ID
   gradeId.value = globalState.initGradeId()
   try{
-    const res = await saveRecord({
-        brpNjId: gradeId.value,
-        brpType: "aiCount",
-        brpProgress: 1
-      });
-      // 获取modelId
+    // 获取modelId
     const modelRes = await getModelIdByType({ type: ModelTypeEnum.IMAGE_TO_VIDEO, platform: "DouBao" })
     modelId.value = modelRes.data
   }catch(error){
@@ -272,19 +221,10 @@ const sendMessage = async() => {
       loading: true
     })
 
-    // 递增消息计数器
-    messageCount.value++
-    // 发送saveRecord请求 保存消息次数
-     try{
-       await saveRecord({
-          brpNjId: gradeId.value,
-          brpType: "aiCount",
-          brpProgress: messageCount.value
-        });
-        console.log('保存记录成功,消息次数:', messageCount.value);
-    }catch(error){
-      console.error('保存记录失败:', error);
-      conversationInProgress.value = false;
+    // 通过emit事件通知父组件保存进度
+    emits('saveProgress', "aiCount", 1)
+    if (props.isCourse){
+      emits('saveProgress', "course", 100)
     }
 
     // 同步历史记录缓存

+ 5 - 20
src/components/videopage/DialogComponents.vue

@@ -175,11 +175,11 @@ const props = defineProps({
   currentQuestion: { type: Object, default: () => ({}) },
   gradeId: { type: String, default: '' },
   typeId: { type: String, default: '' },
-  courseId: { type: String, default: '' }
+  courseId: { type: String, default: '' },
 })
 
 // 定义emits
-const emits = defineEmits(['closeQuestionDialog', 'submitAnswer'])
+const emits = defineEmits(['closeQuestionDialog', 'submitAnswer', 'saveProgress'])
 
 // 内部状态
 const showAIDialog = ref(false)
@@ -187,7 +187,6 @@ const selectedOption = ref(null)
 const messageList = ref([])
 const prompt = ref('')
 const messageContainer = ref(null)
-const aiQuestionCount = ref(0)
 const userScrolled = ref(false) //是否用户手动滚动
 const xZAiData = ref({})
 const activeConversationId = ref(null)
@@ -305,23 +304,6 @@ const sendMessage = async () => {
       content: prompt.value
     })
 
-    // 增加问答次数
-    aiQuestionCount.value++
-
-    //没有传入年级id(blockly课程),不保存问答次数
-    if (props.componentType === 'course'){
-      // 保存AI问答次数
-      try {
-        await saveRecord({
-          brpNjId: props.gradeId,
-          brpType: 'aiCount',
-          brpProgress: aiQuestionCount.value
-        })
-      } catch (error) {
-        console.error('保存AI问答次数失败:', error)
-      }
-    }
-
     // // 模拟 AI 回复
     // const aiResponse = await simulateAIResponse(prompt.value)
     // messageList.value.push({
@@ -474,6 +456,9 @@ const doSendMessage = async content => {
     return
   }
 
+  // 通过emit事件通知父组件保存进度
+  emits('saveProgress', "aiCount", 1)
+
   // 清空输入框
   prompt.value = ''
   // 执行发送

+ 53 - 24
src/views/AIPage/AIDevelop.vue

@@ -128,31 +128,47 @@
               @saveProgress="handleSaveProgress"
           />
           <!-- 图片 -->
-          <ImageView v-if="course.courseContentType === 'image'" 
-                     :imagePath="course.courseImagePath" 
+          <ImageView v-if="course.courseContentType === 'image'"
+                     :imagePath="course.courseImagePath"
                      altText="课程图片"
                      :courseId="course.id"
                      @saveProgress="handleSaveProgress"
           ></ImageView>
 
           <!-- PPT -->
-          <PptView v-if="course.courseContentType === 'ppt'" 
-                  :pptPath="course.pptPath" 
+          <PptView v-if="course.courseContentType === 'ppt'"
+                  :pptPath="course.pptPath"
                   :courseId="course.id"
                   @saveProgress="handleSaveProgress"
                   ref="pptRef"></PptView>
 
           <!--文生文-->
-          <TextToText class="contentClass" v-if="course.courseContentType === 'aiTextToText'" ref="aiTextToText"></TextToText>
+          <TextToText class="contentClass" v-if="course.courseContentType === 'aiTextToText'" ref="aiTextToText"
+                      :isCourse="true"
+                      :cacheDataKey="course.cacheDataKey"
+                      :cacheDataHistoryKey="course.cacheDataHistoryKey"
+                     @saveProgress="handleSaveProgress"></TextToText>
 
           <!--文生图-->
-          <TextToImage class="contentClass" v-if="course.courseContentType === 'aiTextToImage'" ref="aiTextToImage"></TextToImage>
+          <TextToImage class="contentClass" v-if="course.courseContentType === 'aiTextToImage'" ref="aiTextToImage"
+                       :isCourse="true"
+                       :cacheDataKey="course.cacheDataKey"
+                       :cacheDataHistoryKey="course.cacheDataHistoryKey"
+                     @saveProgress="handleSaveProgress"></TextToImage>
 
           <!--图生图-->
-          <ImageToImage class="contentClass" v-if="course.courseContentType === 'aiImageToImage'" ref="aiImageToImage"></ImageToImage>
+          <ImageToImage class="contentClass" v-if="course.courseContentType === 'aiImageToImage'" ref="aiImageToImage"
+                        :isCourse="true"
+                        :cacheDataKey="course.cacheDataKey"
+                        :cacheDataHistoryKey="course.cacheDataHistoryKey"
+                     @saveProgress="handleSaveProgress"></ImageToImage>
 
           <!--图生视频-->
-          <ImageToVideo class="contentClass" v-if="course.courseContentType === 'aiImageToVideo'" ref="aiImageToVideo"></ImageToVideo>
+          <ImageToVideo class="contentClass" v-if="course.courseContentType === 'aiImageToVideo'" ref="aiImageToVideo"
+                        :isCourse="true"
+                        :cacheDataKey="course.cacheDataKey"
+                        :cacheDataHistoryKey="course.cacheDataHistoryKey"
+                     @saveProgress="handleSaveProgress"></ImageToVideo>
         </template>
 
         <!-- 视频切换按钮 - 始终显示 -->
@@ -181,6 +197,7 @@
       :courseId="course.id || ''" 
       @closeQuestionDialog="closeQuestionDialog"
       @submitAnswer="handleSubmitAnswer"
+      @saveProgress="handleSaveProgress"
     />
 
   </div>
@@ -189,9 +206,7 @@
 <script setup>
 import { ref, onMounted, onBeforeUnmount, computed } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
-import { Expand, Fold, Memo } from '@element-plus/icons-vue'
 import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
-import { ElMessage, ElMessageBox, ElNotification, valueEquals } from 'element-plus'
 import isDisabledImage from '@/assets/images/permission/isDisabled.png'
 
 import classImages from '@/assets/icon/class.png'
@@ -220,10 +235,7 @@ import ImageToVideo from "@/components/ai/video/ImageToVideo.vue";
 import {DICT_TYPE} from "@/utils/dictUtils.js";
 
 const router = useRouter() // 获取当前路由对象
-const route = useRoute()
 
-// 添加按钮显示状态
-const buttonVisible = ref(false)
 // 添加抽屉显示状态
 const drawerVisible = ref(false)
 // 渲染页面标题
@@ -258,18 +270,26 @@ const isDisabled = ref(false)
 
 // 保存视频进度接口
 const handleSaveProgress = async (type, progress) => {
-    try {
-      await saveRecord({
-        brpNjId: gradeId.value,
-        brpCtId: typeId.value,
-        brpCourseId: course.value.id,
-        brpType: type,
-        brpProgress: progress
-      })
-    } catch (error) {
-      console.error('保存视频进度失败:', error)
-    }
+
+  if (!progress) {
+    return;
+  }
+  let saveProgressData = {
+    brpNjId: gradeId.value,
+    brpType: type,
+    brpProgress: progress
   }
+  // aiCount类型不需要添加课程大纲id和课程小节id
+  if (type !== "aiCount") {
+    saveProgressData.brpCtId = typeId.value
+    saveProgressData.brpCourseId = course.value.id
+  }
+  try {
+    await saveRecord(saveProgressData)
+  } catch (error) {
+    console.error('保存视频进度失败:', error)
+  }
+}
 
 //课程小节字典
 const menuDict = ref({
@@ -300,6 +320,7 @@ const handleSelect = index => {
   // 根据索引切换视频
   if (videoPathMap.value[index]) {
     course.value = videoPathMap.value[index]
+    setCacheDataKey()
     courseId.value = course.value.id
     // 切换标题后,关闭抽屉
     drawerVisible.value = false
@@ -312,6 +333,13 @@ const handleSelect = index => {
   if (disableMsg(index)) return
 }
 
+//填充阎村key
+const setCacheDataKey = () => {
+  // 设置缓存key
+  course.value.cacheDataKey = localStorage.getItem("token") + "_course_" + course.value.id
+  course.value.cacheDataHistoryKey = course.value.cacheDataKey + "_history"
+}
+
 // 展平所有菜单项索引
 const flattenMenuItems = () => {
   const indices = []
@@ -555,6 +583,7 @@ onMounted(async () => {
           courseId.value = courseTemp.id
           if(!disableMsg(menuIndex)){
             course.value = courseTemp
+            setCacheDataKey()
           }else{
             course.value.key = courseTemp.key
             course.value.courseName = courseTemp.courseName

+ 38 - 21
src/views/laboratory/ExperimentalInterface.vue

@@ -57,31 +57,39 @@
 
           <!--文生文-->
           <TextToText class="contentClass" v-if="course.courseContentType === 'aiTextToText'" ref="aiTextToText"
+                      :isCourse="true"
                       :cacheDataKey="course.cacheDataKey"
                       :cacheDataHistoryKey="course.cacheDataHistoryKey"
                       :preDialogueList="course.aiPreDialogueList"
-                      :replySupplement="course.aiReplySupplement"></TextToText>
+                      :replySupplement="course.aiReplySupplement"
+                      @saveProgress="handleSaveProgress"></TextToText>
 
           <!--文生图-->
           <TextToImage class="contentClass" v-if="course.courseContentType === 'aiTextToImage'" ref="aiTextToImage"
+                       :isCourse="true"
                        :cacheDataKey="course.cacheDataKey"
                        :cacheDataHistoryKey="course.cacheDataHistoryKey"
                        :preDialogueList="course.aiPreDialogueList"
-                       :replySupplement="course.aiReplySupplement"></TextToImage>
+                       :replySupplement="course.aiReplySupplement"
+                       @saveProgress="handleSaveProgress"></TextToImage>
 
           <!--图生图-->
           <ImageToImage class="contentClass" v-if="course.courseContentType === 'aiImageToImage'" ref="aiImageToImage"
+                        :isCourse="true"
                         :cacheDataKey="course.cacheDataKey"
                         :cacheDataHistoryKey="course.cacheDataHistoryKey"
                         :preDialogueList="course.aiPreDialogueList"
-                        :replySupplement="course.aiReplySupplement"></ImageToImage>
+                        :replySupplement="course.aiReplySupplement"
+                        @saveProgress="handleSaveProgress"></ImageToImage>
 
           <!--图生视频-->
           <ImageToVideo class="contentClass" v-if="course.courseContentType === 'aiImageToVideo'" ref="aiImageToVideo"
+                        :isCourse="true"
                         :cacheDataKey="course.cacheDataKey"
                         :cacheDataHistoryKey="course.cacheDataHistoryKey"
                         :preDialogueList="course.aiPreDialogueList"
-                        :replySupplement="course.aiReplySupplement"></ImageToVideo>
+                        :replySupplement="course.aiReplySupplement"
+                        @saveProgress="handleSaveProgress"></ImageToVideo>
           
         </template>
 
@@ -112,6 +120,7 @@
       :courseId="course.id || ''" 
       @closeQuestionDialog="closeQuestionDialog"
       @submitAnswer="handleSubmitAnswer"
+      @saveProgress="handleSaveProgress"
     />
 
   </div>
@@ -125,7 +134,7 @@ import { ElMessage } from 'element-plus'
 import isDisabledImage from '@/assets/images/permission/isDisabled.png'
 import { ClassType } from '@/api/class.js'
 import { Message } from '@/utils/message/Message.js'
-import { saveRecordBlockly } from '@/api/personalized/index.js'
+import { saveRecordAiCourse } from '@/api/personalized/index.js'
 // 导入图标
 import leftImg from '@/assets/icon/backward.png'
 import rightImg from '@/assets/icon/f-backward.png'
@@ -291,13 +300,13 @@ const handleVideoTimeUpdate = async ({ currentTime, progressPercentage, courseCo
       }
       if (config.id) {
         // 保存弹窗问题进度
-        await saveRecordBlockly({
-          brpZtId: props.courseData?.ztId,
-          brpCtId: props.courseData?.acType,
-          brpCourseConfigId: config.id,
-          brpCourseId: courseId.value,
-          brpType: 'courseQuest',
-          brpProgress: 1
+        await saveRecordAiCourse({
+          arpZtId: props.courseData?.ztId,
+          arpCtId: props.courseData?.acType,
+          arpCourseConfigId: config.id,
+          arpCourseId: courseId.value,
+          arpType: 'courseQuest',
+          arpProgress: 1
         })
       }
     } catch (error) {
@@ -339,8 +348,8 @@ const handleParentCourseData = (courseData = props.courseData) => {
   }
   courseId.value = course.value.id
 
-  // 设置对话ID
-  course.value.cacheDataKey = localStorage.getItem("token") + "-" + course.value.id
+  // 设置缓存key
+  course.value.cacheDataKey = localStorage.getItem("token") + "_aiCourse_" + course.value.id
   course.value.cacheDataHistoryKey = course.value.cacheDataKey + "_history"
 
   // 如果有配置,禁用视频检查
@@ -426,14 +435,22 @@ onUnmounted(() => {})
 
 // 保存视频/bockly进度接口
 const handleSaveProgress = async (type, progress) => {
+  if (!progress) {
+    return;
+  }
+  let saveProgressData = {
+    arpZtId: props.courseData?.ztId,
+    arpType: type,
+    arpProgress: progress
+  }
+  // aiCount类型不需要添加课程大纲id和课程小节id
+  if (type !== "aiCount") {
+    saveProgressData.arpCtId = props.courseData?.acType;
+    saveProgressData.arpCourseId = course.value.id;
+  }
   try {
-    await saveRecordBlockly({
-      brpZtId: props.courseData?.ztId,
-      brpCtId: props.courseData?.acType,
-      brpCourseId: course.value.id,
-      brpType: type,
-      brpProgress: progress
-    })
+    debugger
+    await saveRecordAiCourse(saveProgressData)
   } catch (error) {
     console.error(`保存${type}进度失败:`, error)
   }

+ 41 - 11
src/views/programming/Interface.vue

@@ -54,16 +54,32 @@
                   ref="pptRef"></PptView>
 
           <!--文生文-->
-          <TextToText class="contentClass" v-if="course.courseContentType === 'aiTextToText'" ref="aiTextToText"></TextToText>
+          <TextToText class="contentClass" v-if="course.courseContentType === 'aiTextToText'" ref="aiTextToText"
+                      :isCourse="true"
+                      :cacheDataKey="course.cacheDataKey"
+                      :cacheDataHistoryKey="course.cacheDataHistoryKey"
+                      @saveProgress="handleSaveProgress"></TextToText>
 
           <!--文生图-->
-          <TextToImage class="contentClass" v-if="course.courseContentType === 'aiTextToImage'" ref="aiTextToImage"></TextToImage>
+          <TextToImage class="contentClass" v-if="course.courseContentType === 'aiTextToImage'" ref="aiTextToImage"
+                       :isCourse="true"
+                       :cacheDataKey="course.cacheDataKey"
+                       :cacheDataHistoryKey="course.cacheDataHistoryKey"
+                       @saveProgress="handleSaveProgress"></TextToImage>
 
           <!--图生图-->
-          <ImageToImage class="contentClass" v-if="course.courseContentType === 'aiImageToImage'" ref="aiImageToImage"></ImageToImage>
+          <ImageToImage class="contentClass" v-if="course.courseContentType === 'aiImageToImage'" ref="aiImageToImage"
+                        :isCourse="true"
+                        :cacheDataKey="course.cacheDataKey"
+                        :cacheDataHistoryKey="course.cacheDataHistoryKey"
+                        @saveProgress="handleSaveProgress"></ImageToImage>
 
           <!--图生视频-->
-          <ImageToVideo class="contentClass" v-if="course.courseContentType === 'aiImageToVideo'" ref="aiImageToVideo"></ImageToVideo>
+          <ImageToVideo class="contentClass" v-if="course.courseContentType === 'aiImageToVideo'" ref="aiImageToVideo"
+                        :isCourse="true"
+                        :cacheDataKey="course.cacheDataKey"
+                        :cacheDataHistoryKey="course.cacheDataHistoryKey"
+                        @saveProgress="handleSaveProgress"></ImageToVideo>
           
           <!--编程地图游戏-->
           <MapGame v-if="course.courseContentType === 'blockly'"
@@ -113,6 +129,7 @@
       :courseId="course.id || ''" 
       @closeQuestionDialog="closeQuestionDialog"
       @submitAnswer="handleSubmitAnswer"
+      @saveProgress="handleSaveProgress"
     />
 
   </div>
@@ -331,6 +348,11 @@ const handleParentCourseData = (courseData = props.courseData) => {
     isDisabled: courseData.isDisabled,
   };
   courseId.value = course.value.id;
+
+  // 设置缓存key
+  course.value.cacheDataKey = localStorage.getItem("token") + "_blockly_" + course.value.id
+  course.value.cacheDataHistoryKey = course.value.cacheDataKey + "_history"
+
   // 如果有配置,禁用视频检查
   if (courseData.isDisabled) {
     Message().notifyWarning('您的账号并未开放此课程!', true)
@@ -414,14 +436,22 @@ onMounted(async () => {
 
 // 保存视频/bockly进度接口
 const handleSaveProgress = async (type, progress) => {
+  if (!progress) {
+    return;
+  }
+  let saveProgressData = {
+    brpZtId: props.courseData.ztId,
+    brpType: type,
+    brpProgress: progress
+  }
+  // aiCount类型不需要添加课程大纲id和课程小节id
+  if (type !== "aiCount") {
+    saveProgressData.brpCtId = props.courseData.bcType;
+    saveProgressData.brpCourseId = course.value.id;
+  }
   try {
-    await saveRecordBlockly({
-      brpZtId: props.courseData.ztId,
-      brpCtId: props.courseData.bcType,
-      brpCourseId: course.value.id,
-      brpType: type,
-      brpProgress: progress
-    })
+    debugger
+    await saveRecordBlockly(saveProgressData)
   } catch (error) {
     console.error(`保存${type}进度失败:`, error)
   }