SanHQin 10 miesięcy temu
rodzic
commit
85d73c0cbd

+ 1 - 1
src/assets/icon/classroomObservation/echartIcon.svg

@@ -1 +1 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1726640886428" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4312" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M63.5 145v735.3h895.7V145H63.5z m863.7 127.9v127.9H703.3V272.9h223.9zM383.4 496.7h287.9v127.9H383.4V496.7z m-32 127.9H95.5V496.7h255.9v127.9z m351.9-127.9h223.9v127.9H703.3V496.7z m-32-223.8v127.9H383.4V272.9h287.9z m-319.9 0v127.9H95.5V272.9h255.9zM95.5 848.4V720.5h255.9v127.9H95.5z m287.9 0V720.5h287.9v127.9H383.4z m319.9 0V720.5h223.9v127.9H703.3z" p-id="4313"></path></svg>
+<svg t="1726812889551" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1754" width="200" height="200"><path d="M896 896H96a32 32 0 0 1-32-32V224a32 32 0 0 1 64 0v608h768a32 32 0 1 1 0 64z" p-id="1755"></path><path d="M247.008 640a32 32 0 0 1-20.992-56.192l200.992-174.24a32 32 0 0 1 42.272 0.288l172.128 153.44 229.088-246.304a32 32 0 0 1 46.88 43.616l-250.432 269.216a31.936 31.936 0 0 1-44.704 2.08l-174.56-155.52-179.744 155.84a31.872 31.872 0 0 1-20.928 7.776z" p-id="1756"></path></svg>

+ 1 - 1
src/components/pages/classroomObservation/components/addNewAnalysisDialog.vue

@@ -571,7 +571,7 @@ export default {
 				{value:'0',label:"无"},
 				{value:'1',label:"词云图"},
 				{value:'2',label:"雷达图"},
-				{value:'3',label:"柱图"},
+				{value:'3',label:"能量柱图"},
 			],
       form: {
         name: "",

Plik diff jest za duży
+ 505 - 465
src/components/pages/classroomObservation/components/analysisItem.vue


+ 147 - 96
src/components/pages/classroomObservation/components/analysisSpecialItem.vue

@@ -126,7 +126,7 @@
           </el-tooltip>
         </span>
 
-        <!-- <span
+        <span
           v-if="loadNum != 1 && openItem && tid"
           @click.stop="editBtn(true)"
         >
@@ -142,22 +142,22 @@
               "
             />
           </el-tooltip>
-        </span> -->
-
-				<span v-if="loadNum != 1 && openItem && tid" @click="editEcharts(true)">
-					<el-tooltip
-						class="item"
-						effect="light"
-						content="生成图表"
-						placement="top"
-					>
-						<img
-							:src="
-								require('../../../../assets/icon/classroomObservation/echartIcon.svg')
-							"
-						/>
-					</el-tooltip>
-				</span>
+        </span>
+
+        <span v-if="loadNum != 1 && openItem && tid" @click="editEcharts(true)">
+          <el-tooltip
+            class="item"
+            effect="light"
+            content="生成图表"
+            placement="top"
+          >
+            <img
+              :src="
+                require('../../../../assets/icon/classroomObservation/echartIcon.svg')
+              "
+            />
+          </el-tooltip>
+        </span>
 
         <!-- <span class="ai-h-r-icon4" @click.stop="delBtn()"></span> -->
       </div>
@@ -209,6 +209,7 @@ let converter2 = OpenCC.Converter({
 });
 import mdView from "./mdView.vue";
 import eChartTemplate from "./eChartTemplate";
+import { v4 as uuidv4 } from "uuid";
 // import editNameDialog from './editNameDialog.vue'
 export default {
   emits: ["delItem", "editItem", "saveItem"],
@@ -318,10 +319,10 @@ export default {
       this.loadNum = 0;
       this.openItem = newValue;
     },
-    editBtn() {
-      // if (!flag) return console.log("不执行获取");
-      // this.loadNum = 1;
-      // this.getData();
+    editBtn(flag = false) {
+      if (!flag) return console.log("不执行获取");
+      this.loadNum = 1;
+      this.getData(1);
 
       // this.ajax
       // 	.post("https://gpt4.cocorobo.cn/ai_agent_park_chat", parm)
@@ -360,12 +361,12 @@ export default {
       // 	});
     },
 
-		editEcharts(flag = false){
-			if (!flag) return console.log("不执行获取");
+    editEcharts(flag = false) {
+      if (!flag) return console.log("不执行获取");
       this.loadNum = 1;
-      this.getData();
-		},
-    getAtAuContent(_uid, _text, _headUrl, _assistantName) {
+      this.getData(0);
+    },
+    getAtAuContent(_uid) {
       let _source = new EventSource(
         `https://gpt4.cocorobo.cn/question/${_uid}`
       ); //http://gpt4.cocorobo.cn:8011/question/   https://gpt4.cocorobo.cn/question/
@@ -420,7 +421,7 @@ export default {
         }
       };
     },
-    getData() {
+    getData(type = 0) {
       if (!this.bmData.editorBarData || this.bmData.editorBarData.type != 0) {
         this.loadNum = 2;
         return this.$message.info("请上传表格形式的转录文稿");
@@ -446,11 +447,11 @@ export default {
         });
         if (_result.length == 0) return this.$message.error("未找到表格数据");
         if (this.data.jsonData.name == "S-T分析:课堂时间分配") {
-          this.getTimeAllocationData(_result);
+          this.getTimeAllocationData(_result, type);
         } else if (this.data.jsonData.name == "S-T分析:师生互动分析") {
-          this.getInteractionAnalysisData(_result);
+          this.getInteractionAnalysisData(_result, type);
         } else if (this.data.jsonData.name == "S-T分析:教学模式分析") {
-          this.getTeachingModeData(_result);
+          this.getTeachingModeData(_result, type);
         } else {
           return this.$message.error("未找到对应的分析");
         }
@@ -462,7 +463,7 @@ export default {
       }
     },
     // 课堂时间分配
-    getTimeAllocationData(_dataList) {
+    getTimeAllocationData(_dataList, type = 0) {
       this.loading = true;
       this.openItem = false;
       let _data = _dataList.reduce(
@@ -479,83 +480,70 @@ export default {
           { value: 0, name: "学生" }
         ]
       );
+
+			let _dataPercentage = _data
+			_data.forEach((i, index) => {
+				_dataPercentage[index].percentage = (i.value / _data.reduce((pre, cur) => pre + cur.value, 0) * 100).toFixed(2)+'%'
+			})
+
+			_dataPercentage.forEach(i=>delete i.value)
+      if (type == 1) {
+        let _msg = `这是某一节课的师生时间占比,请你分析,写出结论,并给出指导建议。请使用3句完整的话,分析并给出建议。 请注意,当老师或学生的时间占比在【40~59%】之间的时候,也认为师生占比约为1:1,各占50%,师生时间占比比较均衡。
+师生时间占比数据:
+老师占比:${_dataPercentage[0].percentage}
+学生占比:${_dataPercentage[1].percentage}
+`;
+        return this.getAiContent(_msg)
+      }
+
       const _option = {
-				// title: {
+        // title: {
         //   text: "课堂时间分配",
         //   left: "center"
         // },
-      	tooltip: {
-					// text: "课堂时间分配",
-					 left: "center",
-      		trigger: "item",
-      		formatter: "{a} <br/>{b}: {d}%"  // {a}为系列名,{b}为数据名,{d}为百分比
-      	},
-      	legend: {
-      		top: "5%",
-					// orient: "vertical",
-      		left: "center",
-      	},
-      	series: [
-      		{
-      			name: "课堂时间分配",
-      			type: "pie",
-      			radius: ["40%", "70%"],
-      			// avoidLabelOverlap: false,
-      			label: {
-							formatter: "{b}: {d}%"
-      				// show: false,
-      				// position: "center",
-      			},
-      			emphasis: {
-      				label: {
-      					show: true,
-      					// fontSize: 40,
-      					// fontWeight: "bold",
-      					formatter: "{b}: {d}%"  // 显示百分比
-      				},
-							itemStyle: {
-                shadowBlur: 10,
-                shadowOffsetX: 0,
-                shadowColor: "rgba(0, 0, 0, 0.5)"
-              }
-      			},
-      			// labelLine: {
-      			// 	show: false,
-      			// },
-      			data: _data
-      		},
-      	],
-      };
-
-      const _option2 = {
-        title: {
-          text: "课堂时间分配",
-          subtext: "Fake Data",
-          left: "center"
-        },
         tooltip: {
-          trigger: "item"
+          // text: "课堂时间分配",
+          left: "center",
+          trigger: "item",
+          formatter: "{a} <br/>{b}: {d}%" // {a}为系列名,{b}为数据名,{d}为百分比
         },
         legend: {
-          orient: "vertical",
-          left: "left"
+          top: "5%",
+          // orient: "vertical",
+          left: "center"
         },
         series: [
           {
             name: "课堂时间分配",
             type: "pie",
-            radius: "50%",
-            data: _data,
+            radius: ["40%", "70%"],
+            // avoidLabelOverlap: false,
+            label: {
+              formatter: "{b}: {d}%"
+              // show: false,
+              // position: "center",
+            },
             emphasis: {
+              label: {
+                show: true,
+                // fontSize: 40,
+                // fontWeight: "bold",
+                formatter: "{b}: {d}%" // 显示百分比
+              },
               itemStyle: {
                 shadowBlur: 10,
                 shadowOffsetX: 0,
                 shadowColor: "rgba(0, 0, 0, 0.5)"
               }
-            }
+            },
+            // labelLine: {
+            // 	show: false,
+            // },
+            data: _data
           }
         ]
       };
+
       let _copyData = JSON.parse(JSON.stringify(this.data));
       _copyData.jsonData.eChartData = _option;
       _copyData.json_data = JSON.stringify(_copyData.jsonData);
@@ -568,7 +556,7 @@ export default {
       this.loading = false;
     },
     // 师生互动分析
-    getInteractionAnalysisData(_dataList) {
+    getInteractionAnalysisData(_dataList, type = 0) {
       this.loading = true;
       this.openItem = false;
       let _pushData = [0, 0];
@@ -584,6 +572,19 @@ export default {
       let _flatArray = _result.flat();
       const _max = Math.max(..._flatArray);
       const _maxValue = Math.ceil(_max / 100) * 100;
+
+      if (type == 1) {
+        let _msg = `
+## 任务 
+请你结合 FIAS 相关的知识,根据以下提供给你的课堂原始数据(包含S和t的数据),请你具体描述整个课堂S行为与T行为的持续性与变化性。比如,课堂一开始老师占比主导,大约5分钟之后,进入到学生为主的小组讨论环节。在整个课堂之中,老师与学生的互动比较频繁,老师会频繁询问学生问题,引导学生思考。之后是授课时间与问答时间。等等。
+## 输出要求 请使用自然语言进行描述,使用不超过5句完整的话进行整体性、概括性的描述,不要包含具体的时长信息。总结性概括之后,使用1句话对整个课堂的教师引导行为进行鼓励和评价,再使用1句话给出相应的优化建议。
+## 你的知识库 定义与目的:S-T图,即学生-教师(Student-Teacher)图,主要用于记录和分析课堂上的学生行为(S)与教师行为(T)的时间分布。这种图形能够帮助教育专家和教师可视化课堂互动的流程,从而判断课堂的教学型态,如练习型、对话型、讲授型或混合型。 绘制方法:S-T图的绘制开始于教学的起始时刻,纵轴表示学生行为(S),横轴表示教师行为(T)。实际课堂观察或录像回放中,按照固定时间间隔(通常每30秒)采样,将对应的行为按时间顺序标记在相应的轴上。通过这种方法,可以清晰看到课堂上教师行为与学生行为的交替模式及其随时间的变化。 应用场景:例如,一个典型的应用是在分析不同类型课堂活动时使用S-T图。在讲授型课堂中,教师行为的时间占比会较高,S-T图显示较长的横轴(T行为)延续;而在练习型或对话型课堂中,学生行为的时间占比增高,显示为较长的纵轴(S行为)。
+## 课堂实录
+${JSON.stringify(_dataList)}
+`;
+        return this.getAiContent(_msg);
+      }
+
       const _option = {
         xAxis: {
           name: "老师", // X轴标题
@@ -638,7 +639,7 @@ export default {
       this.loading = false;
     },
     // 教学模式分析
-    getTeachingModeData(_dataList) {
+    getTeachingModeData(_dataList, type = 0) {
       this.openItem = false;
       this.loading = true;
       let _continuousTime = 0;
@@ -698,6 +699,19 @@ export default {
 
       let _RT = (_teacherTime / _totalTime).toFixed(2);
       let _CH = (_continuousTime / _totalTime).toFixed(2);
+
+      if (type == 1) {
+        let _msg = `## 任务
+根据FIAS(弗兰德斯互动分析系统)理论,计算获得某一节课的RT和CH值。请你结合FIAS相关知识进行分析,使用3句完整的话对整个课堂进行分析,需注意包含这些内容:分析该课堂所属的教学模型,描述课堂的整体表现与特征,肯定老师做出的努力,以及给出相应的建议。 
+## 你的知识 
+根据RT和CH的值,教学模式通常被分为以下几种类型: 练习型:RT ≤ 0.3,表示学生行为占主导,教师行为较少。 讲授型:RT ≥ 0.7,表示教师行为占主导,学生参与较少。 对话型:CH ≥ 0.4,表示师生之间有较多的互动和转换。 混合型:0.3 < RT < 0.7,CH < 0.4,表示教学中既有教师讲授也有学生参与,但两者都不占绝对优势。
+## 数据
+RT:${_RT}
+CH:${_CH}
+`;
+        return this.getAiContent(_msg);
+      }
+
       let _copyData = JSON.parse(JSON.stringify(this.data));
       _copyData.jsonData.RT = _RT;
       _copyData.jsonData.CH = _CH;
@@ -710,6 +724,43 @@ export default {
       this.changeShowIndex(1);
       this.loading = false;
     },
+    getAiContent(_msg) {
+      let parm = {
+        assistant_id: "f8e1ebb2-2e0d-11ef-8bf4-12e77c4cb76b",
+        message: _msg,
+        session_name: uuidv4(),
+        userId: this.userId,
+        file_ids: "",
+        model: "gpt-4o-2024-08-06"
+      };
+
+      this.ajax
+        .post("https://gpt4.cocorobo.cn/ai_agent_park_chat", parm)
+        .then(res => {
+          let _data = res.data.FunctionResponse;
+          let _copyData = JSON.parse(JSON.stringify(this.data));
+          _copyData.jsonData.content = _data.message;
+          // _copyData.jsonData.dataFileList = [];
+          // _copyData.jsonData.fileList = [];
+          _copyData.json_data = JSON.stringify(_copyData.jsonData);
+          if (this.historyResult.length == 0) {
+            this.historyResult.push(_copyData.jsonData);
+          } else {
+            this.historyResult.splice(
+              this.showIndex + 1,
+              0,
+              _copyData.jsonData
+            );
+          }
+          this.changeShowIndex(1);
+          this.loading = false;
+        })
+        .catch(err => {
+          this.loadNum = 2;
+          // this.$message.error("AI无法识别优化");
+          this.loading = false;
+        });
+    },
     delBtn() {
       this.$confirm("确定删除?", "提示", {
         confirmButtonText: "确定",
@@ -1005,19 +1056,19 @@ th {
 }
 
 .a_h_l_t_input {
-	width: 25%;
-	min-width: 220px;
+  width: 25%;
+  min-width: 220px;
   height: 100%;
   display: flex;
   align-items: center;
 }
 
-.a_h_l_t_input>>>.el-form{
-	width: 100%;
-	min-width: 220px;
+.a_h_l_t_input >>> .el-form {
+  width: 100%;
+  min-width: 220px;
 }
 
-.a_h_l_t_input>>>.el-form-item{
-	margin-bottom: 0;
+.a_h_l_t_input >>> .el-form-item {
+  margin-bottom: 0;
 }
 </style>

+ 0 - 3
src/components/pages/classroomObservation/components/saveTemplateDialog.vue

@@ -119,9 +119,6 @@ export default {
 				brief:"",
 				permissions:false,
 			};
-		},
-		search(){
-			
 		},
 		submitBtn(ref) {
 			this.$refs[ref].validate((valid) => {

+ 31 - 44
src/components/pages/classroomObservation/components/sharePdf.vue

@@ -1,31 +1,29 @@
 <template>
   <el-dialog
-    :visible.sync="localDialogVisibleShare"
+    :visible.sync="show"
     :append-to-body="true"
     width="560px"
     :before-close="handleClose"
     class="dialog_diy"
   >
     <div class="share_box">
-     
-   
       <div class="url_box">
         <div class="title">
           分享链接
         </div>
         <div class="url">
-					<el-input
-          class="sc_fu_input"
-          style="color: black"
-          disabled
-          v-model="origin"
-        >
-          <template slot="append"
-            ><div class="sc_fu_copyBtn" @click.stop="copy()">
-              复制链接
-            </div></template
+          <el-input
+            class="sc_fu_input"
+            style="color: black"
+            disabled
+            v-model="origin"
           >
-        </el-input>
+            <template slot="append"
+              ><div class="sc_fu_copyBtn" @click.stop="copy()">
+                复制链接
+              </div></template
+            >
+          </el-input>
           <!-- <el-tooltip :content="origin" placement="top" effect="dark">
             <span>{{ origin }}</span>
           </el-tooltip>
@@ -61,14 +59,10 @@ import Clipboard from "clipboard";
 import QRCode from "qrcodejs2";
 export default {
   props: {
-    dialogVisibleShare: {
-      type: Boolean,
-      default: false
-    },
-		tid:{
-			type:String,
-			default:"",
-		}
+    tid: {
+      type: String,
+      default: ""
+    }
   },
   data() {
     return {
@@ -77,7 +71,7 @@ export default {
       copyText2: "",
       noCount: 0,
       pname: [],
-      localDialogVisibleShare: this.dialogVisibleShare
+      show: false
     };
   },
   methods: {
@@ -85,13 +79,17 @@ export default {
       this.close();
       done();
     },
+    open() {
+      this.show = true;
+      this.setQr();
+    },
     close() {
-    //   this.$emit("update:dialogVisibleShare", false);
-      this.$emit('shareBtn');
-
+      //   this.$emit("update:dialogVisibleShare", false);
+      // this.$emit('shareBtn');
+      this.show = false;
     },
     setQr() {
-      setTimeout(() => {
+      this.$nextTick(() => {
         let url = `https://beta.cloud.cocorobo.cn/aigpt/#/classroom_observation_board?tid=${this.tid}`;
         this.origin = url;
         this.$refs.qrCodeUrl.innerHTML = "";
@@ -103,7 +101,7 @@ export default {
           colorLight: "#ffffff",
           correctLevel: QRCode.CorrectLevel.H
         });
-      }, 500);
+      });
     },
     downQr() {
       // 创建一个虚拟链接,并将 canvas 转换为图片文件
@@ -115,7 +113,7 @@ export default {
       link.click();
     },
     copy() {
-			const input = document.createElement("input");
+      const input = document.createElement("input");
       // 设置 display为none会导致无法复制
       // input.style.display = "none";
       // 所以只能用其他方法隐藏
@@ -147,7 +145,7 @@ export default {
       // });
     },
     copy2() {
-      let url = 'https://beta.cloud.cocorobo.cn/#/classroomObservation';
+      let url = "https://beta.cloud.cocorobo.cn/#/classroomObservation";
       this.copyText2 = `链接提醒:${url}`;
       var clipboard = new Clipboard(".tag-read2");
       clipboard.on("success", e => {
@@ -191,25 +189,14 @@ export default {
     // }
   },
   watch: {
-    dialogVisibleShare(newValue, oldValue) {
-      console.log("newValue", newValue);
-      if (newValue) {
-        this.localDialogVisibleShare=newValue
+    tid() {
+      if (this.show) {
         this.setQr();
-        // this.getData();
-        // console.log(top.origin);
-        // this.origin = top.origin
       }
-    },
-		tid(){
-			if(this.dialogVisibleShare){
-				this.setQr();
-			}
-		}
+    }
   },
   mounted() {
     // console.log("this.info", this.info);
-
     // console.log(top.origin);
     // this.origin = top.origin
   }

+ 21 - 2
src/components/pages/classroomObservation/index.vue

@@ -584,8 +584,9 @@ export default {
             }
 
             if (i2.jsonData.CH && i2.jsonData.RT) {
-              tagHtml += `<div>
-								<img src=''>
+              tagHtml += `<div style="width:100vw;text-align:center;">
+								<img src="${await this.getImageSrcToBase64(require('../../../assets/icon/classroomObservation/rt-ch.png'))}" style="width:200px;height:200px;margin:auto;">
+								<div style="color:#1A7AD3;font-style:italic;font-weight:blob;">RT:${i2.jsonData.RT}CH:${i2.jsonData.CH}</div>
 								</div>`;
             }
 
@@ -679,6 +680,24 @@ export default {
         });
       });
     },
+		getImageSrcToBase64(src){
+			return new Promise((resolve,reject)=>{
+				const image = new Image();
+				image.src = src;
+				image.onload = () =>{
+					const canvas = document.createElement('canvas');
+					canvas.width = image.naturalWidth;
+					canvas.height = image.naturalHeight;
+					canvas.style.width = `${canvas.width / window.devicePixelRatio}px`
+					canvas.style.height = `${canvas.height / window.devicePixelRatio}px`
+
+					const context = canvas.getContext('2d');
+					context.drawImage(image, 0, 0);
+					const base64 = canvas.toDataURL('image/png');
+					resolve(base64);
+				}
+			})
+		},
     // 导出docx
     async generateDocx(name, html) {
       // 将html文件中需要用到的数据挂载到store上

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików