SanHQin 1 năm trước cách đây
mục cha
commit
e103d04f79
29 tập tin đã thay đổi với 21489 bổ sung610 xóa
  1. 1 1
      dist/index.html
  2. 0 0
      dist/static/css/app.20570fc7cd8f61d125228fb6aef9db13.css
  3. 0 0
      dist/static/css/app.20570fc7cd8f61d125228fb6aef9db13.css.map
  4. 0 0
      dist/static/js/app.1257986c05621dc37023.js
  5. 0 0
      dist/static/js/app.1257986c05621dc37023.js.map
  6. 0 0
      dist/static/js/manifest.571c38d63f24b1ae9e16.js.map
  7. 0 0
      dist/static/js/vendor.85f22e7b4ab99591785c.js
  8. 0 0
      dist/static/js/vendor.85f22e7b4ab99591785c.js.map
  9. 18827 0
      package-lock.json
  10. 1 0
      package.json
  11. 844 451
      src/components/pages/aiAddCourse/addCourse.vue
  12. 341 22
      src/components/pages/aiAddCourse/aiCreateDialog.vue
  13. 1 1
      src/components/pages/aiAddCourse/aiTips.vue
  14. 29 5
      src/components/pages/classroomObservation/components/analysis.vue
  15. 758 0
      src/components/pages/classroomObservation/components/analysisSpecialItem.vue
  16. 5 1
      src/components/pages/classroomObservation/components/analysisTemplateDialog.vue
  17. 40 40
      src/components/pages/classroomObservation/components/baseMessage.vue
  18. 2 2
      src/components/pages/classroomObservation/components/bindingFormDialog.vue
  19. 40 5
      src/components/pages/classroomObservation/components/chatArea.vue
  20. 46 0
      src/components/pages/classroomObservation/components/eChartTemplate.vue
  21. 41 18
      src/components/pages/classroomObservation/components/messageArea.vue
  22. 6 1
      src/components/pages/classroomObservation/index.vue
  23. 172 0
      src/components/pages/components/wOffice.vue
  24. 190 36
      src/components/pages/contrastObservation/index.vue
  25. 107 11
      src/components/pages/test/check/index.vue
  26. 20 2
      src/components/pages/test/shareBox/index.vue
  27. 7 5
      src/components/pages/testStudent/view/component/course.vue
  28. 4 2
      src/components/pages/testStudent/view/component/eva.vue
  29. 7 7
      src/components/pages/testStudent/view/preview.vue

+ 1 - 1
dist/index.html

@@ -32,7 +32,7 @@
       width: 100%;
       background: #e6eaf0;
       font-family: '黑体';
-    }</style><link href=./static/css/app.7e365798787e2ed41229edd7c082dd1c.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.571c38d63f24b1ae9e16.js></script><script type=text/javascript src=./static/js/vendor.3cd0a0187ca1f70ded67.js></script><script type=text/javascript src=./static/js/app.63c436f02f1a49d07572.js></script></body></html><script>function stopSafari() {
+    }</style><link href=./static/css/app.20570fc7cd8f61d125228fb6aef9db13.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.571c38d63f24b1ae9e16.js></script><script type=text/javascript src=./static/js/vendor.85f22e7b4ab99591785c.js></script><script type=text/javascript src=./static/js/app.1257986c05621dc37023.js></script></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/css/app.20570fc7cd8f61d125228fb6aef9db13.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/css/app.20570fc7cd8f61d125228fb6aef9db13.css.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/js/app.1257986c05621dc37023.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/js/app.1257986c05621dc37023.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/js/manifest.571c38d63f24b1ae9e16.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/js/vendor.85f22e7b4ab99591785c.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/js/vendor.85f22e7b4ab99591785c.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 18827 - 0
package-lock.json


+ 1 - 0
package.json

@@ -37,6 +37,7 @@
     "language-hk-loader": "^1.0.1",
     "markdown-it": "^14.1.0",
     "pdfjs-dist": "^2.5.207",
+    "pptxgenjs": "^3.12.0",
     "qrcodejs2": "^0.0.2",
     "qs": "^6.10.1",
     "relation-graph": "^1.1.0",

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 844 - 451
src/components/pages/aiAddCourse/addCourse.vue


+ 341 - 22
src/components/pages/aiAddCourse/aiCreateDialog.vue

@@ -1,51 +1,108 @@
 <template>
-    <el-dialog title="AI生成" :visible.sync="dialogVisibleAiCreate" :append-to-body="true" width="650px" :before-close="handleClose"
-        class="dialog_diy">
-        <div style="height: 100%;padding:15px">
-            <div class="t_box">
+    <el-dialog title="AI生成PPT" :visible.sync="dialogVisibleAiCreate" :append-to-body="true" width="700px"
+        :before-close="handleClose" class="dialog_diy">
+        <div style="height: 500px;padding:15px" v-loading="loading">
+            <!-- <div class="t_box">
                 <span>选择:</span>
-                <el-radio-group v-model="radio">
+                <el-radio-group v-model="radio" @change="changeRadio">
                     <el-radio :label="0">PPT</el-radio>
                     <el-radio :label="1">教案</el-radio>
                     <el-radio :label="2">视频</el-radio>
                 </el-radio-group>
-            </div>
-            <div class="t_box">
+            </div> -->
+            <!-- <div class="t_box">
                 <span>提示词:</span>
                 <textarea rows="10" class="binfo_input binfo_textarea" cols placeholder="请输入提示词"
                     v-model="detail"></textarea>
-            </div>
-            
+            </div> -->
+            <wOffice v-if="url" :url="url"></wOffice>
         </div>
         <span slot="footer" class="dialog-footer">
+            <el-button @click="aiGet" type="primary">重新生成</el-button>
             <el-button @click="confirm" type="primary">确 定</el-button>
             <el-button @click="close">关 闭</el-button>
         </span>
     </el-dialog>
 </template>
-  
+
 <script>
