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

Merge branch 'beta' of https://git.cocorobo.cn/jack/PPT into beta

jack 1 неделя назад
Родитель
Сommit
eb0bb60930

+ 14 - 5
src/components/CollapsibleToolbar/componets/aiChat.vue

@@ -32,7 +32,7 @@
                                 keySplines=".33,.66,.66,1;.33,0,.66,.33" values="12;6;12" />
                         </circle>
                     </svg>
-                    <button class="confirm-btn" v-if="message.jsonData?.gType !== 'chat' && !message.chatloading && message.aiContent"
+                    <button class="confirm-btn" :class="{ disabled: message.jsonData?.isGenerate }" v-if="message.jsonData?.gType !== 'chat' && !message.chatloading && message.aiContent"
                         @click="generate(message)">{{ message.gLoading ? lang.ssLoading : lang.ssConfirm}}</button>
                 </div>
             </div>
@@ -133,6 +133,7 @@ interface ChatMessage {
     }>
     jsonData?: {
         gType?: string
+        isGenerate?: boolean
         headUrl?: string
         assistantName?: string
         files?: Array<{
@@ -338,13 +339,15 @@ const sendAction = async (action: string) => {
     // generate_qa // generate_choice_question
     if (gType.value !== 'chat') {
       messages.value.at(-1).jsonData = {
-        gType: gType.value
+        gType: gType.value,
+        isGenerate: false
       }
     }
   }
   else {
     messages.value.at(-1).jsonData = {
-      gType: gType.value
+      gType: gType.value,
+      isGenerate: false
     }
   }
 
@@ -381,7 +384,7 @@ const { createSlide } = useSlideHandler()
 const { createFrameElement } = useCreateElement()
 
 const generate = (message: ChatMessage) => {
-  if (message.gLoading) {
+  if (message.gLoading || message.jsonData?.isGenerate) {
     return
   }
   message.gLoading = true
@@ -401,6 +404,7 @@ const generate = (message: ChatMessage) => {
         createSlide()
         createFrameElement(url, 45)
         message.gLoading = false
+        message.jsonData.isGenerate = true
       })
     })
   }
@@ -420,6 +424,7 @@ const generate = (message: ChatMessage) => {
         createSlide()
         createFrameElement(url, 15)
         message.gLoading = false
+        message.jsonData.isGenerate = true
       })
     })
   }
@@ -777,6 +782,10 @@ onMounted(() => {
     &:hover {
         background: #E68A00;
     }
+    &.disabled {
+        background: #9CA3AF;
+        cursor: not-allowed;
+    }
 }
 
 ul {
@@ -814,7 +823,7 @@ ul {
         transition: all 0.2s ease;
 
         &:hover {
-            background: #F3F4F6;
+            background: #fff4e5;
         }
     }
 }

+ 293 - 124
src/views/Student/components/choiceQuestionDetailDialog.vue

@@ -16,19 +16,22 @@
               .teststitle
           }}</div>
           <div class="c_t45_msg">
-            <div>{{ lang.ssAnswerCount }} {{ props.showData.workArray.length}}<span v-if="props.showData.unsubmittedStudents.length > 0">/{{ props.showData.unsubmittedStudents.length }}</span></div>
-            <span v-if="props.showData.unsubmittedStudents.length > 0" @click="viewUnsubmittedStudents()">{{ lang.ssViewUnsubmittedStudents }}</span>
+            <div>{{ lang.ssAnswerCount }} {{ props.showData.workArray.length }}<span
+                v-if="props.showData.unsubmittedStudents.length > 0">/{{ props.showData.unsubmittedStudents.length
+                }}</span></div>
+            <span v-if="props.showData.unsubmittedStudents.length > 0" @click="viewUnsubmittedStudents()">{{
+              lang.ssViewUnsubmittedStudents }}</span>
           </div>
           <!--<span class="c_t45_t_btn" :class="{'c_t45_t_btn_noActive': props.showData.workIndex <= 0}" @click="changeWorkIndex(0)">{{ lang.ssPrevQ }}</span>-->
           <!--<span class="c_t45_t_btn" :class="{'c_t45_t_btn_noActive': props.showData.workIndex >= props.showData.choiceQuestionListData.length - 1}" @click="changeWorkIndex(1)">{{ lang.ssNextQ }}</span>-->
         </div>
         <img class="c_t45_img" :src="props.showData.choiceQuestionListData[props.showData.workIndex]
-            .timuList[0].src
+          .timuList[0].src
           " v-if="props.showData.choiceQuestionListData[props.showData.workIndex] &&
             props.showData.choiceQuestionListData[props.showData.workIndex]
               .timuList.length > 0
           " @click="previewImageToolRef.previewImage(props.showData.choiceQuestionListData[props.showData.workIndex]
-            .timuList[0].src)"/>
+            .timuList[0].src)" />
         <!-- <span class="c_t45_type" v-if="
           props.showData.choiceQuestionListData[props.showData.workIndex]
             .type === '1'
@@ -43,21 +46,34 @@
         }">
           <div id="echartsArea1" ref="echartsArea1"></div>
         </div>
-        <div class="aiAnalysis" v-if="props.workArray.length>0">
+        <div class="aiAnalysis" v-if="props.workArray.length > 0">
           <div class="ai_header">
             <div class="ai_title">
-              <svg viewBox="0 0 1024 1024" width="200" height="200"><path d="M512 170.666667C323.477333 170.666667 170.666667 323.477333 170.666667 512s152.810667 341.333333 341.333333 341.333333 341.333333-152.810667 341.333333-341.333333S700.522667 170.666667 512 170.666667zM85.333333 512C85.333333 276.352 276.352 85.333333 512 85.333333s426.666667 191.018667 426.666667 426.666667-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512z"></path><path d="M693.013333 330.986667a42.666667 42.666667 0 0 1 10.304 43.648l-75.413333 226.282666a42.666667 42.666667 0 0 1-26.986667 26.986667l-226.282666 75.413333a42.666667 42.666667 0 0 1-53.973334-53.973333l75.434667-226.261333a42.666667 42.666667 0 0 1 26.986667-26.986667l226.282666-75.413333a42.666667 42.666667 0 0 1 43.648 10.304z m-222.72 139.306666l-41.685333 125.098667 125.077333-41.706667 41.706667-125.077333-125.077333 41.706667z"></path></svg>{{ lang.ssAnalysis }}
+              <svg viewBox="0 0 1024 1024" width="200" height="200">
+                <path
+                  d="M512 170.666667C323.477333 170.666667 170.666667 323.477333 170.666667 512s152.810667 341.333333 341.333333 341.333333 341.333333-152.810667 341.333333-341.333333S700.522667 170.666667 512 170.666667zM85.333333 512C85.333333 276.352 276.352 85.333333 512 85.333333s426.666667 191.018667 426.666667 426.666667-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512z">
+                </path>
+                <path
+                  d="M693.013333 330.986667a42.666667 42.666667 0 0 1 10.304 43.648l-75.413333 226.282666a42.666667 42.666667 0 0 1-26.986667 26.986667l-226.282666 75.413333a42.666667 42.666667 0 0 1-53.973334-53.973333l75.434667-226.261333a42.666667 42.666667 0 0 1 26.986667-26.986667l226.282666-75.413333a42.666667 42.666667 0 0 1 43.648 10.304z m-222.72 139.306666l-41.685333 125.098667 125.077333-41.706667 41.706667-125.077333-125.077333 41.706667z">
+                </path>
+              </svg>{{ lang.ssAnalysis }}
             </div>
-            <div class="ai_refresh" :class="{'disabled': currentAnalysis && currentAnalysis.loading}" @click="aiAnalysisRefresh45()">
+            <div class="ai_refresh" :class="{ 'disabled': currentAnalysis && currentAnalysis.loading }"
+              @click="aiAnalysisRefresh45()">
               {{ lang.ssAIGenerate }}
-             <svg viewBox="0 0 1024 1024" width="200" height="200"><path d="M875 483c-33.4 0-60.5 27.1-60.5 60.5v0.1C814.4 710.3 678.8 846 512 846S209.5 710.3 209.5 543.5 345.2 241 512 241c36.8 0 71.7 7.6 104.4 19.7-32 3-57.4 29.1-57.4 61.9 0 34.8 28.2 63 63 63h201.9c34.8 0 63-28.2 63-63V120c0-34.8-28.2-63-63-63s-63 28.2-63 63v81.4C691 150.5 605.2 120 512 120 278.1 120 88.5 309.6 88.5 543.5S278.1 967 512 967s423.5-189.6 423.5-423.5c0-33.4-27.1-60.5-60.5-60.5z"></path></svg>
+              <svg viewBox="0 0 1024 1024" width="200" height="200">
+                <path
+                  d="M875 483c-33.4 0-60.5 27.1-60.5 60.5v0.1C814.4 710.3 678.8 846 512 846S209.5 710.3 209.5 543.5 345.2 241 512 241c36.8 0 71.7 7.6 104.4 19.7-32 3-57.4 29.1-57.4 61.9 0 34.8 28.2 63 63 63h201.9c34.8 0 63-28.2 63-63V120c0-34.8-28.2-63-63-63s-63 28.2-63 63v81.4C691 150.5 605.2 120 512 120 278.1 120 88.5 309.6 88.5 543.5S278.1 967 512 967s423.5-189.6 423.5-423.5c0-33.4-27.1-60.5-60.5-60.5z">
+                </path>
+              </svg>
 
             </div>
           </div>
           <div class="ai_content" v-if="currentAnalysis">
             {{ currentAnalysis.json }}
           </div>
-          <div class="ai_updateTime" v-if="currentAnalysis">{{ lang.ssUpdateTime }}:{{ currentAnalysis.update_at }}</div>
+          <div class="ai_updateTime" v-if="currentAnalysis">{{ lang.ssUpdateTime }}:{{ currentAnalysis.update_at }}
+          </div>
         </div>
         <div class="cq_changeBtn" v-if="props.showData.choiceQuestionListData.length > 1">
           <div :class="{ cq_cb_disabled: props.showData.workIndex <= 0 }" @click="changeWorkIndex(0)">
@@ -67,7 +83,7 @@
                 fill=""></path>
             </svg>
           </div>
-          <span>{{ props.showData.workIndex+1 }}/{{ props.showData.choiceQuestionListData.length }}</span>
+          <span>{{ props.showData.workIndex + 1 }}/{{ props.showData.choiceQuestionListData.length }}</span>
           <div :class="{ cq_cb_disabled: props.showData.workIndex >= props.showData.choiceQuestionListData.length - 1 }"
             @click="changeWorkIndex(1)">
             <svg style="transform: rotate(90deg);" viewBox="0 0 1024 1024" version="1.1" width="200" height="200">
@@ -95,21 +111,34 @@
           </div>
         </div>
 
-       <div class="aiAnalysis" style="margin-top:1rem ;" v-if="processedWorkArray.length>0">
+        <div class="aiAnalysis" style="margin-top:1rem ;" v-if="processedWorkArray.length > 0">
           <div class="ai_header">
             <div class="ai_title">
-              <svg viewBox="0 0 1024 1024" width="200" height="200"><path d="M512 170.666667C323.477333 170.666667 170.666667 323.477333 170.666667 512s152.810667 341.333333 341.333333 341.333333 341.333333-152.810667 341.333333-341.333333S700.522667 170.666667 512 170.666667zM85.333333 512C85.333333 276.352 276.352 85.333333 512 85.333333s426.666667 191.018667 426.666667 426.666667-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512z"></path><path d="M693.013333 330.986667a42.666667 42.666667 0 0 1 10.304 43.648l-75.413333 226.282666a42.666667 42.666667 0 0 1-26.986667 26.986667l-226.282666 75.413333a42.666667 42.666667 0 0 1-53.973334-53.973333l75.434667-226.261333a42.666667 42.666667 0 0 1 26.986667-26.986667l226.282666-75.413333a42.666667 42.666667 0 0 1 43.648 10.304z m-222.72 139.306666l-41.685333 125.098667 125.077333-41.706667 41.706667-125.077333-125.077333 41.706667z"></path></svg>{{ lang.ssAnalysis }}
+              <svg viewBox="0 0 1024 1024" width="200" height="200">
+                <path
+                  d="M512 170.666667C323.477333 170.666667 170.666667 323.477333 170.666667 512s152.810667 341.333333 341.333333 341.333333 341.333333-152.810667 341.333333-341.333333S700.522667 170.666667 512 170.666667zM85.333333 512C85.333333 276.352 276.352 85.333333 512 85.333333s426.666667 191.018667 426.666667 426.666667-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512z">
+                </path>
+                <path
+                  d="M693.013333 330.986667a42.666667 42.666667 0 0 1 10.304 43.648l-75.413333 226.282666a42.666667 42.666667 0 0 1-26.986667 26.986667l-226.282666 75.413333a42.666667 42.666667 0 0 1-53.973334-53.973333l75.434667-226.261333a42.666667 42.666667 0 0 1 26.986667-26.986667l226.282666-75.413333a42.666667 42.666667 0 0 1 43.648 10.304z m-222.72 139.306666l-41.685333 125.098667 125.077333-41.706667 41.706667-125.077333-125.077333 41.706667z">
+                </path>
+              </svg>{{ lang.ssAnalysis }}
             </div>
-            <div class="ai_refresh" :class="{'disabled': currentAnalysis && currentAnalysis.loading}" @click="aiAnalysisRefresh15()">
+            <div class="ai_refresh" :class="{ 'disabled': currentAnalysis && currentAnalysis.loading }"
+              @click="aiAnalysisRefresh15()">
               {{ lang.ssAIGenerate }}
-             <svg viewBox="0 0 1024 1024" width="200" height="200"><path d="M875 483c-33.4 0-60.5 27.1-60.5 60.5v0.1C814.4 710.3 678.8 846 512 846S209.5 710.3 209.5 543.5 345.2 241 512 241c36.8 0 71.7 7.6 104.4 19.7-32 3-57.4 29.1-57.4 61.9 0 34.8 28.2 63 63 63h201.9c34.8 0 63-28.2 63-63V120c0-34.8-28.2-63-63-63s-63 28.2-63 63v81.4C691 150.5 605.2 120 512 120 278.1 120 88.5 309.6 88.5 543.5S278.1 967 512 967s423.5-189.6 423.5-423.5c0-33.4-27.1-60.5-60.5-60.5z"></path></svg>
+              <svg viewBox="0 0 1024 1024" width="200" height="200">
+                <path
+                  d="M875 483c-33.4 0-60.5 27.1-60.5 60.5v0.1C814.4 710.3 678.8 846 512 846S209.5 710.3 209.5 543.5 345.2 241 512 241c36.8 0 71.7 7.6 104.4 19.7-32 3-57.4 29.1-57.4 61.9 0 34.8 28.2 63 63 63h201.9c34.8 0 63-28.2 63-63V120c0-34.8-28.2-63-63-63s-63 28.2-63 63v81.4C691 150.5 605.2 120 512 120 278.1 120 88.5 309.6 88.5 543.5S278.1 967 512 967s423.5-189.6 423.5-423.5c0-33.4-27.1-60.5-60.5-60.5z">
+                </path>
+              </svg>
 
             </div>
           </div>
           <div class="ai_content" v-if="currentAnalysis">
             {{ currentAnalysis.json }}
           </div>
-          <div class="ai_updateTime" v-if="currentAnalysis">{{ lang.ssUpdateTime }}:{{ currentAnalysis.update_at }}</div>
+          <div class="ai_updateTime" v-if="currentAnalysis">{{ lang.ssUpdateTime }}:{{ currentAnalysis.update_at }}
+          </div>
         </div>
 
 
@@ -142,6 +171,36 @@
           </div>
         </div>
 
+        <div class="aiAnalysis" style="margin-top:1rem ;" v-show="!lookWorkData" v-if="processedWorkArray.length > 0">
+          <div class="ai_header">
+            <div class="ai_title">
+              <svg viewBox="0 0 1024 1024" width="200" height="200">
+                <path
+                  d="M512 170.666667C323.477333 170.666667 170.666667 323.477333 170.666667 512s152.810667 341.333333 341.333333 341.333333 341.333333-152.810667 341.333333-341.333333S700.522667 170.666667 512 170.666667zM85.333333 512C85.333333 276.352 276.352 85.333333 512 85.333333s426.666667 191.018667 426.666667 426.666667-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512z">
+                </path>
+                <path
+                  d="M693.013333 330.986667a42.666667 42.666667 0 0 1 10.304 43.648l-75.413333 226.282666a42.666667 42.666667 0 0 1-26.986667 26.986667l-226.282666 75.413333a42.666667 42.666667 0 0 1-53.973334-53.973333l75.434667-226.261333a42.666667 42.666667 0 0 1 26.986667-26.986667l226.282666-75.413333a42.666667 42.666667 0 0 1 43.648 10.304z m-222.72 139.306666l-41.685333 125.098667 125.077333-41.706667 41.706667-125.077333-125.077333 41.706667z">
+                </path>
+              </svg>{{ lang.ssAnalysis }}
+            </div>
+            <div class="ai_refresh" :class="{ 'disabled': currentAnalysis && currentAnalysis.loading }"
+              @click="aiAnalysisRefresh72()">
+              {{ lang.ssAIGenerate }}
+              <svg viewBox="0 0 1024 1024" width="200" height="200">
+                <path
+                  d="M875 483c-33.4 0-60.5 27.1-60.5 60.5v0.1C814.4 710.3 678.8 846 512 846S209.5 710.3 209.5 543.5 345.2 241 512 241c36.8 0 71.7 7.6 104.4 19.7-32 3-57.4 29.1-57.4 61.9 0 34.8 28.2 63 63 63h201.9c34.8 0 63-28.2 63-63V120c0-34.8-28.2-63-63-63s-63 28.2-63 63v81.4C691 150.5 605.2 120 512 120 278.1 120 88.5 309.6 88.5 543.5S278.1 967 512 967s423.5-189.6 423.5-423.5c0-33.4-27.1-60.5-60.5-60.5z">
+                </path>
+              </svg>
+
+            </div>
+          </div>
+          <div class="ai_content" v-if="currentAnalysis">
+            {{ currentAnalysis.json }}
+          </div>
+          <div class="ai_updateTime" v-if="currentAnalysis">{{ lang.ssUpdateTime }}:{{ currentAnalysis.update_at }}
+          </div>
+        </div>
+
         <div class="c_t72_workDetail" v-if="lookWorkData">
           <div class="c_t72_wd_top">
             <img src="../../../assets/img/arrow_left.png" @click="lookWork('')" />
@@ -242,6 +301,7 @@ const props = defineProps<{
   workArray: any[];
   courseDetail: any;
   userId: string;
+  workId: string;
 }>()
 
 const emit = defineEmits<{
@@ -501,7 +561,7 @@ const setEchartsArea1 = () => {
           fontSize: 17,
           lineHeight: 20,
           interval: 0,
-          formatter: function(value: any, idx: number) {
+          formatter: function (value: any, idx: number) {
             // 如果是字符串且格式为JSON(图片),则解析处理
             if (typeof value === 'string') {
               try {
@@ -645,11 +705,12 @@ const setEchartsArea1 = () => {
 
 // 获取分析
 const getAnalysis = () => {
-  if (!props.showData || !props.showData.workDetail || !props.showData.workDetail.id) {
+  if (!props.workId) {
     return
   }
+  console.log('props.workId', props.workId)
   const params = {
-    pid: props.showData.workDetail.id,
+    pid: props.workId,
   }
   axios.get('https://pbl.cocorobo.cn/api/pbl/select_pptAnalysisByPid?pid=' + params.pid).then(res => {
     const data = res[0]
@@ -700,6 +761,8 @@ watch(
   { immediate: true, deep: true }
 )
 
+
+
 // 监听作业变化
 watch(
   () => props.showData?.choiceQuestionListData,
@@ -776,7 +839,7 @@ watch(
 
 // 查看未提交学生
 const viewUnsubmittedStudents = () => {
-  selectUserDialogRef.value.open(lang.ssUnsubmittedStudents, {user: props.showData.unsubmittedStudents.map((item: any) => item.name)})
+  selectUserDialogRef.value.open(lang.ssUnsubmittedStudents, { user: props.showData.unsubmittedStudents.map((item: any) => item.name) })
   // if (props.unsubmittedStudents.length > 0) {
   // unsubmittedStudentsDialogRef.value.open(props.unsubmittedStudents)
   // }
@@ -817,7 +880,7 @@ const aiAnalysisRefresh45 = () => {
 
   if (!currentAnalysis.value) {
     aiAnalysisData.value.push({
-      pid: props.showData.workDetail.id,
+      pid: props.workId,
       index: props.showData.workIndex,
       loading: true,
       json: '',
@@ -827,33 +890,33 @@ const aiAnalysisRefresh45 = () => {
     })
   }
   else {
-    aiAnalysisData.value.find((item:any) => {
-      return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+    aiAnalysisData.value.find((item: any) => {
+      return item.pid === props.workId && item.index === props.showData.workIndex
     }).loading = true
-    aiAnalysisData.value.find((item:any) => {
-      return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+    aiAnalysisData.value.find((item: any) => {
+      return item.pid === props.workId && item.index === props.showData.workIndex
     }).json = ''
   }
 
   chat_stream(msg, 'a7741704-ba56-40b7-a6b8-62a423ef9376', props.userId, lang.lang, (event) => {
-    if (event.type === 'message') { 
-      aiAnalysisData.value.find((item:any) => {
-        return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+    if (event.type === 'message') {
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
       }).json = event.data
 
-      aiAnalysisData.value.find((item:any) => {
-        return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
       }).loading = false
     }
     else if (event.type === 'messageEnd') {
-      aiAnalysisData.value.find((item:any) => {
-        return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
       }).json = event.data
-      aiAnalysisData.value.find((item:any) => {
-        return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
       }).noEnd = false
-      aiAnalysisData.value.find((item:any) => {
-        return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
       }).update_at = new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).replace(/\//g, '-')
       saveAnalysis()
     }
@@ -876,7 +939,7 @@ const aiAnalysisRefresh15 = () => {
 - 课程学科:${props.courseDetail.name}
 当前页面答题数据(问答题):【分析重点】
 - 问答题题目:${props.showData.workDetail.json.answerQ}
-- 回答数据:${JSON.stringify(processedWorkArray.value.map((i) => ({user: i.name, answer: i.content.answer})))}
+- 回答数据:${JSON.stringify(processedWorkArray.value.map((i) => ({ user: i.name, answer: i.content.answer })))}
 - 未提交学生:${JSON.stringify(props.showData.unsubmittedStudents.map((item: any) => item.name))}
 
 # ANALYSIS RULES #
@@ -891,10 +954,104 @@ const aiAnalysisRefresh15 = () => {
 
 # EXAMPLES #
 样例:
-选择题正确率62%,核心概念“机器学习三步骤”(输入数据→训练模型→预测结果)掌握尚可,但“训练与预测区分”混淆率达38%;建议强化训练vs预测对比教学。`
+30人中15人提交问答题(参与率50%),核心概念“同理心地图”掌握薄弱。发现学生13在智能体对话中6次答“不知道”,需单独辅导设计思维基础概念。建议课程增加POV框架实例演练,强化痛点识别能力训练。`
+  if (!currentAnalysis.value) {
+    aiAnalysisData.value.push({
+      pid: props.workId,
+      index: props.showData.workIndex,
+      loading: true,
+      json: '',
+      noEnd: true,
+      update_at: '',
+      create_at: '',
+    })
+  }
+  else {
+    aiAnalysisData.value.find((item: any) => {
+      return item.pid === props.workId && item.index === props.showData.workIndex
+    }).loading = true
+    aiAnalysisData.value.find((item: any) => {
+      return item.pid === props.workId && item.index === props.showData.workIndex
+    }).json = ''
+  }
+
+  chat_stream(msg, 'a7741704-ba56-40b7-a6b8-62a423ef9376', props.userId, lang.lang, (event) => {
+    if (event.type === 'message') {
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
+      }).json = event.data
+
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
+      }).loading = false
+    }
+    else if (event.type === 'messageEnd') {
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
+      }).json = event.data
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
+      }).noEnd = false
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
+      }).update_at = new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).replace(/\//g, '-')
+      saveAnalysis()
+    }
+  }).catch(err => {
+    console.log('err', err)
+  })
+}
+
+// ai应用
+const aiAnalysisRefresh72 = async () => {
+
+  let chatMsg = ``
+
+  processedWorkArray.value.forEach((i) => {
+    i.content.forEach(j => {
+      j.messages.forEach((a) => {
+        chatMsg += `\n${a.sender}:
+${a.content}\n`
+      })
+    })
+
+  })
+
+
+
+// - 未提交学生:${JSON.stringify(props.showData.unsubmittedStudents.map((item: any) => item.name))}
+  const msg = `# CONTEXT #
+你是K-12阶段的AI教育课堂分析助手,基于上传的课件、逐字稿,以及当页的学生答题数据(选择题/问答题/智能体对话)进行智能分析。
+
+# OBJECTIVE #
+输出当前学生答题的分析报告:整体表现、核心发现(共性问题/误区)、教学优化(改进方向),为教师提供教学策略的建议和支持。
+
+#INPUT#
+课程数据:
+- 课程名称:${props.courseDetail.title}
+- 课程学科:${props.courseDetail.name}
+当前页面答题数据(问答题):【分析重点】
+- AI应用
+- 对话数据:${chatMsg}
+
+
+# ANALYSIS RULES #
+1. **问题定位**:明确指出哪个知识点/概念/步骤掌握不佳
+2. **建议具体**:给出可执行的教学动作(如“增加XX实例演练”“补充XX对比图”)
+
+# RESPONSE #
+采用段落叙述,数据量化呈现,突出可操作建议,严格控制输出为80词内。采用三段式论述:
+1. 整体表现-1句话
+2. 核心发现-1-2句,指出共性问题+典型案例
+3. 改进建议-1句话,提出具体教学动作
+
+# EXAMPLES #
+样例:
+智能体对话显示学生对“模型训练”概念模糊,多次询问“为什么不能直接告诉机器答案”。针对概念混淆学生,补充“人类学习类比”相关解释,巩固“从数据中学习规律”核心认知。`
+console.log("cs",msg)
   if (!currentAnalysis.value) {
     aiAnalysisData.value.push({
-      pid: props.showData.workDetail.id,
+      pid: props.workId,
       index: props.showData.workIndex,
       loading: true,
       json: '',
@@ -904,33 +1061,33 @@ const aiAnalysisRefresh15 = () => {
     })
   }
   else {
-    aiAnalysisData.value.find((item:any) => {
-      return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+    aiAnalysisData.value.find((item: any) => {
+      return item.pid === props.workId && item.index === props.showData.workIndex
     }).loading = true
-    aiAnalysisData.value.find((item:any) => {
-      return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+    aiAnalysisData.value.find((item: any) => {
+      return item.pid === props.workId && item.index === props.showData.workIndex
     }).json = ''
   }
 
   chat_stream(msg, 'a7741704-ba56-40b7-a6b8-62a423ef9376', props.userId, lang.lang, (event) => {
-    if (event.type === 'message') { 
-      aiAnalysisData.value.find((item:any) => {
-        return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+    if (event.type === 'message') {
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
       }).json = event.data
 
-      aiAnalysisData.value.find((item:any) => {
-        return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
       }).loading = false
     }
     else if (event.type === 'messageEnd') {
-      aiAnalysisData.value.find((item:any) => {
-        return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
       }).json = event.data
-      aiAnalysisData.value.find((item:any) => {
-        return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
       }).noEnd = false
-      aiAnalysisData.value.find((item:any) => {
-        return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+      aiAnalysisData.value.find((item: any) => {
+        return item.pid === props.workId && item.index === props.showData.workIndex
       }).update_at = new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).replace(/\//g, '-')
       saveAnalysis()
     }
@@ -942,8 +1099,8 @@ const aiAnalysisRefresh15 = () => {
 
 // 当前分析
 const currentAnalysis = computed(() => {
-  return aiAnalysisData.value.find((item:any) => {
-    return item.pid === props.showData.workDetail.id && item.index === props.showData.workIndex
+  return aiAnalysisData.value.find((item: any) => {
+    return item.pid === props.workId && item.index === props.showData.workIndex
   })
 })
 
@@ -953,7 +1110,7 @@ const saveAnalysis = () => {
     return
   }
   const params = [{
-    pid: props.showData.workDetail.id,
+    pid: props.workId,
     idx: props.showData.workIndex,
     json: currentAnalysis.value.json,
   }]
@@ -970,7 +1127,7 @@ const saveAnalysis = () => {
 
 // 监听 props.showData.workDetail.id 变化
 watch(
-  () => props.showData?.workDetail?.id,
+  () => props.showData?.workDetail,
   (newId, oldId) => {
     if (newId && newId !== oldId) {
       getAnalysis()
@@ -1077,13 +1234,14 @@ onUnmounted(() => {
           color: #CCCCCC;
         }
 
-        .c_t45_msg{
+        .c_t45_msg {
           display: flex;
           align-items: center;
           font-size: .9rem;
           font-weight: 400;
           gap: 1rem;
-          &>span{
+
+          &>span {
             text-decoration: underline;
             cursor: pointer;
           }
@@ -1127,6 +1285,7 @@ onUnmounted(() => {
         align-items: center;
         gap: 1.5rem;
         margin: 1rem auto;
+
         &>div {
           padding: .6rem;
           border-radius: .5rem;
@@ -1686,70 +1845,80 @@ onUnmounted(() => {
   }
 }
 
-      .aiAnalysis{
-        width: 100%;
-        height: auto;
-        display: flex;
-        flex-direction: column;
-        padding: 1rem;
-        border: solid 1px #F6C82B;
-        border-left-width: 4px;
-        border-radius: 1rem;
-        gap: 1rem;
-        &>.ai_header{
-          display: flex;
-          align-items: center;
-          justify-content: space-between;
-          gap: 1rem;
-          &>div{
-            display: flex;
-            align-items: center;
-            gap: .5rem;
-            &>svg{
-              width: 1rem;
-              height: 1rem;
-              
-            }
-          }
-          &>.ai_title{
-            color: #F7CD49;
-            font-weight: 500;
-            &>svg{
-              fill: #F7CD49;
-              width: 1.2rem;
-              height: 1.2rem;
-            }
-          }
-          &>.ai_refresh{
-            padding: .5rem 1rem;
-            border-radius: .5rem;
-            background: #F6C82B;
-            display: flex;
-            justify-content: center;
-            align-items: center;
-            cursor: pointer;
-            color: #000;
-            font-weight: bold;
-            font-size: .8rem;
-            gap: .5rem;
-            &>svg{
-              fill: #000;
-              width: .8rem;
-              height: .8rem;
-            }
-            &.disabled{
-              cursor: not-allowed !important;
-              background: #FEF8E9 !important;
-            }
-          }
-        }
-        &>.ai_content{
-          font-size: 1rem;
-          font-weight: 500;
-        }
-        &>.ai_updateTime{
-          font-size: .8rem;
-           font-weight: 500;
-        }
+.aiAnalysis {
+  width: 100%;
+  height: auto;
+  display: flex;
+  flex-direction: column;
+  padding: 1rem;
+  border: solid 1px #F6C82B;
+  border-left-width: 4px;
+  border-radius: 1rem;
+  gap: 1rem;
+
+  &>.ai_header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 1rem;
+
+    &>div {
+      display: flex;
+      align-items: center;
+      gap: .5rem;
+
+      &>svg {
+        width: 1rem;
+        height: 1rem;
+
       }
+    }
+
+    &>.ai_title {
+      color: #F7CD49;
+      font-weight: 500;
+
+      &>svg {
+        fill: #F7CD49;
+        width: 1.2rem;
+        height: 1.2rem;
+      }
+    }
+
+    &>.ai_refresh {
+      padding: .5rem 1rem;
+      border-radius: .5rem;
+      background: #F6C82B;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      cursor: pointer;
+      color: #000;
+      font-weight: bold;
+      font-size: .8rem;
+      gap: .5rem;
+
+      &>svg {
+        fill: #000;
+        width: .8rem;
+        height: .8rem;
+      }
+
+      &.disabled {
+        cursor: not-allowed !important;
+        background: #FEF8E9 !important;
+      }
+    }
+  }
+
+  &>.ai_content {
+    font-size: 1rem;
+    font-weight: 500;
+  }
+
+  &>.ai_updateTime {
+    font-size: .8rem;
+    font-weight: 500;
+  }
+}
 </style>

+ 1 - 1
src/views/Student/index.vue

@@ -99,7 +99,7 @@
           <ScreenSlideList :style="{ width: isFullscreen ? '100%' : slideWidth2 * canvasScale + 'px', height: isFullscreen ? '100%' : slideHeight2 * canvasScale + 'px', margin: '0 auto' }" :slideWidth="isFullscreen ? slideWidth * canvasScale : slideWidth2 * canvasScale" :slideHeight="isFullscreen ? slideHeight * canvasScale : slideHeight2 * canvasScale"
             :animationIndex="0" :turnSlideToId="() => { }" :manualExitFullscreen="() => { }"  :slideIndex="slideIndex" v-show="!choiceQuestionDetailDialogOpenList.includes(slideIndex)"/>
 
-          <choiceQuestionDetailDialog v-if="choiceQuestionDetailDialogOpenList.includes(slideIndex)"  :userId="props.userid" :courseDetail="courseDetail" :workArray="workArray" @changeWorkIndex="changeWorkIndex" v-model:visible="choiceQuestionDetailDialogOpenList" :showData="answerTheResultRef" :slideIndex="slideIndex" :workIndex="0" :style="{ width: isFullscreen ? '100%' : slideWidth2 * canvasScale + 'px', height: isFullscreen ? '100%' : slideHeight2 * canvasScale + 'px', margin: '0 auto' }" :slideWidth="isFullscreen ? slideWidth * canvasScale : slideWidth2 * canvasScale" :slideHeight="isFullscreen ? slideHeight * canvasScale : slideHeight2 * canvasScale"/>
+          <choiceQuestionDetailDialog v-if="choiceQuestionDetailDialogOpenList.includes(slideIndex)" :workId="workId"  :userId="props.userid" :courseDetail="courseDetail" :workArray="workArray" @changeWorkIndex="changeWorkIndex" v-model:visible="choiceQuestionDetailDialogOpenList" :showData="answerTheResultRef" :slideIndex="slideIndex" :workIndex="0" :style="{ width: isFullscreen ? '100%' : slideWidth2 * canvasScale + 'px', height: isFullscreen ? '100%' : slideHeight2 * canvasScale + 'px', margin: '0 auto' }" :slideWidth="isFullscreen ? slideWidth * canvasScale : slideWidth2 * canvasScale" :slideHeight="isFullscreen ? slideHeight * canvasScale : slideHeight2 * canvasScale"/>
 
 
           <div class="slide-bottom" v-if="!isFullscreen">

+ 1 - 1
src/views/lang/cn.json

@@ -732,7 +732,7 @@
   "ssAiChatExample": "例如:创建45分钟的四年级教学内容为水的三态变化的课程",
   "ssAiChatShortcut": "输入 / 获取快捷操作短语",
   "ssAiChatQuickAction1": "为当前页面内容生成2道选择题",
-  "ssAiChatQuickAction2": "为当前页面生成2页内容页面",
+  "ssAiChatQuickAction2": "为当前页面内容生成1道问答题",
   "ssAiChatParsing": "解析中...",
   "ssAiChatWaitUpload": "请等待文件上传完成后再发送消息",
   "ssAiChatFileSizeLimit": "文件大小不能超过10MB",

+ 1 - 1
src/views/lang/en.json

@@ -732,7 +732,7 @@
   "ssAiChatExample": "Example: Create a 45-minute lesson plan on water's three states of matter for 4th graders",
   "ssAiChatShortcut": "Type / for quick actions",
   "ssAiChatQuickAction1": "Generate 2 multiple choice questions for the current page content",
-  "ssAiChatQuickAction2": "Generate 2 content pages based on the current page",
+  "ssAiChatQuickAction2": "Generate 1 essay question for the current page content",
   "ssAiChatParsing": "Parsing...",
   "ssAiChatWaitUpload": "Please wait for the file upload to complete before sending a message",
   "ssAiChatFileSizeLimit": "File size cannot exceed 10MB",

+ 1 - 1
src/views/lang/hk.json

@@ -732,7 +732,7 @@
   "ssAiChatExample": "例如:創建45分鐘的四年級教學內容為水的三態變化的課程",
   "ssAiChatShortcut": "輸入 / 獲取快捷操作短語",
   "ssAiChatQuickAction1": "為當前頁面內容生成2道選擇題",
-  "ssAiChatQuickAction2": "為當前頁面生成2頁內容頁面",
+  "ssAiChatQuickAction2": "為當前頁面內容生成1道問答題",
   "ssAiChatParsing": "解析中...",
   "ssAiChatWaitUpload": "請等待文件上傳完成後再發送消息",
   "ssAiChatFileSizeLimit": "文件大小不能超過10MB",