+import Pptxgen from "pptxgenjs"
+import wOffice from '../components/wOffice.vue'
+import { v4 as uuidv4 } from "uuid";
 
 export default {
+    components: {
+        wOffice,
+    },
     props: {
         dialogVisibleAiCreate: {
             type: Boolean,
             default: false
         },
+        courseName: {
+            type: String,
+            default: ""
+        },
+        infoData: {
+            type: Array,
+            default: ""
+        }
     },
+    // 根据用户给你的参考资料
     data() {
         return {
+            userid: this.$route.query.userid,
             radio: 0,
-            detail: ""
+            aiJson: {
+                ppt: `## 任务
+请生成关于${this.courseName},为教师生成这节课的教学ppt,页数在20页左右。PPT的内容主要是讲解该课程中所有可能涉及到的知识点。
+
+## 工作流
+1. 从用户提供的参考资料中提取10个最重要的知识点(知识点水平限制在小学和初中),并输出。
+2. 针对10个知识点中的每个,你使用1~3页ppt详细的对知识点进行讲解。你的讲解词应该在100token左右
+3. 讲解完所有知识点后,再根据知识点出5道单选题(放在5页ppt中)
+
+## 限制
+- 你不能输出错误的知识,如果你实在不清楚,输出“对不起,我不确定”
+- 你不能输出违反伦理的内容`,
+                word: '',
+                video: ''
+            },
+            aiUrl: {
+                ppt: '',
+                word: '',
+                video: ''
+            },
+            detail: "",
+            loading: false,
+            url: "",
+            uJson: {}
         }
     },
-    watch:{
+    watch: {
         dialogVisibleAiCreate(newValue, oldValue) {
-            if(newValue){
-                this.text = JSON.parse(JSON.stringify(this.aiText))
-                if(this.clickType == 2){
-                    this.confirm();
-                }
+            if (newValue) {
+                // if (this.radio == 0) {
+                    this.detail =  `## 任务
+请根据用户给你的参考资料,生成关于${this.courseName},为教师生成这节课的教学ppt,页数在20页左右。PPT的内容主要是讲解该课程中所有可能涉及到的知识点。
+
+## 工作流
+1. 从用户提供的参考资料中提取10个最重要的知识点(知识点水平限制在小学和初中),并输出。
+2. 针对10个知识点中的每个,你使用1~3页ppt详细的对知识点进行讲解。你的讲解词应该在100token左右
+3. 讲解完所有知识点后,再根据知识点出5道单选题(放在5页ppt中)
+
+## 限制
+- 你不能输出错误的知识,如果你实在不清楚,输出“对不起,我不确定”
+- 你不能输出违反伦理的内容`
+                // }
+                // if (this.radio == 1) {
+                //     this.detail = this.aiJson.word
+                // }
+                // if (this.radio == 2) {
+                //     this.detail = this.aiJson.video
+                // }
+                // this.loading = false
+                this.aiGet()
             }
         },
     },
@@ -57,14 +114,276 @@ export default {
         close() {
             this.$emit('update:dialogVisibleAiCreate', false)
         },
-        confirm(){
-            this.$emit("aiConfirm",this.text);
-            this.$emit('update:dialogVisibleAiCreate', false)
-        }
+        confirm() {
+            if(this.url){
+                this.$emit('createAiPpt', this.uJson)
+            }else {
+                this.$message.error('请先生成ppt');
+            }
+        },
+        changeRadio() {
+            if (this.radio == 0) {
+                this.detail = this.aiJson.ppt
+            }
+            if (this.radio == 1) {
+                this.detail = this.aiJson.word
+            }
+            if (this.radio == 2) {
+                this.detail = this.aiJson.video
+            }
+        },
+        createFileid(url) {
+            let _this = this
+            return new Promise((resolve, reject) => {
+                try {
+                _this.ajax
+                .put("https://gpt4.cocorobo.cn/upload_file_knowledge", {
+                    url: url,
+                })
+                .then((res) => {
+                    let _data = res.data.FunctionResponse;
+                    if (_data.result && _data.result.id) {
+                    resolve(_data.result.id)
+                    }
+                }).catch(function (error) {
+                    resolve('')
+                });
+                }catch (e){
+                resolve()
+                }
+                
+            });
+        },
+        async aiGet() {
+            if(this.loading){
+                this.$message.error('正在生成中,请稍后');
+                return;
+            }
+            this.url = ''
+            this.uJson = {}
+            let _this = this
+
+            let fileid = []
+            if (_this.infoData.length) {
+                for (var i = 0; i < _this.infoData.length; i++) {
+                if(_this.infoData[i].fileid){
+                    fileid.push(_this.infoData[i].fileid)
+                }else {
+                    let _fileid = await _this.createFileid(_this.infoData[i].url)
+                    if(_fileid){
+                    _this.infoData[i].fileid = _fileid
+                    _this.$forceUpdate();
+                    fileid.push(_fileid)
+                    }
+                }
+                }
+            }
+            console.log('fileid=========',fileid)  
+
+
+            let message = ''
+            if (_this.radio == 0) {
+                message = `NOTICE
+Role: 提供的参考资料中读取10个最重要的知识点(知识点水平限制在小学和初中,作为ppt内容。
+Output: Provide your output in json format.
+ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
+Instruction: Based on the context, follow "Format example", write content.
+
+# Context 
+## 任务
+请根据用户给你的参考资料,生成关于${this.courseName},为教师生成这节课的教学ppt,页数在20页左右。PPT的内容主要是讲解该课程中所有可能涉及到的知识点。
+
+## 工作流
+1. 提供的参考资料中读取10个最重要的知识点(知识点水平限制在小学和初中,作为ppt内容。
+2. 针对10个知识点中的每个,你使用1~3页ppt详细的对知识点进行讲解。你的讲解词应该在100token左右
+3. 讲解完所有知识点后,再根据知识点出5道单选题(放在5页ppt中)。
+
+# Format example
+[{"page": "页码(数字)","title": "标题","task": "对应教学任务:依据用户输入的参考资料而定,如果用户未提供则不输出","points": "知识点讲解:针对知识点的详细讲解,你的语气应该让小学或初中的学生清晰易懂的讲解。你的讲解词在100 token左右。请尽可能的详细,这对我很重要。"}]`
+            } else if (_this.radio == 1) {
+
+            } else if (_this.radio == 2) {
+
+            }
+
+
+            // let params = JSON.stringify({
+            //     // "model": "Chat",
+            //     model: 'gpt-3.5-turbo',
+            //     temperature: 0,
+            //     max_tokens: 4096,
+            //     top_p: 1,
+            //     frequency_penalty: 0,
+            //     presence_penalty: 0,
+            //     messages: [{
+            //         content: message,
+            //         role: 'user'
+            //     }],
+            //     stream: false,
+            //     uid: this.userid,
+            //     mind_map_question: "",
+            // })
+
+            // _this.loading = true
+            // _this.ajax.post('https://gpt4.cocorobo.cn/chat', params).then(function (response) {
+            //     console.log(response);
+            //     let data = response.data.FunctionResponse
+            //     if (data.choices && data.choices.length && data.choices[0].message) {
+            //         console.log(data.choices[0].message.content);
+            //         try {
+            //             let _data = JSON.parse(data.choices[0].message.content)
+            //             _this.createPpt(_data)
+            //         } catch (e) {
+            //             console.log('error_________________'+e);
+            //             _this.$message.error(data.choices[0].message.content)
+            //             _this.loading = false
+            //         }
+
+            //     }
+            // }).catch(function (error) {
+            //     _this.loading = false
+            //     console.log(error);
+            // });
+
+
+            let parm = {
+                assistant_id: '6063369f-289a-11ef-8bf4-12e77c4cb76b',
+                message: [{"type":"text", "text":message}],
+                session_name: uuidv4(),
+                userId: this.userid,
+                file_ids: fileid.length ? [...fileid] : '',
+            }
+            _this.loading = true
+            this.ajax
+                .post("https://gpt4.cocorobo.cn/ai_agent_park_chat", parm)
+                .then((response) => {
+                console.log(response);
+                let data = response.data.FunctionResponse
+                if (data.message) {
+                    console.log(data.message);
+                    try {
+                        let _data = JSON.parse(data.message.replaceAll('```json','').replaceAll('```',''))
+                        _this.createPpt(_data)
+                    } catch (e) {
+                        console.log('error_________________'+e);
+                        _this.$message.error(data.message)
+                        _this.loading = false
+                    }
+                }
+                })
+                .catch((error) => {
+                _this.loading = false
+                console.log(error);
+                });
+        },
+        createPpt(array) {
+            // 1. 创建PPT
+            const pres = new Pptxgen()
+            for (var i = 0; i < array.length; i++) {
+                // 2. 创建一个PPT页面,每调用一次 pres.addSlide() 都可以生成一张新的页面
+                // 建议把每个页面的构造抽成一个个函数,然后通过函数调用生成新页面,代码不会很乱
+                const _slide = pres.addSlide()
+
+                // 3. 调用addTetx(),在PPT页面中插入文字“Hello World from PptxGenJS...”
+                // 括号里面是对文字的配置,文字横坐标x为1.5,纵坐标y为1.5,字体颜色 363636……
+                // 关于坐标长度与px的转换 x 1 = 127~128px 左右
+                const tempResult1 = array[i].title
+                _slide.addText(tempResult1, {
+                    x: 0.5, // 横坐标
+                    y: 0.5,
+                    color: '363636',
+                    fontSize: 24, // 字号
+                    fill: { color: 'F1F1F1' },
+                    align: 'center'
+                })
+                const tempResult2 = array[i].task
+                _slide.addText(tempResult2, {
+                    x: 0.5, // 横坐标
+                    y: 2,
+                    color: '363636',
+                    fontSize: 18, // 字号
+                    fill: { color: 'F1F1F1' },
+                    align: 'center'
+                })
+                const tempResult3 = array[i].points
+                _slide.addText(tempResult3, {
+                    x: 0.5, // 横坐标
+                    y: 4,
+                    color: '363636',
+                    fontSize: 18, // 字号
+                    fill: { color: 'F1F1F1' },
+                    align: 'center'
+                })
+            }
+
+            // 获取PPTX文件的ArrayBuffer
+
+            // 保存为 Blob 并处理
+            pres.write('blob').then((blob) => {
+                // 现在你有了一个 Blob 对象
+                console.log(blob);
+
+                const file = new File([blob], 'aiPpt.pptx', { type: "application/vnd.openxmlformats-officedocument.presentationml.presentation" });
+                console.log(pres)
+                this.beforeUpload(file)
+            });
+
+        },
+        beforeUpload(event) {
+            var file = event;
+            var credentials = {
+                accessKeyId: "AKIATLPEDU37QV5CHLMH",
+                secretAccessKey: "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",
+            }; //秘钥形式的登录上传
+            window.AWS.config.update(credentials);
+            window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+            var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+            var _this = this;
+
+            if (file) {
+                var params = {
+                    Key:
+                        file.name.split(".")[0] +
+                        new Date().getTime() +
+                        "." +
+                        file.name.split(".")[file.name.split(".").length - 1],
+                    ContentType: file.type,
+                    Body: file,
+                    "Access-Control-Allow-Credentials": "*",
+                    ACL: "public-read",
+                }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+                var options = {
+                    partSize: 2048 * 1024 * 1024,
+                    queueSize: 2,
+                    leavePartsOnError: true,
+                };
+                bucket
+                    .upload(params, options)
+                    .on("httpUploadProgress", function (evt) {
+                        //这里可以写进度条
+                        // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+                    })
+                    .send(function (err, data) {
+                        _this.loading = false
+                        if (err) {
+                            _this.$message.error("上传失败");
+                        } else {
+                            _this.url = data.Location
+                            _this.uJson = {
+                              name: file.name,
+                              url: data.Location,
+                              type: 3,
+                            }
+                            console.log(data.Location);
+                        }
+                    });
+            }
+        },
     },
 }
 </script>
-  
+
 <style scoped>
 .dialog_diy>>>.el-dialog {
     height: auto;

+ 1 - 1
src/components/pages/aiAddCourse/aiTips.vue

@@ -163,7 +163,7 @@ export default {
 .binfo_textarea {
     border: 1.5px solid #cad1dc;
     font-size: 15px;
-    resize: none;
+    resize: vertical;
     /* background: #f6f6f6; */
     font-family: "Microsoft YaHei";
 }

+ 29 - 5
src/components/pages/classroomObservation/components/analysis.vue

@@ -13,10 +13,10 @@
 			</div>
 		</div>
 		<div class="a-main" v-show="showItem">
-			<analysisItem
+			<template v-for="(item, index) in analysisItemList">
+				<analysisItem
 				ref="analysisItemRef"
-				v-if="item.jsonData.name!='词频词汇分析'"
-				v-for="(item, index) in analysisItemList"
+				v-if="(item.jsonData.name!='词频词汇分析') && !['S-T分析:课堂时间分配','S-T分析:师生互动分析','S-T分析:教学模式分析'].includes(item.jsonData.name) "
 				:dialogTagDataList="dialogTagDataList"
 				:key="item.id"
 				:data="item"
@@ -28,6 +28,22 @@
 				@editItem="editItem"
 				@saveItem="saveItem"
 			/>
+			<analysisSpecialItem
+				v-if="['S-T分析:课堂时间分配','S-T分析:师生互动分析','S-T分析:教学模式分析'].includes(item.jsonData.name)"
+				:dialogTagDataList="dialogTagDataList"
+				ref="analysisItemRef"
+				:bmData="bmData"
+				:key="item.id"
+				:data="item"
+				:tid="tid"
+				:fileId="fileId"
+				:index="index"
+				:showBrief="showBrief"
+				@delItem="delItem"
+				@editItem="editItem"
+				@saveItem="saveItem"
+			/>
+			</template>
 			<div class="a_m_empty" v-if="analysisItemList.length == 0">
 				暂无模块...
 			</div>
@@ -37,9 +53,16 @@
 
 <script>
 import analysisItem from "./analysisItem";
+import analysisSpecialItem from './analysisSpecialItem'
 export default {
 	emits: ["delItem", "editItem","saveItem"],
 	props: {
+		bmData:{
+			type:Object,
+			default:()=>{
+				return {}
+			}
+		},
 		title: {
 			type: String,
 			default: "分析",
@@ -75,6 +98,7 @@ export default {
 	},
 	components: {
 		analysisItem,
+		analysisSpecialItem
 	},
 	data() {
 		return {
@@ -102,11 +126,11 @@ export default {
 		getReport(id) {
 			if (!id) {
 				this.$refs.analysisItemRef.forEach((i) => {
-					i.editBtn();
+					i.editBtn(false);
 				});
 			} else {
 				this.$nextTick(()=>{
-					this.$refs.analysisItemRef[this.analysisItemList.findIndex((i) => i.id == id)].editBtn();
+					this.$refs.analysisItemRef[this.analysisItemList.findIndex((i) => i.id == id)].editBtn(false);
 				})
 				
 			}

+ 758 - 0
src/components/pages/classroomObservation/components/analysisSpecialItem.vue

@@ -0,0 +1,758 @@
+<template>
+	<div class="analysisItem">
+		<div class="ai-header" v-show="data.jsonData.name != '词频词汇分析'">
+			<div class="ai-h-left" @click.stop="changeOpenItem(!openItem)">
+				<span
+					:class="['ai-h-l-icon', openItem ? 'ai-h-l-iconActive' : '']"
+				></span>
+				<span class="ai-h-l-text">{{ data.jsonData.name }}</span>
+			</div>
+			<div class="ai-h-right">
+				<span style="width: 100px" class="generateError" v-if="loadNum == 2"
+					>优化失败
+				</span>
+				<span style="width: 100px" v-if="loadNum == 1">
+					<span v-if="loading" class="generate">
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/generate.svg')
+							"
+						/>
+						生成中...
+					</span>
+					<span v-else class="generateSuccess">
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/success.svg')
+							"
+						/>
+						生成完成
+					</span>
+				</span>
+				<span
+					v-if="loadNum == 0 && !openItem && tid"
+					class="ai-h-r-icon4"
+					@click.stop="delBtn()"
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="删除"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/del.svg')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
+				<span
+					v-if="loadNum == 0 && openItem"
+					:class="['ai-h-r-icon1', showIndex <= 0 ? 'ai_h_r_iconOpacity' : '']"
+					@click.stop="changeShowIndex(-1)"
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="上一个"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/back.svg')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
+				<span
+					v-if="loadNum != 1 && openItem"
+					:class="[
+						showIndex >= historyResult.length - 1 ? 'ai_h_r_iconOpacity' : '',
+					]"
+					@click.stop="changeShowIndex(1)"
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="下一个"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/back.svg')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
+				<span
+					v-if="loadNum != 1 && openItem && tid"
+					@click.stop="editBtn(true)"
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="优化"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/edit.svg')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
+				<!-- <span class="ai-h-r-icon4" @click.stop="delBtn()"></span> -->
+			</div>
+		</div>
+		<div class="ai-main" v-if="openItem">
+			<div class="a-m-brief" v-if="showBrief">
+				{{ data.jsonData.result }}
+			</div>
+			<!-- 图 -->
+			<eChartTemplate
+				style="width: 100%; height: 400px"
+				:data="data.jsonData.eChartData"
+				v-if="data.jsonData.eChartData"
+			/>
+			<div class="rtCh" v-if="data.jsonData.RT && data.jsonData.CH">
+				<img :src="require('../../../../assets/icon/classroomObservation/rt-ch.png')">
+				<div>
+					<span>RT={{ data.jsonData.RT }}</span>
+					<span>CH={{ data.jsonData.CH }}</span>
+				</div>
+			</div>
+			<mdView :text="data.jsonData.content" />
+		</div>
+	</div>
+</template>
+
+<script>
+import mdView from "./mdView.vue";
+import eChartTemplate from "./eChartTemplate";
+import { v4 as uuidv4 } from "uuid";
+export default {
+	emits: ["delItem", "editItem", "saveItem"],
+	components: {
+		mdView,
+		eChartTemplate,
+	},
+	props: {
+		data: {
+			type: Object,
+			default: () => {
+				return {};
+			},
+		},
+		bmData: {
+			type: Object,
+			default: () => {
+				return {};
+			},
+		},
+		dialogTagDataList: {
+			type: Array,
+			default: () => {
+				return [];
+			},
+		},
+		index: {
+			type: Number,
+			default: 0,
+		},
+		tid: {
+			type: String,
+			require: true,
+		},
+		fileId: {
+			type: String,
+			require: true,
+		},
+		showBrief: {
+			type: Boolean,
+			default: true,
+		},
+	},
+	data() {
+		return {
+			openItem: false,
+			loading: false,
+			loadNum: 0,
+			userId: this.$route.query["userid"],
+			showIndex: 0,
+			historyResult: [],
+			tableData: [],
+			imgTypeList: [
+				"png",
+				"jpg",
+				"jpeg",
+				"bmp",
+				"gif",
+				"webp",
+				"psd",
+				"svg",
+				"tiff",
+			],
+			oldData: {},
+		};
+	},
+	computed: {
+		checkFileType() {
+			return (url) => {
+				return url.split(".").pop();
+			};
+		},
+	},
+	watch: {
+		// showIndex(){
+		// 	let _copyData = JSON.parse(JSON.stringify(this.data));
+		// 	_copyData.jsonData = this.historyResult[this.showIndex];
+		// 	_copyData.json_data = JSON.stringify(_copyData.jsonData);
+		// 	this.$emit("editItem", this.data.id, _copyData);
+		// }
+	},
+	methods: {
+		changeOpenItem(newValue) {
+			if (this.loading == true && this.loadNum != 0)
+				return this.$message("请稍后...");
+			this.loadNum = 0;
+			this.openItem = newValue;
+		},
+		editBtn(flag = false) {
+			if (!flag) return console.log("不执行获取");
+			this.loadNum = 1;
+			this.getData();
+
+			// this.ajax
+			// 	.post("https://gpt4.cocorobo.cn/ai_agent_park_chat", parm)
+			// 	.then((res) => {
+			// 		let _data = res.data.FunctionResponse;
+			// 		if (
+			// 			!_data.message ||
+			// 			_data.message.indexOf("由于我无法直接访问您上传的文件内容") > -1
+			// 		) {
+			// 			this.loading = false;
+			// 			this.loadNum = 2;
+			// 			return this.$message.error("AI无法识别优化");
+			// 		}
+			// 		let _copyData = JSON.parse(JSON.stringify(this.data));
+			// 		// _copyData.jsonData.result = "";
+			// 		_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;
+			// 	});
+		},
+		getAtAuContent(_uid, _text, _headUrl, _assistantName) {
+			let _source = new EventSource(
+				`https://gpt4.cocorobo.cn/question/${_uid}`
+			); //http://gpt4.cocorobo.cn:8011/question/   https://gpt4.cocorobo.cn/question/
+			let _allText = "";
+			let _mdText = "";
+			let _copyData = JSON.parse(JSON.stringify(this.data));
+			// _copyData.jsonData.result = "";
+			_copyData.jsonData.content = "";
+			_copyData.jsonData.dataFileList = [];
+			_copyData.jsonData.fileList = [];
+			if (this.historyResult.length == 0) {
+				this.historyResult.push(_copyData.jsonData);
+			} else {
+				this.historyResult.splice(this.showIndex + 1, 0, _copyData.jsonData);
+			}
+			this.showIndex++;
+			this.$emit("editItem", this.data.id, _copyData);
+			// const md = new MarkdownIt();
+			_source.onmessage = (_e) => {
+				let _eData = JSON.parse(_e.data);
+				if (_eData.content.replace("'", "").replace("'", "") == "[DONE]") {
+					let _result = [];
+					if ("result" in _eData) {
+						_result = _eData.result;
+						for (let i = 0; i < _result.length; i++) {
+							_mdText = _mdText.replace(_result[i].text, _result[i].fileName);
+						}
+					}
+					_mdText = _mdText.replace("_", "");
+					_copyData.jsonData.content = _mdText;
+					this.loading = false;
+					this.loadNum = 0;
+					this.$emit("editItem", this.data.id, _copyData);
+					this.$emit("saveItem", this.data.id, _copyData);
+					_source.close();
+				} else {
+					let _text = _eData.content.replace("'", "").replace("'", "");
+					if (_allText == "") {
+						_allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
+					} else {
+						_allText += _text;
+					}
+					_mdText = _allText + "_";
+					_mdText = _mdText.replace(/\\n/g, "\n");
+					_mdText = _mdText.replace(/\\/g, "");
+					if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
+					//转化返回的回复流数据
+					// _mdText = md.render(_mdText);
+					_copyData.jsonData.content = _mdText;
+					this.$emit("editItem", this.data.id, _copyData);
+					// 处理流数据
+				}
+			};
+		},
+		getData() {
+			if (this.bmData.editorBarData.type != 0) {
+				return this.$message.info("请上传表格形式的转录文稿");
+			}
+			try {
+				let _result = [];
+				let _data = this.bmData.editorBarData.content;
+				let _div = document.createElement("div");
+				_div.innerHTML = _data;
+				let _tableRows = _div.querySelectorAll(`table tbody tr`);
+				_tableRows.forEach((i, index) => {
+					if (index == 0) return;
+					let obj = {
+						index: i.cells[0].textContent,
+						startTime: i.cells[1].textContent,
+						endTime: i.cells[2].textContent,
+						message: i.cells[3].textContent,
+						time: i.cells[4].textContent,
+						role: i.cells[5].textContent,
+						behavior: i.cells[6].textContent,
+					};
+					_result.push(obj);
+				});
+				if (_result.length == 0) return this.$message.error("未找到表格数据");
+				if (this.data.jsonData.name == "S-T分析:课堂时间分配") {
+					this.getTimeAllocationData(_result);
+				} else if (this.data.jsonData.name == "S-T分析:师生互动分析") {
+					this.getInteractionAnalysisData(_result);
+				} else if (this.data.jsonData.name == "S-T分析:教学模式分析") {
+					this.getTeachingModeData(_result);
+				} else {
+					return this.$message.error("未找到对应的分析");
+				}
+			} catch (error) {
+				console.log(error);
+				this.loadNum = 2;
+				this.loading = false;
+				return this.$message.error("生成分析失败");
+			}
+		},
+		// 课堂时间分配
+		getTimeAllocationData(_dataList) {
+			this.loading = true;
+			this.openItem = false;
+			let _data = _dataList.reduce((pre,cur)=>{
+				if(cur.role == '学生'){
+					pre[1].value += this.convertToSeconds(cur.time)
+				}else if(cur.role=='老师'){
+					pre[0].value += this.convertToSeconds(cur.time)
+				}
+				return pre;
+			},[
+				{value:0,name:"老师"},
+				{value:0,name:'学生'}
+			])
+			const _option = {
+				tooltip: {
+					trigger: "item",
+				},
+				legend: {
+					top: "5%",
+					left: "center",
+				},
+				series: [
+					{
+						name: "课堂时间分配",
+						type: "pie",
+						radius: ["40%", "70%"],
+						avoidLabelOverlap: false,
+						label: {
+							show: false,
+							position: "center",
+						},
+						emphasis: {
+							label: {
+								show: true,
+								fontSize: 40,
+								fontWeight: "bold",
+							},
+						},
+						labelLine: {
+							show: false,
+						},
+						data: _data
+					},
+				],
+			};
+			let _copyData = JSON.parse(JSON.stringify(this.data));
+			_copyData.jsonData.eChartData = _option;
+			_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;
+		},
+		// 师生互动分析
+		getInteractionAnalysisData(_dataList) {
+			this.loading = true;
+			this.openItem = false;
+			let _pushData = [0,0]
+			let _result = []
+			_dataList.forEach(i=>{
+				if(i.role=='老师'){
+					_pushData[0] += this.convertToSeconds(i.time)
+				}else if(i.role=='学生'){
+					_pushData[1] += this.convertToSeconds(i.time)
+				}
+				return _result.push(JSON.parse(JSON.stringify(_pushData)))
+			})
+			const _option = {
+				xAxis: {
+					name: "老师", // X轴标题
+					nameLocation: "end", // 标题位置
+				},
+				yAxis: {
+					name: "学生", // Y轴标题
+					nameLocation: "end", // 标题位置
+				},
+				series: [
+					{
+						data: _result,
+						type: "line",
+					},
+				],
+			};
+
+			let _copyData = JSON.parse(JSON.stringify(this.data));
+			_copyData.jsonData.eChartData = _option;
+			_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;
+
+		},
+		// 教学模式分析
+		getTeachingModeData(_dataList) {
+			this.openItem = false;
+			this.loading = true
+			let _continuousTime = 0;
+			let _totalTime = 0;
+			let _continuousRole = "老师"
+			let _teacherTime = 0;
+			_dataList.forEach((item,index)=>{
+				if(index==0){//第一个
+					_continuousRole = item.role
+				}else if(_dataList.length-1==index){//最后一个
+					if(_continuousRole==item.role){//连续对话了
+						_continuousTime += this.convertToSeconds(_dataList[index-1].time)
+						_continuousTime += this.convertToSeconds(item.time)
+					}else{//没连续对话
+						if(index>=2){
+							if(_dataList[index-2].role==_dataList[index-1].role){
+								_continuousTime += this.convertToSeconds(_dataList[index-1].time)
+							}else{
+								_continuousRole = item.role;
+							}
+						}else{
+							_continuousRole = item.role;
+						}
+					}
+				}else{
+					if(_continuousRole==item.role){//连续对话了
+						_continuousTime += this.convertToSeconds(_dataList[index-1].time)
+					}else{//没连续对话
+						if(index>=2){
+							if(_dataList[index-2].role==_dataList[index-1].role){
+								_continuousTime += this.convertToSeconds(_dataList[index-1].time)
+							}else{
+								_continuousRole = item.role;
+							}
+						}else{
+							_continuousRole = item.role;
+						}
+					}
+				}
+
+				if(item.role == "老师"){
+					_teacherTime+=this.convertToSeconds(item.time);
+				}
+
+				_totalTime += this.convertToSeconds(item.time);
+			})
+
+			let _RT = (_teacherTime/_totalTime).toFixed(2)
+			let _CH = (_continuousTime/_totalTime).toFixed(2)
+			let _copyData = JSON.parse(JSON.stringify(this.data));
+			_copyData.jsonData.RT = _RT;
+			_copyData.jsonData.CH = _CH;
+			_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;
+		},
+		delBtn() {
+			this.$confirm("确定删除?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "error",
+			})
+				.then(() => {
+					this.$emit("delItem", this.data.id);
+				})
+				.catch((_) => {
+					console.log("取消");
+				});
+		},
+		changeShowIndex(value) {
+			if (this.historyResult.length == 0) return;
+			if (value == -1) {
+				if (this.showIndex > 0) this.showIndex--;
+			} else if (value == 1) {
+				if (this.showIndex < this.historyResult.length - 1) this.showIndex++;
+			}
+			let _copyData = JSON.parse(JSON.stringify(this.data));
+			let _oldCopyDate = JSON.parse(JSON.stringify(this.data));
+			_copyData.jsonData = this.historyResult[this.showIndex];
+			_copyData.json_data = JSON.stringify(_copyData.jsonData);
+			_oldCopyDate.json_data = JSON.stringify(_oldCopyDate.jsonData);
+			// 一样就不用更新了
+			if (JSON.stringify(_copyData) == JSON.stringify(_oldCopyDate)) return;
+			// this.data = _copyData;
+			this.$emit("editItem", this.data.id, _copyData);
+			this.$emit("saveItem", this.data.id, _copyData);
+		},
+		convertToSeconds(time) {
+		  let parts = time.split(':');
+		  let seconds = (+parts[0]) * 3600 + (+parts[1]) * 60 + (+parts[2]);
+		  return seconds;
+		}
+	},
+	mounted() {
+		if (this.data.jsonData.content) {
+			this.historyResult.push(this.data.jsonData);
+		}
+	},
+};
+</script>
+
+<style scoped>
+.analysisItem {
+	width: 100%;
+	height: auto;
+
+	margin: 11.7px 0px;
+
+	padding-right: 10px;
+	box-sizing: border-box;
+}
+.text1 {
+	color: rgba(54, 129, 252, 1);
+}
+.text2 {
+	color: rgba(23, 196, 105, 1);
+}
+.ai-header {
+	width: 100%;
+	height: 50px;
+	display: flex;
+	background-color: white;
+	border-radius: 5px;
+}
+.ai-h-left {
+	flex: 1;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 0 10px;
+	cursor: pointer;
+}
+
+.ai-h-l-icon {
+	width: 16px;
+	height: 16px;
+	background: url("../../../../assets/icon/classroomObservation/right.svg")
+		no-repeat;
+	background-size: 100% 100%;
+	margin-right: 10px;
+	transition: 0.3s;
+}
+
+.ai-h-l-iconActive {
+	transform: rotate(90deg);
+}
+.ai-h-l-text {
+	font-size: 18px;
+}
+
+.ai-h-right {
+	width: auto;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: space-around;
+	position: relative;
+}
+
+.ai-h-right > span {
+	width: 18px;
+	height: 18px;
+	background-size: 100% 100%;
+	margin: 0 10px;
+	cursor: pointer;
+}
+
+.ai-h-right > span > img {
+	width: 18px;
+	height: 18px;
+}
+
+.ai-h-r-icon1 {
+	background: url("../../../../assets/icon/classroomObservation/back.svg");
+	/* 镜像 */
+	transform: scaleX(-1);
+}
+
+.ai-h-r-icon2 {
+	background: url("../../../../assets/icon/classroomObservation/back.svg");
+}
+
+.ai_h_r_iconOpacity {
+	opacity: 0.5;
+	cursor: not-allowed !important;
+}
+
+.ai-h-r-icon3 {
+	background: url("../../../../assets/icon/classroomObservation/edit.svg");
+	/* display: none; */
+}
+
+.ai-header:hover .ai-h-r-icon4 {
+	display: block;
+}
+
+.ai-h-r-icon4 {
+	background: url("../../../../assets/icon/classroomObservation/del.svg");
+	/* position: absolute; */
+	/* right: -40px; */
+	display: none;
+}
+
+.analysisItem:hover .ai-h-r-icon4 {
+	display: block;
+}
+
+.ai-main {
+	width: 100%;
+	height: auto;
+	background-color: white;
+	border-radius: 0 0 5px 5px;
+	overflow: auto;
+	box-sizing: border-box;
+	padding: 10px 20px;
+}
+
+.a-m-brief {
+	font-size: 16px;
+	/* 斜体 */
+	font-style: italic;
+	margin-bottom: 10px;
+	color: #6b798e;
+}
+
+td,
+th {
+	padding: 10px;
+}
+
+.generate {
+	color: #00000099;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+
+.generate > img {
+	margin-right: 5px;
+	width: 20px;
+	height: 20px;
+}
+
+.generateSuccess {
+	color: #17c469;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+
+.generateSuccess > img {
+	margin-right: 5px;
+	width: 20px;
+	height: 20px;
+}
+
+.generateError {
+	color: #e60012;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+
+.rtCh{
+	width: 100%;
+	height: 300px;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+}
+
+.rtCh>img{
+	max-height: 250px;
+}
+
+.rtCh>div{
+	margin-top: 20px;
+}
+
+.rtCh>div>span{
+	margin: 0 10px;
+	font-size: 20px;
+	font-weight: bold;
+	color: #1A7AD3;
+	/* 斜体字 */
+	font-style: italic;
+}
+</style>

+ 5 - 1
src/components/pages/classroomObservation/components/analysisTemplateDialog.vue

@@ -173,7 +173,7 @@
 								</div>
 								<div class="a-d-b-i-bottom">{{ item.detail }}</div>
 								<div class="a-d-b-i-bottomPer">
-									<span>{{ 3982 }}人已使用</span>
+									<span>{{ item.use }}人已使用</span>
 									<span>{{
 										tagSubjectList.find((i) => i.value == item.type)
 											? tagSubjectList.find((i) => i.value == item.type).label
@@ -504,6 +504,7 @@ export default {
 					let params = {
 						uid: this.userId,
 						cid: item.id,
+						st:1,
 					};
 					this.ajax
 						.get(
@@ -564,6 +565,7 @@ export default {
 			let params = {
 				uid: this.userId,
 				cid: item.id,
+				st:0
 			};
 			this.ajax
 				.get(this.$store.state.api + "selectClassroomTemplateDetail", params)
@@ -592,12 +594,14 @@ export default {
 			let params = {
 				uid: this.userId,
 				cid: item.id,
+				st:0
 			};
 			this.ajax
 				.get(this.$store.state.api + "selectClassroomTemplateDetail", params)
 				.then((res) => {
 					let _data = res.data[0][0];
 					if (_data) {
+					
 						_data.tips = JSON.parse(_data.tips);
 						this.analysisDetail = _data;
 						this.tagBox = 1;

+ 40 - 40
src/components/pages/classroomObservation/components/baseMessage.vue

@@ -508,33 +508,55 @@ export default {
 			if(!this.tid)return this.$message.error("请选择课堂")
 			if(this.uploadNephogramLoading)return this.$message.info("请稍等");
 			this.uploadNephogramLoading = true;
-			let _workText = ``;
-			this.dataList.forEach((i) => {
-						let _jsonObj = i.jsonData;
-							_workText += `名称:${_jsonObj.name}\n分析内容:${_jsonObj.content?_jsonObj.content:''}\n\n`;
-				});
 			const _msg = `NOTICE
 Language: Please use the same language as the user requirement, if the user speaks Chinese, the specific text of your answer should also be in Chinese.
 ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
 Instruction: Based on the context, follow "Format example", write content.
 
-## 参靠内容
-${_workText}
+## 任务
+
+请基于以下课堂实录文本(大约5000字),提炼出20-30个关键词,用于绘制词云图。请给出相应的关键词,关键词出现的频次,词云图上的大小。请确保输出的关键字准确反映课堂实录的主要内容和主题。
 
 ## 要求
-根据#参考内容 生成词云图数据,2-4个字的短语,选取与课程比较相关的词汇,禁止有重复的词汇,去掉【这里】【哪里】【谁知】之类无指示含义的词汇;格式参考## format example
-输入完整的JSON数据,禁止有重复的词汇;
-## format example
+
+1. **提取关键词**:从提供的课堂实录文本中提取出20-30个最具代表性的关键字。关键词应该涵盖课堂实录中的主要概念、重要术语和核心主题。尽量选择多样化的关键词,避免过于集中在某一个主题或概念上。
+2. **词频统计**:计算每个关键字在文本中出现的频率。
+3. **词汇大小**:根据词频数量,确定每个关键字在词云图中的大小。词频越高,词汇大小数值越大,数值范围1-100。
+4. **输出格式**:输出结果应包含每个关键字、对应的词频数量以及词汇大小数值。
+
+## 输出格式
+
+### 输出格式
+
+[
+	{"value":1,"name":"氯化钠","textStyle":{"color":"#ee7959"}},
+	{"value":2,"name":"溶液","textStyle":{"color":"#db9b34"}},
+	{"value":1,"name":"实验","textStyle":{"color":"#9d9d82"}},
+	{"value":3,"name":"质量分数","textStyle":{"color":"#ea5514"}},
+	{"value":1,"name":"溶质","textStyle":{"color":"#c8161d"}},
+	{"value":2,"name":"氢氧化钠","textStyle":{"color":"#e60012"}},
+	{"value":1,"name":"溶解度","textStyle":{"color":"#1e2732"}},
+	{"value":4,"name":"饱和溶液","textStyle":{"color":"#e3adb9"}}
+]
+
+请仅仅输出表头,输出关键词和相应的内容,无需其它任何说明文字。
+冒号、逗号等符号均使用英文字符。
+
+### 输出示例
+
 [
-	{"value":1,"name":"词汇","textStyle":{"color":"随机颜色"}},
-	{"value":2,"name":"词汇","textStyle":{"color":"随机颜色"}},
-	{"value":1,"name":"词汇","textStyle":{"color":"随机颜色"}},
-	{"value":3,"name":"词汇","textStyle":{"color":"随机颜色"}},
-	{"value":1,"name":"词汇","textStyle":{"color":"随机颜色"}},
-	{"value":2,"name":"词汇","textStyle":{"color":"随机颜色"}},
-	{"value":1,"name":"词汇","textStyle":{"color":"随机颜色"}},
-	{"value":4,"name":"词汇","textStyle":{"color":"随机颜色"}}
+	{"value":1,"name":"氯化钠","textStyle":{"color":"#ee7959"}},
+	{"value":2,"name":"溶液","textStyle":{"color":"#db9b34"}},
+	{"value":1,"name":"实验","textStyle":{"color":"#9d9d82"}},
+	{"value":3,"name":"质量分数","textStyle":{"color":"#ea5514"}},
+	{"value":1,"name":"溶质","textStyle":{"color":"#c8161d"}},
+	{"value":2,"name":"氢氧化钠","textStyle":{"color":"#e60012"}},
+	{"value":1,"name":"溶解度","textStyle":{"color":"#1e2732"}},
+	{"value":4,"name":"饱和溶液","textStyle":{"color":"#e3adb9"}}
 ]
+
+## 课堂实录 
+${this.data.editorBarData.content}
 `;
 				const _uuid = uuidv4();
 				let params = {
@@ -583,23 +605,7 @@ ${_workText}
         //   enable: true,
         //   minSize: 12,
         // },
-        // textStyle: {
-        //   color: function () {
-        //     var colors = [
-        //       '#F6A878',
-        //       '#FDCA71',
-        //       '#D9E4E4',
-        //       '#CAE1E6',
-        //       '#8B9ECD',
-        //       '#6CB9FB',
-        //       '#5596F7',
-        //       '#4778FE',
-        //     ];
-        //     return colors[parseInt(Math.random() * 8)];
-        //   },
-        // },
         data: _result,
-        // [{name: "行政处罚"num: 1324}]
       },
     ],
   })
@@ -611,12 +617,6 @@ ${_workText}
 					.finally((_) => {
 						this.uploadNephogramLoading = false;
 					});
-			// this.$emit('saveNephogram',{
-			// 		name: "测试",
-			// 		status: "success",
-			// 		uid: "1",
-			// 		url: "测试",
-			// })
 		},
 
 		// 删除图片

+ 2 - 2
src/components/pages/classroomObservation/components/bindingFormDialog.vue

@@ -32,8 +32,8 @@
 					<span @click.stop="dialogVisible = false">×</span>
 				</div>
 			</div>
-			<div class="bfd_box" v-loading="loading">
-				<el-table :data="list" border>
+			<div class="bfd_box">
+				<el-table :data="list" border  v-loading="loading">
 					<el-table-column
 						prop="title"
 						label="标题"

+ 40 - 5
src/components/pages/classroomObservation/components/chatArea.vue

@@ -324,7 +324,7 @@
 								justify-content: space-between;
 							"
 						>
-							<div class="lyStart" @click="stopRecorded()">
+							<div class="lyStart" @click="stopRecorded()" v-loading="recordedForm.loading">
 								<img
 									style="width: 12px; height: 12px"
 									src="@/assets/icon/classroomObservation/lyStart.svg"
@@ -338,7 +338,7 @@
 									v-if="recordedForm.status == 2"
 								/>
 							</div>
-							<div class="lyStart" @click="finishRecorded()">
+							<div class="lyStart" @click="finishRecorded()" v-loading="recordedForm.loading">
 								<img
 									style="width: 12px; height: 12px"
 									src="@/assets/icon/classroomObservation/lyStop.svg"
@@ -528,6 +528,7 @@ export default {
 				startTime: 0,
 				endTime: 0,
 				textList: [],
+				loading:false,
 			},
 			roleList: [],
 			publicRoleList: [],
@@ -684,7 +685,7 @@ export default {
 			if (this.uploadFileLoading) return this.$message.info("请稍等...");
 			// 开始录音
 			if (this.audioUrl) {
-				this.$confirm("再次录音会顶替掉原先的录音,您确定吗", "提醒", {
+				this.$confirm("是否创建新的课堂并开始录音?", "提醒", {
 					confirmButtonText: "确定",
 					cancelButtonText: "取消",
 					type: "warning",
@@ -694,9 +695,13 @@ export default {
 						this.audioUrl = "";
 						// recorder.initRecorder(); //初始化录音
 						// recorder.destroy(); // 销毁录音
-						this.recordedStart();
+						// this.recordedStart();
+						return this.$parent.addNewCourse().then(_=>{
+							this.recordedStart();
+						})
 					})
-					.catch((_) => {
+					.catch((e) => {
+						console.log(e)
 						console.log("不顶替");
 					});
 			} else if (this.controlsStatus != 1 && this.recordedForm.status == 0) {
@@ -890,8 +895,10 @@ export default {
 			// this.uploadWavFileAndGetText(audioFile);
 		},
 		stopRecorded() {
+			if(this.recordedForm.loading)return this.$message.info("请稍等")
 			if (this.recordedForm.status == 1) {
 				//暂停
+				this.recordedForm.loading = true;
 				let iiframe = this.$refs["iiframe"];
 				iiframe.contentWindow.window.document
 					.getElementById("scenarioStopButton")
@@ -907,12 +914,14 @@ export default {
 					this.recordedForm.audioBlob.push(e.preaudio);
 					iiframe.contentWindow.onSessionStopped = null;
 					iiframe.contentWindow.onRecognizedResult = null;
+					this.this.recordedForm.loading = false;
 				};
 				// this.recordedForm.status = 2;
 				// clearInterval(this.recordedForm.timer)
 				// this.$message.success("已暂停录音")
 			} else if (this.recordedForm.status == 2) {
 				//开始
+				this.recordedForm.loading = true;
 				let iiframe = this.$refs["iiframe"];
 				iiframe.contentWindow.window.document.getElementById(
 					"languageOptions"
@@ -921,6 +930,7 @@ export default {
 				this.controlsStatus = 1;
 				this.recordedForm.status = 1;
 				this.$message.success("已开始录音");
+				this.recordedForm.loading = false;
 				this.recordedForm.timer = setInterval(() => {
 					this.recordedForm.timeDuration += 1;
 					this.recordedForm.time = this.updateRecordedTime({
@@ -1770,6 +1780,31 @@ export default {
 				// let div = document.createElement("div");
 				// div.innerHTML = this.editorBarData.content;
 				// return this.loading = false;
+				let _data = this.editorBarData.content;
+				let _div = document.createElement("div");
+				let _sentence = 0;
+				let _words = 0;
+				_div.innerHTML = _data;
+				let _tableRows = _div.querySelectorAll(`table tbody tr`);
+				_tableRows.forEach((i, index) => {
+					if (index == 0) return;
+					// let obj = {
+					// 	index: i.cells[0].textContent,
+					// 	startTime: i.cells[1].textContent,
+					// 	endTime: i.cells[2].textContent,
+					// 	message: i.cells[3].textContent,
+					// 	time: i.cells[4].textContent,
+					// 	role: i.cells[5].textContent,
+					// 	behavior: i.cells[6].textContent,
+					// };
+					if(i.cells[3].textContent!=""){
+						_sentence+=1;
+						_words+=i.cells[3].textContent.length;
+					}
+				});
+				this.editorBarData.sentenceNum = _sentence;
+				this.editorBarData.wordsNum = _words;
+				this.$parent.saveWordFrequency({_sentence,_words})
 				this.$emit(
 					"updateTranscription",
 					{

+ 46 - 0
src/components/pages/classroomObservation/components/eChartTemplate.vue

@@ -0,0 +1,46 @@
+<template>
+	<div class="chart" id="charts_canvas" ref="chartRef"></div>
+</template>
+
+<script>
+import * as echarts from 'echarts';
+export default {
+	props: {
+		data: {
+			type: Object,
+			default: () => {},
+		},
+	},
+	data() {
+		return {
+			chartObj: null,
+			chartData: null,
+		};
+	},
+	watch: {
+		data() {
+			this.getChartData();
+		},
+	},
+	methods: {
+		getChartData() {
+			this.chartObj = echarts.init(this.$refs.chartRef);
+			this.chartObj.setOption(this.data);
+			window.addEventListener("resize", () => {
+					this.chartObj.resize();
+      });
+		},
+	},
+	mounted() {
+		this.getChartData();
+	},
+};
+</script>
+
+<style scoped>
+.chart {
+	max-width: 100%;
+	width: 100%;
+	height: 100%;
+}
+</style>

+ 41 - 18
src/components/pages/classroomObservation/components/messageArea.vue

@@ -37,6 +37,7 @@
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
 				@saveItem="saveAnalysis"
+				:bmData="bmData.jsonData"
 				title="通用课堂分析"
 				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 0)"
@@ -49,6 +50,7 @@
 				@updateMessage="updateMessage"
 				ref="analysis1"
 				:showBrief="showBrief"
+				:bmData="bmData.jsonData"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
 				@saveItem="saveAnalysis"
@@ -63,6 +65,7 @@
 			<analysis
 				@updateMessage="updateMessage"
 				ref="analysis2"
+				:bmData="bmData.jsonData"
 				:showBrief="showBrief"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
@@ -270,6 +273,7 @@ export default {
 			scienceLoading: false,
 			extendLoading: false,
 			valueAddedLoading: false,
+			userId: this.$route.query["userid"],
 			input2: "",
 			userId:this.$route.query['userid'],
 			dialogTagList: [
@@ -314,21 +318,27 @@ export default {
 					type: 0,
 					sum:206
 				},
-				// {
-				// 	title: "课堂时间分配",
-				// 	brief: "多维度分析课堂整体情况",
-				// 	type: 0
-				// },
-				// {
-				// 	title: "师生互动分析",
-				// 	brief: "多维度分析课堂整体情况",
-				// 	type: 0
-				// },
-				// {
-				// 	title: "教学模式分析",
-				// 	brief: "多维度分析课堂整体情况",
-				// 	type: 0
-				// },
+				{
+					title: "S-T分析:课堂时间分配",
+					brief: "多维度分析课堂整体情况",
+					value: "st1",
+					type: 0,
+					sum:451
+				},
+				{
+					title: "S-T分析:师生互动分析",
+					brief: "多维度分析课堂整体情况",
+					value: "st2",
+					type: 0,
+					sum:342
+				},
+				{
+					title: "S-T分析:教学模式分析",
+					brief: "多维度分析课堂整体情况",
+					value: "st3",
+					type:0,
+					sum:143
+				},
 				{
 					title: "课堂活动类型",
 					brief: "识别特定的课堂活动类型",
@@ -608,6 +618,7 @@ export default {
 				let newIndex = newIndexData?newIndexData.tIndex+1:assistant.type==0?2:0;
 				let params = {
 					index: newIndex,
+					userid:this.userId,
 					json_data: JSON.stringify({
 						name: assistant.title,
 						result: "",
@@ -634,8 +645,8 @@ export default {
 								this.$refs.analysis1.getReport(_result.id);
 							} else if (_result.Type == 2) {
 								this.$refs.analysis2.getReport(_result.id);
-							} else if (_result.Type == 3) {
-								this.$refs.analysis3.getReport(_result.id);
+							// } else if (_result.Type == 3) {
+							// 	this.$refs.analysis3.getReport(_result.id);
 							}
 							this.$message.success("添加成功");
 							resolve();
@@ -936,6 +947,18 @@ export default {
 				this.$forceUpdate();
 			});
 		},
+		// 保存词频词汇分析
+		saveWordFrequency({_sentence=0,_words=0}){
+			let _saveData = this.dataList.find(i=>i.jsonData.name=='词频词汇分析');
+			if(_saveData){
+				_saveData.jsonData.wordCountNum = _sentence;
+			_saveData.jsonData.wordNum = _words;
+			this.saveData(_saveData).then(_=>{
+				console.log("词频词汇分析")
+			})
+			}
+			
+		},
 		// 切换录音文件
 		changeAudioUrl(data){
 			this.imageList.jsonData.fileList = [];
@@ -955,7 +978,7 @@ export default {
 			this.$refs.analysis0.getReport();
 			this.$refs.analysis1.getReport();
 			this.$refs.analysis2.getReport();
-			this.$refs.analysis3.getReport();
+			// this.$refs.analysis3.getReport();
 		},
 		insertBaseMessage() {
 			return new Promise((resolve, reject) => {

+ 6 - 1
src/components/pages/classroomObservation/index.vue

@@ -290,6 +290,7 @@ export default {
 					this.$refs.messageAreaRef.getReport();
 				})
 				.catch((e) => {
+					console.log(e)
 					console.log("取消生成报告");
 				});
 		},
@@ -502,7 +503,11 @@ export default {
 				this.loading = false;
 			})
 			}
-		}
+		},
+		//保存词频词汇分析
+		saveWordFrequency({_sentence=0,_words=0}){
+			this.$refs.messageAreaRef.saveWordFrequency({_sentence,_words})
+		},
 	},
 	mounted() {
 		this.getCourseList().then((_) => {

+ 172 - 0
src/components/pages/components/wOffice.vue

@@ -0,0 +1,172 @@
+<template>
+  <!--使用 pdfvuer 实现 滑动浏览 单印章-->
+  <div class="pdf">
+    <iframe ref="viframe" style="width: 100%; height: 99%; border: none"
+    :src="'https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(url)"></iframe>
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: "Pdfvuer",
+  components: {
+    // pdf: pdfvuer,
+  },
+  props: {
+    // 当前pdf路径
+    url: {
+      type: String,
+      default:
+        "",
+    },
+  },
+  data() {
+    return {
+
+    };
+  },
+  mounted() {
+  
+  },
+  beforeDestroy() { },
+  watch: {
+  },
+  methods: {
+   
+  },
+};
+</script>
+<style scoped>
+.loading {
+  height: 100%;
+  width: 100%;
+  /* background: #000; */
+  position: absolute;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  /* background-color: rgba(255, 255, 255, 0.7); */
+  background-color: rgba(255, 255, 255, 1);
+  z-index: 9;
+  font-size: 20px;
+  color: #007fff;
+}
+
+.pdf {
+  height: 100%;
+  width: 100%;
+  position: relative;
+  box-sizing: border-box;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.pdf .show {
+  margin: auto;
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.pdf .show .p-pdf {
+  overflow: hidden;
+}
+
+.pdf .show .p-pdf .line {
+  position: absolute;
+  width: 50px;
+  right: -50px;
+  background: rgb(255, 186, 96);
+  height: 2px;
+}
+
+.pdf .show .p-pdf span {
+  width: 100%;
+  text-align: center;
+  color: #fff;
+}
+
+.pdf .show .p-pdf span+span {
+  margin-top: 10px;
+}
+
+.pdfbox {
+  /* border: 3px solid #000; */
+  /* box-sizing: border-box; */
+  /* border-radius: 4px; */
+  /* overflow: hidden; */
+}
+
+.pdf .pdf_footer {
+  position: sticky;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 10px 0;
+  width: 100%;
+  height: 75px;
+  background-color: rgba(255, 255, 255, 0.5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+}
+
+.pdf .pdf_footer .info {
+  display: flex;
+  flex-wrap: wrap;
+  width: 100%;
+  justify-content: center;
+}
+
+.pdf .p-pdf .viewerContainer {
+  width: 100%;
+}
+
+/* .pdf .pdf_footer .info div {
+  width: 30%;
+} */
+.pdf .pdf_footer .operate {
+  margin: 10px 0 0;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+  width: 100%;
+}
+
+.pdf .pdf_footer .operate div {
+  text-align: center;
+  font-size: 15px;
+}
+
+.pdf .pdf_footer .operate .btn {
+  cursor: pointer;
+  margin: 5px 10px;
+  width: 100px;
+  border-radius: 10px;
+  padding: 5px;
+  color: #fff;
+  background-color: #066ebe;
+}
+
+.pdf::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 6px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 6px;
+}
+
+/*定义滚动条轨道 内阴影+圆角*/
+.pdf::-webkit-scrollbar {
+  border-radius: 10px;
+  background-color: #b8bdc9;
+}
+
+/*定义滑块 内阴影+圆角*/
+.pdf::-webkit-scrollbar-thumb {
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 6px rgb(96, 125, 184);
+  background-color: #2c5ab3;
+}
+</style>

+ 190 - 36
src/components/pages/contrastObservation/index.vue

@@ -1,6 +1,51 @@
 <template>
 	<div class="contrastObservation" v-loading="loading">
-		<div class="co_card co_aggregateData" v-loading="aggregateLoading">
+		<div class="co_nav">
+			<div class="co_n_left">
+				<span
+					:class="showIndex == 0 ? 'co_n_l_active' : ''"
+					@click="showIndex = 0"
+					v-loading="aggregateLoading"
+					>总览</span
+				>
+				<span
+					:class="showIndex == 1 ? 'co_n_l_active' : ''"
+					@click="showIndex = 1"
+						v-loading="aiLoading"
+					>AI观察</span
+				>
+				<span
+					:class="showIndex == 2 ? 'co_n_l_active' : ''"
+					@click="showIndex = 2"
+						v-loading="teacherLoading"
+					>教师观察</span
+				>
+				<span
+					:class="showIndex == 3 ? 'co_n_l_active' : ''"
+					@click="showIndex = 3"
+					v-loading="contrastLoading"
+					>对比观察</span
+				>
+			</div>
+			<div class="co_n_right" v-loading="
+				loading ||
+				aggregateLoading ||
+				aiLoading ||
+				teacherLoading ||
+				contrastLoading
+			">
+				<div @click.stop="refresh()">
+					<img
+						:src="require('../../../assets/icon/contrastObservation/refresh.svg')"
+					/>
+				</div>
+			</div>
+		</div>
+		<div
+			class="co_card co_aggregateData"
+			:style="`z-index:${showIndex == 0 ? 11 : 10}`"
+			v-loading="aggregateLoading"
+		>
 			<div class="co_ad_title">
 				<img
 					:src="
@@ -14,7 +59,10 @@
 			</div>
 			<div class="co_ad_messageArea" v-html="aggregateData.message"></div>
 		</div>
-		<div class="co_card co_ai_card">
+		<div
+			class="co_card co_ai_card"
+			:style="`z-index:${showIndex == 1 ? 11 : 10}`"
+		>
 			<div class="co_c_main" v-loading="aiLoading">
 				<div class="co_c_title">AI观察结果</div>
 				<div
@@ -54,7 +102,10 @@
 				</div>
 			</div>
 		</div>
-		<div class="co_card co_teacher_card">
+		<div
+			class="co_card co_teacher_card"
+			:style="`z-index:${showIndex == 2 ? 11 : 10}`"
+		>
 			<div class="co_c_main" v-loading="teacherLoading">
 				<div class="co_c_title">教师观察结果</div>
 				<div
@@ -94,7 +145,10 @@
 				</div>
 			</div>
 		</div>
-		<div class="co_card co_contrast_card">
+		<div
+			class="co_card co_contrast_card"
+			:style="`z-index:${showIndex == 3 ? 11 : 10}`"
+		>
 			<div class="co_c_main" v-loading="contrastLoading">
 				<div class="co_c_title">对比观察结果</div>
 				<div
@@ -206,7 +260,8 @@ export default {
 				checkUrl: "",
 				doUrl: "",
 			},
-			bmData:null,
+			showIndex: 0,
+			bmData: null,
 			editorBarData: {
 				type: 0,
 				content: "",
@@ -291,13 +346,15 @@ export default {
 							let _testData = baseMessage.jsonData.testData;
 							this.editorBarData = baseMessage.jsonData.editorBarData;
 							this.bmData = baseMessage;
-							if(!flag){//判断是否是需要生成数据
-								if(baseMessage.jsonData.contrastObservationData){//如果有这个字段则只取里面的数据
+							if (!flag) {
+								//判断是否是需要生成数据
+								if (baseMessage.jsonData.contrastObservationData) {
+									//如果有这个字段则只取里面的数据
 									let _data = baseMessage.jsonData.contrastObservationData;
-									this.aggregateData=_data.aggregateData;
-									this.aiData=_data.aiData;
-									this.teacherData=_data.teacherData;
-									this.contrastData=_data.contrastData;
+									this.aggregateData = _data.aggregateData;
+									this.aiData = _data.aiData;
+									this.teacherData = _data.teacherData;
+									this.contrastData = _data.contrastData;
 									return;
 								}
 							}
@@ -1160,16 +1217,19 @@ ${_aiWorkText}
 			this.getBindTestId(flag).then((_) => {
 				// 后去表单的数据
 				this.getBindTestData().then((_) => {
+					Promise.all([
+						this.getTeacherResultData(),
+						this.getAiResultData(),
+					]).then((_) => {
+						this.getAggregateChartData();
 						Promise.all([
-							this.getTeacherResultData(),
-							this.getAiResultData(),
+							this.getContrastResultData(),
+							this.getAggregateResultData(),
 						]).then((_) => {
-							this.getAggregateChartData();
-							Promise.all([this.getContrastResultData(),this.getAggregateResultData()]).then(_=>{
-								this.saveData()
-							})
+							this.saveData();
 						});
 					});
+				});
 			});
 		},
 		//储存数据
@@ -1177,11 +1237,11 @@ ${_aiWorkText}
 			return new Promise((resolve, reject) => {
 				let _saveData = JSON.parse(JSON.stringify(this.bmData));
 				_saveData.jsonData.contrastObservationData = {
-						aggregateData: this.aggregateData,
-						aiData: this.aiData,
-						teacherData: this.teacherData,
-						contrastData: this.contrastData,
-				}
+					aggregateData: this.aggregateData,
+					aiData: this.aiData,
+					teacherData: this.teacherData,
+					contrastData: this.contrastData,
+				};
 				let params = {
 					id: _saveData.id,
 					json_data: JSON.stringify(_saveData.jsonData),
@@ -1189,16 +1249,14 @@ ${_aiWorkText}
 				// console.log(params)
 				// return resolve();
 				this.ajax
-					.post(
-						"https://gpt4.cocorobo.cn/update_classroom_observation",
-						params
-					)
+					.post("https://gpt4.cocorobo.cn/update_classroom_observation", params)
 					.then((res) => {
-						this.$message.success("保存数据成功")
+						this.$message.success("保存数据成功");
 						resolve();
-					}).catch(e=>{
+					})
+					.catch((e) => {
 						console.log(e);
-						this.$message.info('保存数据失败')
+						this.$message.info("保存数据失败");
 					});
 			});
 		},
@@ -1211,9 +1269,9 @@ ${_aiWorkText}
 
 <style scoped>
 .contrastObservation {
-	min-width: 1500px;
+	/* min-width: 1500px; */
 	/* min-height: 800px; */
-	width: 100%;
+	width: 100vw;
 	height: 100vh;
 	display: flex;
 	background-color: #f0f2f5;
@@ -1224,6 +1282,7 @@ ${_aiWorkText}
 	justify-content: space-around;
 	align-items: center;
 	position: relative;
+	overflow-x: hidden
 }
 
 .refresh {
@@ -1239,6 +1298,7 @@ ${_aiWorkText}
 	align-items: center;
 	box-shadow: 0 16px 24px 2px #0000000a;
 	cursor: pointer;
+	z-index: 11;
 }
 
 .refreshDisabled {
@@ -1264,7 +1324,9 @@ ${_aiWorkText}
 	box-sizing: border-box;
 	padding: 20px;
 	position: relative;
-	overflow: hidden;
+	/* overflow: hidden; */
+	z-index: 10;
+	overflow-x:hidden ;
 }
 
 .co_aggregateData {
@@ -1436,7 +1498,9 @@ ${_aiWorkText}
 .titleBlob {
 	font-weight: bold;
 }
-
+.co_nav {
+	display: none;
+}
 /* .compareTitle{
 	margin-left: 10px;
 	position: relative;
@@ -1450,10 +1514,100 @@ ${_aiWorkText}
 	position: relative;
 } */
 /* 手机 */
-@media screen and (max-width:600px){
-	.refresh{
+@media screen and (max-width: 600px) {
+	.refresh {
 		display: none;
 	}
-}
+	.co_nav {
+		display: flex;
+		width: 100vw;
+		height: 50px;
+		position: absolute;
+		top: 0;
+		justify-content: space-between;
+		align-items: center;
+		background-color: #fff;
+	}
+	.co_n_left {
+		flex: 1;
+		height: 100%;
+		background-color: #fff;
+		display: flex;
+		display: flex;
+		align-items: center;
+		max-width: (100% - 50px);
+		overflow-y: hidden;
+	}
+	.co_n_left > span {
+		height: 100%;
+		padding: 0 10px;
+		margin: 0 5px;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		font-size: 1em;
+		white-space: nowrap;
+		position: relative;
 
+	}
+	.co_n_right {
+		width: 50px;
+		height: 100%;
+		background-color: #fff;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+	.co_n_right>div{
+		width: 100%;
+		height: 100%;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		position: relative;
+	}
+	.co_n_right>div::after{
+		content:"";
+		width: 2px;
+		height: 20px;
+		position: absolute;
+		left: 0;
+		top: 15px;
+		background-color: #E7E7E7;
+	}
+	.co_n_l_active {
+		color: #3681fc;
+	}
+	.co_n_l_active::after {
+		content: "";
+		width: 100%;
+		height: 2px;
+		background-color: #3681fc;
+		position: absolute;
+		bottom: 0;
+	}
+	.co_card {
+		position: absolute !important;
+		min-width: 100vw !important;
+		max-width: 100vw !important;
+		width: 100vw !important;
+		height: calc(100vh - 50px) !important;
+		margin-top: 50px;
+		border-radius: 0;
+	}
+	.co_ai_card {
+		padding: 0;
+	}
+
+	.co_teacher_card {
+		padding: 0;
+	}
+
+	.co_contrast_card {
+		padding: 0;
+	}
+	.co_card>.co_c_main{
+		border-radius: 0;
+	}
+}
 </style>

+ 107 - 11
src/components/pages/test/check/index.vue

@@ -27,7 +27,7 @@
           <div class="test_title">
             <div class="left">
               <div class="title">{{ testJson.title }}</div>
-              <div class="info">
+              <div class="info"  v-if="isDesktop">
                 <div class="info_box" v-if="testJson.typeN">
                   <span>类型:</span>
                   <span>{{ testJson.typeN }}</span>
@@ -42,7 +42,7 @@
                 </div>
               </div>
             </div>
-            <div class="right">
+            <div class="right" v-if="isDesktop">
               <div class="data_box">
                 <span>提交数量</span>
                 <span><span class="big">{{ works.length }}</span>份</span>
@@ -67,7 +67,42 @@
               <span :class="{ active: stype == 2 }" @click="checkDataType(2)">按人员查看</span>
               <span :class="{ active: stype == 3 }" @click="checkDataType(3)" v-show="false">按数量查看</span>
             </div>
-            <div class="left">
+            <div class="left"  v-if="isDesktop">
+              <div style="margin-right: 10px;position: relative;" v-if="stype == 2 || stype == 3">
+                <el-select v-model="TeachingValue" @change="searchCourse" placeholder="按教研室">
+                  <el-option
+                    label="全部"
+                    value="">
+                  </el-option>
+                  <el-option
+                    v-for="item in TeachingOptions"
+                    :key="item.id"
+                    :label="item.name"
+                    :value="item.id">
+                  </el-option>
+                </el-select>
+              </div>
+              <div style="margin-right: 10px;position: relative;" v-if="stype == 2 || stype == 3">
+                <el-date-picker
+                  v-model="SubmitTime"
+                  type="date"
+                   @change="searchCourse"
+                  value-format="yyyy-MM-dd"
+                  placeholder="选择日期">
+                </el-date-picker>
+                <!-- <el-select v-model="SubmitTime" placeholder="按提交时间筛选">
+                  <el-option
+                    label="全部"
+                    value="">
+                  </el-option>
+                  <el-option
+                    v-for="item in SubmitTimeOptions"
+                    :key="item.id"
+                    :label="item.name"
+                    :value="item.id">
+                  </el-option>
+                </el-select> -->
+              </div>
               <div style="margin-right: 10px;position: relative;" v-if="stype == 2 || stype == 3">
                 <el-input v-model="courseName" class="student_input" placeholder="请输入需要搜索的姓名"></el-input>
                 <span class="serach_icon" @click="searchCourse"></span>
@@ -320,9 +355,9 @@
                     <div>{{ scope.row.type == 3 ? '是' : '否' }}</div>
                   </template>
                 </el-table-column>
-                <el-table-column label="操作" width="300px">
+                <el-table-column label="操作" width="300px"  v-if="isDesktop">
 
-                  <template slot-scope="scope">
+                  <template slot-scope="scope" >
                     <el-button @click="getTest(scope.row)" type="primary" size="small">查看</el-button>
                     <el-button @click="setWordHtml2(scope.row)" type="primary" size="small">导出答题信息</el-button>
                     <el-button @click="deleteTest(scope.row.id)" type="primary" size="small">删除</el-button>
@@ -339,7 +374,7 @@
         </div>
       </div>
     </div>
-    <share-box :testJson="testJson" :dialogVisibleShare.sync="dialogVisibleShare"></share-box>
+    <share-box :testJson="testJson" :TeachingValue="TeachingValue" :TeachName="TeachNameCpt"   :dialogVisibleShare.sync="dialogVisibleShare"></share-box>
     <wpdf :dialogVisiblePdf.sync="dialogVisiblePdf" :url="wurl"></wpdf>
     <wVideo :dialogVisibleVideo.sync="dialogVisibleVideo" :url="wurl"></wVideo>
     <wOffice :dialogVisibleOffice.sync="dialogVisibleOffice" :url="wurl"></wOffice>
@@ -421,12 +456,18 @@ export default {
       role: this.$route.query.role,
       cid: this.$route.query.cid,
       isN: this.$route.query.isN,
+      screenWidth: window.innerWidth,
+      isDesktop: false,
       title: "",
       testType: [],
       see: false,
       cJson: [],
       loading: false,
       look: "",
+      TeachingOptions:[],
+      TeachingValue :'',
+      SubmitTimeOptions: [],
+      SubmitTime: '',
       tableHeight: 500,
       isLoading: false,
       pageSize: 10,
@@ -464,7 +505,21 @@ export default {
   },
   watch: {},
   computed: {
-
+    TeachNameCpt: function () {
+        // `this` 指向 vm 实例
+        return this.TeachingOptions.filter(i => {return i.id == this.TeachingValue})
+    },
+    // TeachNameCpt(){
+    //   return function (val) {
+    //     let a = this.TeachingOptions.filter(i => {
+    //       if (i.id == val) {
+    //          return i.name  
+    //       }}
+    //     )
+    //     console.log('aaaaaaaaaaaaaa',a);
+    //     return a;
+    //   };
+    // },
     // vcWords() {
     //   return function (array) {
     //     let _array = [];
@@ -525,6 +580,22 @@ export default {
 		}
   },
   methods: {
+    //获取教研室列表
+    getClass2() {
+      let params = {
+          oid: this.oid,
+      };
+      this.ajax
+          .get(this.$store.state.api + "selectTeacherOfficeBySchool", params)
+          .then((res) => {
+              this.TeachingOptions = res.data[0];
+              console.log('this.TeachingOptions',this.TeachingOptions);
+          })
+          .catch((err) => {
+              this.isLoading = false;
+              console.error(err);
+          });
+    },
     filterName(value, row, index) {
       let name = []
       for (var i = 0; i < row.array[index].json.answer2.length; i++) {
@@ -633,13 +704,28 @@ export default {
       this.isLoading = true;
       let params = {
         cid: this.cid,
-        cn: this.courseName
+        cn: this.courseName,
+        tim : !this.SubmitTime? '' : this.SubmitTime,
+        tea: this.TeachingValue
       };
       this.ajax
-        .get(this.$store.state.api + "getTestWorksNoPage", params)
+        .get(this.$store.state.api + "getTestWorksNoPageCopy", params)
         .then(async (res) => {
-          this.isLoading = false;
           this.testJson = res.data[0][0]
+          console.log('this.testJson',JSON.parse(JSON.stringify(this.testJson)));
+          if (this.testJson.juriP) {
+            let ajuri2 =  this.testJson.juri2.split (',');
+            let ajurip =  this.testJson.juriP.split (',');
+            let JData = ajuri2.reverse()
+            this.TeachingOptions = JData.map((key, index) => ({
+              id : key,
+              name: ajurip[index]
+            }));
+          }else{
+            this.getClass2()
+          }
+          // console.log('dddd',this.TeachingOptions);
+
           this.works = res.data[1]
           this.iscount = res.data[2][0].count
           this.pcount = res.data[3][0].count
@@ -778,6 +864,8 @@ export default {
           }
           this.testArray = testArray
           this.worksArray = array
+          this.isLoading = false;
+          
         })
         .catch((err) => {
           console.error(err);
@@ -1459,6 +1547,10 @@ export default {
           array.push(i)
         }
         return item.answer2 ? array[item.answer2] : ''
+    },
+    checkScreenSize() {
+      this.screenWidth = window.innerWidth;
+      this.isDesktop = this.screenWidth > 750; // 你可以根据需要调整这个阈值
     },
 		downloadFileType5(fileData,title="附件"){
 			let data = fileData;
@@ -1526,13 +1618,17 @@ export default {
 		},
   },
   beforeDestroy() {
-    document.getElementsByTagName('html')[0].style.overflow = ''
+    document.getElementsByTagName('html')[0].style.overflow = '';
+    window.removeEventListener("resize", this.checkScreenSize);
   },
   mounted() {
+    this.checkScreenSize();
+    window.addEventListener("resize", this.checkScreenSize);
     document.getElementsByTagName('html')[0].scrollTop = 0
     document.getElementsByTagName('html')[0].style.overflow = 'hidden'
     this.$nextTick(function () {
       this.getData();
+      // this.getClass2()
       this.changeHeight()
     });
   },

+ 20 - 2
src/components/pages/test/shareBox/index.vue

@@ -8,8 +8,9 @@
                     <span>{{ testJson.title }}</span>
                 </div>
                 <div class="info" >
+                    <!-- {{ reversedMessage }} -->
                     <span>表单范围:</span>
-                    <span>{{ testJson.juriP ? testJson.juriP : '所有人' }}</span>
+                    <span>{{ reversedMessage }}</span>
                 </div>
                 <div class="info" v-if="testJson && testJson.overtime">
                     <span>截止时间:</span>
@@ -72,6 +73,12 @@ export default {
         testJson: {
             type: Object
         },
+        TeachingValue: {
+            type: String
+        },
+        TeachName: {
+            type: Array
+        }
     },
     data() {
         return {
@@ -83,6 +90,15 @@ export default {
             isSuo: true
         };
     },
+    computed: {
+        reversedMessage() {
+            if (this.TeachingValue == '') {
+                return this.testJson.juriP ? this.testJson.juriP : '所有人'
+            }else{
+                return this.TeachName[0].name
+            }
+        }
+    },
     methods: {
         handleClose(done) {
             this.close();
@@ -150,10 +166,12 @@ export default {
             // }
             let params = {
                 id: this.testJson.courseId,
+                tea: this.TeachingValue
             };
             this.ajax
-                .get(this.$store.state.api + "getTestWorkShare", params)
+                .get(this.$store.state.api + "getTestWorkShareCopy", params)
                 .then((res) => {
+                    console.log('res.datares.datares.datares.datares.datares.data',res.data);
                     let parray = res.data[0]
                     let is = res.data[1]
                     this.noCount = parray.length - is.length

+ 7 - 5
src/components/pages/testStudent/view/component/course.vue

@@ -10,7 +10,7 @@
             </div>
             <div class="choices" v-if="checkJson.courses.length">
                 <div class="course" @click="openCourse()">
-                    <div class="banner">
+                    <div class="banner" :style=" isN==1? 'width:140px;height:90px;' : ''">
                         <div v-if="tid" class="isRate">已评分</div>
                         <img :src="courseDetail.cover" alt="">
                     </div>
@@ -18,25 +18,25 @@
                         <div class="c_c">
                             <span>课程名称:</span>
                             <el-tooltip :content="courseDetail.title" placement="top" effect="dark">
-                                <span>{{ courseDetail.title }}</span>
+                                <span :style=" isN==1? 'max-width:75px;' : ''">{{ courseDetail.title }}</span>
                             </el-tooltip>
                         </div>
                         <div class="c_c">
                             <span>课程类型:</span>
                             <span v-if="!courseDetail.name">{{ '暂无' }}</span>
                             <el-tooltip v-else :content="courseDetail.name" placement="top" effect="dark">
-                                <span>{{ courseDetail.name }}</span>
+                                <span :style=" isN==1? 'max-width:75px;' : ''">{{ courseDetail.name }}</span>
                             </el-tooltip>
                         </div>
                         <div class="c_c">
                             <span>创建人:</span>
-                            <span>{{ courseDetail.username }}</span>
+                            <span :style=" isN==1? 'max-width:75px;' : ''">{{ courseDetail.username }}</span>
                         </div>
                         <div class="c_c">
                             <span>协作者:</span>
                             <span v-if="!courseDetail.xieName">{{ '暂无' }}</span>
                             <el-tooltip v-else :content="courseDetail.xieName" placement="top" effect="dark">
-                                <span>{{ courseDetail.xieName }}</span>
+                                <span :style=" isN==1? 'max-width:75px;' : ''">{{ courseDetail.xieName }}</span>
                             </el-tooltip>
                         </div>
                     </div>
@@ -85,6 +85,8 @@ export default {
                 1: { name: '附件' },
             },
             userid: this.$route.query.userid,
+            isN: this.$route.query.isN,
+
             checkJson: undefined,
             progress: 0,
             isFinishSize: 0,

+ 4 - 2
src/components/pages/testStudent/view/component/eva.vue

@@ -8,8 +8,8 @@
             <div class="detail" v-if="checkJson.detail" v-html="checkJson.detail"
                 style="color: #00000099;margin-top: 5px;">
             </div>
-            <div class="choices">
-                <div class="score" :class="{active: (checkJson.answer2 || checkJson.answer2 === 0) && (checkJson.answer2 > index || checkJson.answer2 === index)}" @click="score(index)" v-for="(item, index) in (parseInt(checkJson.big) - parseInt(checkJson.small) + 1)" :key="index">{{ parseInt(checkJson.small) + index }}</div>
+            <div class="choices" :style=" isN==1? 'justify-content: space-around;width:100%' : ''">
+                <div class="score" :style=" isN==1? 'width:25px;height:25px;margin:0;' : ''" :class="{active: (checkJson.answer2 || checkJson.answer2 === 0) && (checkJson.answer2 > index || checkJson.answer2 === index)}" @click="score(index)" v-for="(item, index) in (parseInt(checkJson.big) - parseInt(checkJson.small) + 1)" :key="index">{{ parseInt(checkJson.small) + index }}</div>
             </div>
         </div>
     </div>
@@ -40,6 +40,8 @@ export default {
                 1: { name: '附件' },
             },
             userid: this.$route.query.userid,
+            isN: this.$route.query.isN,
+
             checkJson: undefined,
             progress: 0,
             isFinishSize: 0,

+ 7 - 7
src/components/pages/testStudent/view/preview.vue

@@ -39,14 +39,14 @@
           <div class="r_pub_button_retrun" @click="retrunCourse">返回</div>
         </div>
         <div class="step_box">
-          <div class="edit_top" :style="isN==1?'border-bottom:none;justify-content:space-between;padding:20px':''">
-						<div v-if="isN==1" class="edit_title">提交记录</div>
+          <div class="edit_top" :style="isN==1?'border-bottom:none;justify-content:space-between;padding:10px':''">
+						<div v-if="isN==1" class="edit_title"  :style=" isN==1? 'margin-left : 12px' : ''">提交记录</div>
             <div class="op_btn">
-							<el-button type="primary" size="small" @click="autoFill" v-if="(showAutoFillBtn && isN!=1)">智能填写</el-button>
-              <el-button type="primary" size="small" @click="refresh" v-if="isReset">刷新</el-button>
-              <el-button :type="isN!=1?'primary':'info'" size="small" @click="reset">重置</el-button>
-              <el-button type="primary" size="small" @click="save" v-if="(type != 3 && isN!=1)">保存</el-button>
-              <el-button type="primary" size="small" @click="publish">提交</el-button>
+							<el-button type="primary" :style=" isN==1? 'padding: 5px 10px;' : ''" size="small" @click="autoFill" v-if="(showAutoFillBtn && isN!=1)">智能填写</el-button>
+              <el-button type="primary" :style=" isN==1? 'padding: 5px 10px;' : ''" size="small" @click="refresh" v-if="isReset">刷新</el-button>
+              <el-button :type="isN!=1?'primary':'info'" :style=" isN==1? 'padding: 5px 10px;' : ''" size="small" @click="reset">重置</el-button>
+              <el-button type="primary" :style=" isN==1? 'padding: 5px 10px;' : ''" size="small" @click="save" v-if="(type != 3 && isN!=1)">保存</el-button>
+              <el-button type="primary" :style=" isN==1? 'padding: 5px 10px;' : ''" size="small" @click="publish">提交</el-button>
             </div>
           </div>
           <topicVue :cJson.sync="cJson" :title="title" :brief="brief" ref="topicVue" v-if="!loading"

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác