SanHQin 1 年之前
父節點
當前提交
c3649e24dd
共有 27 個文件被更改,包括 2469 次插入0 次删除
  1. 二進制
      src/assets/icon/classroomObservation/ai.png
  2. 二進制
      src/assets/icon/classroomObservation/aiImage.png
  3. 二進制
      src/assets/icon/classroomObservation/avatar.png
  4. 二進制
      src/assets/icon/classroomObservation/back.png
  5. 二進制
      src/assets/icon/classroomObservation/close.png
  6. 二進制
      src/assets/icon/classroomObservation/close1.png
  7. 二進制
      src/assets/icon/classroomObservation/del.png
  8. 二進制
      src/assets/icon/classroomObservation/edit.png
  9. 二進制
      src/assets/icon/classroomObservation/file.png
  10. 二進制
      src/assets/icon/classroomObservation/foldIcon.png
  11. 二進制
      src/assets/icon/classroomObservation/ice.png
  12. 二進制
      src/assets/icon/classroomObservation/right.png
  13. 二進制
      src/assets/icon/classroomObservation/six.png
  14. 二進制
      src/assets/icon/classroomObservation/tape.png
  15. 152 0
      src/components/pages/classroomObservation/components/analysisItem.vue
  16. 263 0
      src/components/pages/classroomObservation/components/baseMessage.vue
  17. 80 0
      src/components/pages/classroomObservation/components/chatArea.vue
  18. 281 0
      src/components/pages/classroomObservation/components/currencyAnalysis.vue
  19. 281 0
      src/components/pages/classroomObservation/components/extendAnalysis.vue
  20. 108 0
      src/components/pages/classroomObservation/components/messageArea.vue
  21. 281 0
      src/components/pages/classroomObservation/components/pdf.vue
  22. 281 0
      src/components/pages/classroomObservation/components/scienceAnalysis.vue
  23. 137 0
      src/components/pages/classroomObservation/components/startPage.vue
  24. 284 0
      src/components/pages/classroomObservation/components/tape.vue
  25. 62 0
      src/components/pages/classroomObservation/components/transcription.vue
  26. 250 0
      src/components/pages/classroomObservation/index.vue
  27. 9 0
      src/router/index.js

二進制
src/assets/icon/classroomObservation/ai.png


二進制
src/assets/icon/classroomObservation/aiImage.png


二進制
src/assets/icon/classroomObservation/avatar.png


二進制
src/assets/icon/classroomObservation/back.png


二進制
src/assets/icon/classroomObservation/close.png


二進制
src/assets/icon/classroomObservation/close1.png


二進制
src/assets/icon/classroomObservation/del.png


二進制
src/assets/icon/classroomObservation/edit.png


二進制
src/assets/icon/classroomObservation/file.png


二進制
src/assets/icon/classroomObservation/foldIcon.png


二進制
src/assets/icon/classroomObservation/ice.png


二進制
src/assets/icon/classroomObservation/right.png


二進制
src/assets/icon/classroomObservation/six.png


二進制
src/assets/icon/classroomObservation/tape.png


+ 152 - 0
src/components/pages/classroomObservation/components/analysisItem.vue

@@ -0,0 +1,152 @@
+<template>
+	<div class="analysisItem">
+		<div class="ai-header">
+			<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.title}}</span>
+			</div>
+			<div class="ai-h-right">
+				<span class="ai-h-r-icon1" @click.stop="backLeft()"></span>
+				<span class="ai-h-r-icon2" @click.stop="backRight()"></span>
+				<span class="ai-h-r-icon3" @click.stop="editBtn()"></span>
+				<span class="ai-h-r-icon4" @click.stop="delBtn()"></span>
+			</div>
+		</div>
+		<div class="ai-main" v-if="openItem">
+			<div class="ai-m-html" v-html="data.content" v-for="i in 4" :key="i"></div>
+		</div>
+	</div>
+</template>
+
+<script>
+export default {
+	props:{
+		data:{
+			type:Object,
+			default:()=>{
+				return {}
+			}
+		}
+	},
+	data(){
+		return{
+			openItem:false
+		}
+	},
+	methods:{
+		changeOpenItem(newValue){
+			this.openItem = newValue;
+		},
+		backLeft(){
+			this.$message.info("回退左")
+		},
+		backRight(){
+			this.$message.info("回退右")
+		},
+		editBtn(){
+			this.$message.info("编辑")
+		},
+		delBtn(){
+			this.$message.info("删除")
+		}
+	}
+}
+</script>
+
+<style scoped>
+.analysisItem{
+	width: 100%;
+	height: auto;
+	
+	margin:10px 0px;
+	
+	padding-right: 40px;
+	box-sizing: border-box;
+}
+.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: 25px;
+	height: 25px;
+	background: url("../../../../assets/icon/classroomObservation/right.png") no-repeat;
+	background-size: 100% 100%;
+	margin-right: 10px;
+	transition: .3s;
+}
+
+.ai-h-l-iconActive{
+	transform: rotate(90deg);
+}
+.ai-h-l-text{
+	font-size: 16px;
+}
+
+.ai-h-right{
+	width: auto;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: space-around;
+	position: relative;
+}
+
+.ai-h-right>span{
+	width: 25px;
+	height: 25px;
+	background-size: 100% 100%;
+	margin: 0 10px;
+	cursor: pointer;
+}
+
+.ai-h-r-icon1{
+	background: url("../../../../assets/icon/classroomObservation/back.png");
+	/* 镜像 */
+	transform: scaleX(-1);
+}
+
+.ai-h-r-icon2{
+	background: url("../../../../assets/icon/classroomObservation/back.png");
+}
+
+.ai-h-r-icon3{
+	background: url("../../../../assets/icon/classroomObservation/edit.png");
+}
+
+
+.ai-h-r-icon4{
+	background: url("../../../../assets/icon/classroomObservation/del.png");
+	position: absolute;
+	right: -40px;
+	display: none;
+}
+
+.analysisItem:hover .ai-h-r-icon4{
+	display: block;
+}
+
+.ai-main{
+	width: 100%;
+	height: 300px;
+	background-color: white;
+	border-radius: 0 0 5px 5px;
+	overflow: auto;
+	box-sizing: border-box;
+	padding: 10px 20px;
+
+}
+</style>

+ 263 - 0
src/components/pages/classroomObservation/components/baseMessage.vue

@@ -0,0 +1,263 @@
+<template>
+	<div class="message">
+		<div class="m-header">
+			<span class="m-h-icon"></span>
+			<span class="m-h-title">{{ title }}</span>
+		</div>
+		<div class="m-main">
+			<div class="m-m-formItem" style="width: 63%;">
+				<div class="m-m-fi-label">课程名称</div>
+				<div class="m-m-fi-input" >
+					<el-input  v-model="from.courseName" placeholder="请输入课程名称"></el-input>
+				</div>
+			</div>
+
+			<div class="m-m-formItem" style="width: 33%;">
+				<div class="m-m-fi-label">授课老师</div>
+				<div class="m-m-fi-input" >
+					<el-input v-model="from.teacherName" placeholder="请输入授课老师"></el-input>
+				</div>
+			</div>
+
+			<div class="m-m-formItem" style="width: 23%;">
+				<div class="m-m-fi-label">年级</div>
+				<div class="m-m-fi-input" >
+					<el-select v-model="from.grade" placeholder="请选择年级">
+						<el-option v-for="(item,index) in gradeList" :key="index" :value="item.value" :label="item.label"></el-option>
+					</el-select>
+				</div>
+			</div>
+
+			<div class="m-m-formItem" style="width: 23%;">
+				<div class="m-m-fi-label">科目</div>
+				<div class="m-m-fi-input" >
+					<el-select v-model="from.subjectList" placeholder="请选择年级">
+						<el-option v-for="(item,index) in gradeList" :key="index" :value="item.value" :label="item.label"></el-option>
+					</el-select>
+				</div>
+			</div>
+
+			<div class="m-m-formItem" style="width: 24%;">
+				<div class="m-m-fi-label">班级</div> 
+				<div class="m-m-fi-input" >
+					<el-input v-model="from.class" placeholder="请输入班级"></el-input>
+				</div>
+			</div>
+
+			<div class="m-m-formItem" style="width: 23.6%;">
+				<div class="m-m-fi-label">学生人数</div>
+				<div class="m-m-fi-input" >
+					<el-input v-model.number="from.studentNum" placeholder="请输入学生人数"></el-input>
+				</div>
+			</div>
+			<div class="m-m-formImage">
+				<div class="m-m-fi-imageList">
+					<div class="m-m-fi-imageItem" v-for="item in imageList" :key="item.id" @click.stop="showImage(item)">
+						<span class="m-m-fi-i-icon"></span>
+						<div class="m-m-fi-i-text">{{ item.fileName }}</div>
+					</div>
+					<!-- 图片区域 -->
+				</div>
+				<div class="m-m-fi-btn" @click.stop="addImage()">添加课堂图片</div>
+			</div>
+
+
+			<!-- <el-form :inline="true" :model="form">
+				<el-form-item label="课程名称" >
+					<el-input v-model="from.courseName" placeholder="请输入课程名称"></el-input>
+				</el-form-item>
+				<el-form-item label="授课老师">
+					<el-input v-model="from.teacherName" placeholder="请输入授课老师"></el-input>
+				</el-form-item>
+				<el-form-item label="年级">
+					<el-select v-model="from.grade" placeholder="请选择年级">
+						<el-option v-for="(item,index) in gradeList" :key="index" :value="item.value" :label="item.label"></el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="科目">
+					<el-select v-model="from.subjectList" placeholder="请选择年级">
+						<el-option v-for="(item,index) in gradeList" :key="index" :value="item.value" :label="item.label"></el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="班级">
+					<el-input v-model="from.class" placeholder="请输入班级"></el-input>
+				</el-form-item>
+				<el-form-item label="学生人数">
+					<el-input v-model.number="from.studentNum" placeholder="请输入学生人数"></el-input>
+				</el-form-item>
+			</el-form> -->
+		</div>
+	</div>
+</template>
+
+<script>
+export default {
+	data(){
+		return{
+			title:"基本信息设置",
+			from:{
+				courseName:"",
+				teacherName:"",
+				grade:"",
+				subject:"",
+				class:"",
+				studentNum:0,
+			},
+			imageList:[
+				{id:0,url:"",fileName:"课堂图片1.png"},
+				{id:1,url:"",fileName:"课堂图片2.png"},
+				{id:2,url:"",fileName:"课堂图片3.png"},
+				{id:3,url:"",fileName:"课堂图片4.png"},
+				{id:4,url:"",fileName:"课堂图片5.png"},
+				{id:5,url:"",fileName:"课堂图片6.png"},
+
+			],
+			gradeList:[
+				{value:"一年级",label:"一年级"},
+				{value:"二年级",label:"二年级"},
+				{value:"三年级",label:"三年级"},
+				{value:"四年级",label:"四年级"},
+				{value:"五年级",label:"五年级"},
+				{value:"六年级",label:"六年级"},
+				{value:"七年级",label:"七年级"},
+			],
+			subjectList:[
+				{value:"科目一",label:"科目一"},
+				{value:"科目二",label:"科目二"},
+				{value:"科目三",label:"科目三"},
+				{value:"科目四",label:"科目四"},
+				{value:"科目五",label:"科目五"},
+				{value:"科目六",label:"科目六"},
+				{value:"科目七",label:"科目七"},
+				{value:"科目八",label:"科目八"},
+			],
+
+		}
+	},
+	methods:{
+		addImage(){
+			this.$message.info("添加课堂图片")
+		},
+		showImage(item){
+			this.$message.info(`点击了图片${item.fileName}`)
+		}
+	}
+}
+</script>
+
+<style scoped>
+.message{
+	width: 100%;
+	height: auto;
+}
+
+.m-header{
+	width: 100%;
+	height: 50px;
+	display: flex;
+	align-items: center;
+}
+
+.m-h-icon{
+	width: 23px;
+	height: 23px;
+	background: url("../../../../assets/icon/classroomObservation/right.png") no-repeat;
+	background-size: 100% 100%;
+	margin-right: 5px;
+}
+
+.m-h-title{
+	font-size: 18px;
+}
+
+.m-main{
+	width: calc(100% - 40px);
+	height: auto;
+	border-radius: 5px;
+	background-color: #FFFFFF;
+	padding: 20px 20px 0 20px;
+	box-sizing: border-box;
+	display: flex;
+	flex-wrap: wrap;
+}
+
+.m-m-formItem{
+	width: 100%;
+	height: auto;
+	display: flex;
+	align-items: center;
+	margin-right: 10px;
+	margin-bottom: 20px;
+}
+
+.m-m-fi-input{
+	width: 100%;
+}
+
+.m-m-fi-label{
+	font-size: 16px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 0 10px;
+	text-wrap: nowrap;
+}
+
+.m-m-formImage{
+	width: 100%;
+	height: auto;
+	margin-bottom: 20px;
+	display: flex;
+	justify-content: space-between;
+	box-sizing: border-box;
+	padding: 0 25px 0 10px;
+}
+
+.m-m-fi-imageList{
+	flex: 1;
+	height: auto;
+	margin-right: 20px;
+	display: flex;
+	flex-wrap: wrap;
+}
+
+.m-m-fi-imageItem{
+	width: auto;
+	height: auto;
+	margin-right:10px;
+	margin-bottom:10px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 5px 10px;
+	font-size: 14px;
+	cursor: pointer;
+}
+
+.m-m-fi-i-icon{
+	width: 20px;
+	height: 20px;
+	background: url("../../../../assets/icon/classroomObservation/file.png") no-repeat;
+	background-size: 100% 100%;
+	margin-right: 5px;
+
+}
+
+.m-m-fi-btn{
+	width: auto;
+	height: 35px;
+	box-sizing: border-box;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	border-radius: 18px;
+	font-size: 14px;
+	border: solid 1px #C5C5C5;
+	background-color: white;
+	cursor: pointer;
+	padding: 0 10px;
+}
+
+</style>

文件差異過大導致無法顯示
+ 80 - 0
src/components/pages/classroomObservation/components/chatArea.vue


+ 281 - 0
src/components/pages/classroomObservation/components/currencyAnalysis.vue

@@ -0,0 +1,281 @@
+<template>
+	<div class="analysis">
+		<div class="a-header">
+			<div class="a-h-left">
+				<span class="a-h-l-icon"></span>
+				<span class="a-h-l-title">{{ title }}</span>
+			</div>
+			<div class="a-h-right">
+				<div class="a-h-r-btn" @click.stop="addTemplate()">添加模块</div>
+			</div>
+		</div>
+		<div class="a-main">
+			<analysisItem v-for="item in analysisList" :key="item.id" :data="item"/>
+		</div>
+		<div v-if="showDialog == true" class="a-dialog" v-el-drag-dialog>
+      <div class="a-d-top">
+       <div class="a-d-t-left">
+				<div :style="tagIndex==index?'background:white':''" class="a-d-t-l-item" v-for="(item,index) in dialogTagList" :key="item.id" @click.stop="tagIndex=index">
+					{{ item.name }}
+				</div>
+			 </div>
+			 <div class="a-d-t-right">
+				<span @click.stop="showDialog=false">×</span>
+			 </div>
+      </div>
+      <div class="a-d-box">
+				<div class="a-d-b-item" v-for="item in 24" :key="item">
+					<div class="a-d-b-i-top">
+						<img :src="require('../../../../assets/icon/classroomObservation/avatar.png')">
+						<div>学生问答情况</div>
+						<div class="a-d-b-i-t-btn">添加</div>
+					</div>
+					<div class="a-d-b-i-bottom">使用IRE模型分析学生回答情况</div>
+				</div>
+      </div>
+    </div>
+	</div>
+</template>
+
+<script>
+import analysisItem from './analysisItem'
+export default {
+	components:{
+		analysisItem
+	},
+	data(){
+		return{
+			title:"通用课堂分析",
+			showDialog:false,
+			tagIndex:0,
+			dialogTagList:[
+				{id:1,name:"通用课堂分析"},
+				{id:2,name:"学科课堂分析"},
+				{id:3,name:"扩展分析"},
+			],
+			dialogTagDataList:[
+				[],
+				[],
+				[],
+			],
+			analysisList:[
+				{id:1,title:"OMO 智慧课堂分析",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+				{id:2,title:"加涅教学阶段九事件",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+				{id:3,title:"课堂时间分配",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+				{id:4,title:"学生问答情况",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+			]
+		}
+	},
+	methods:{
+		addTemplate(){
+			this.showDialog = true;
+		}
+	}
+}
+</script>
+
+<style scoped>
+.analysis{
+	width: 100%;
+	height: auto;
+}
+
+.a-header{
+	width: 100%;
+	height: 50px;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	box-sizing: border-box;
+	padding-right: 40px;
+}
+
+.a-h-left{
+	display: flex;
+	align-items: center;
+}
+
+.a-h-l-icon{
+	width: 23px;
+	height: 23px;
+	background: url("../../../../assets/icon/classroomObservation/right.png") no-repeat;
+	background-size: 100% 100%;
+	margin-right: 5px;
+}
+
+.a-h-l-title{
+	font-size: 18px;
+}
+
+.a-h-r-btn{
+	font-size: 14px;
+	height: 35px;
+	width: auto;
+	box-sizing: border-box;
+	padding: 0 20px;
+	border: solid 1px #C5C5C5;
+	border-radius: 18px;
+	cursor: pointer;
+	background-color: white;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.a-main{
+	width: calc(100%);
+	height: auto;
+}
+
+.a-dialog {
+  position: fixed;
+  width: 60%;
+  height: 60%;
+  min-height: 600px;
+  box-shadow: 0px 0 8px 0px #555555;
+  border-radius: 15px;
+  z-index: 999;
+  left: 30%;
+  top: 50%;
+  margin: -18% 0 0 -300px;
+	overflow: hidden;
+}
+
+.a-d-top{
+  background: #ADADAD;
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  justify-content: space-between;
+  height: 40px;
+  border-radius: 15px 15px 0 0;
+  user-select: none;
+}
+
+.a-d-t-left{
+	width: calc(100% - 40px);
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: flex-start;
+	box-sizing: border-box;
+	padding-left: 5px;
+}
+
+.a-d-t-l-item{
+	width: auto;
+	height: 90%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	padding: 0 10px;
+	border-radius: 10px;
+	background-color: #D4D9DA;
+	margin-right: 3px;
+	cursor: pointer;
+}
+
+.a-d-t-l-item:hover{
+	background-color: white
+}
+
+.a-d-t-right{
+	width: 40px;
+	height: 40px;
+	margin-right: 10px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	color: black !important;
+}
+
+.a-d-t-right>span{
+	width: 25px;
+	height: 25px;
+	border-radius: 25px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	/* align-items: center; */
+	font-size: 22px;
+	color: #fff;
+	background-color: #ADADAD;
+	cursor: pointer;
+	background-color: #E6E6E6;
+	color: #ADADAD;
+}
+
+.a-d-box{
+	width: 100%;
+	height: calc(100% - 40px);
+	background-color: #F0F2F5;
+	overflow: auto;
+}
+
+.a-d-b-item{
+	width: 23%;
+	height: 100px;
+	background-color:#D9D9D9;
+	border-radius: 10px;
+	margin: 10px;
+	padding: 10px;
+	float: left;
+	box-sizing: border-box
+}
+.a-d-b-i-top{
+	width: 100%;
+	height: 50%;
+	display: flex;
+	justify-content: space-between;
+}
+.a-d-b-i-top>img{
+	width: 35px;
+	height: 35px;
+}
+/* .a-d-b-i-top>div{ */
+	/* width: auto;
+	height: 35px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin-left: 10px; */
+/* } */
+
+.a-d-b-i-top>div:nth-of-type(1){
+	width: calc(100% - 90px);
+	height: 35px;
+	display: flex;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 0 10px;
+	/* 字体溢出显示... */
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+
+}
+
+.a-d-b-i-bottom{
+	width: 100%;
+	height: 50%;
+	display: flex;
+	font-size: 14px;
+	align-items: center;
+}
+
+.a-d-b-i-t-btn{
+	font-size: 14px;
+	height: 30px;
+	position: relative;
+	top: 5px;
+	box-sizing: border-box;
+	padding: 0 10px;
+	background-color: #F3F3F3;
+	border-radius: 5px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+}
+</style>

+ 281 - 0
src/components/pages/classroomObservation/components/extendAnalysis.vue

@@ -0,0 +1,281 @@
+<template>
+	<div class="analysis">
+		<div class="a-header">
+			<div class="a-h-left">
+				<span class="a-h-l-icon"></span>
+				<span class="a-h-l-title">{{ title }}</span>
+			</div>
+			<div class="a-h-right">
+				<div class="a-h-r-btn" @click.stop="addTemplate()">添加模块</div>
+			</div>
+		</div>
+		<div class="a-main">
+			<analysisItem v-for="item in analysisList" :key="item.id" :data="item"/>
+		</div>
+		<div v-if="showDialog == true" class="a-dialog" v-el-drag-dialog>
+      <div class="a-d-top">
+       <div class="a-d-t-left">
+				<div :style="tagIndex==index?'background:white':''" class="a-d-t-l-item" v-for="(item,index) in dialogTagList" :key="item.id" @click.stop="tagIndex=index">
+					{{ item.name }}
+				</div>
+			 </div>
+			 <div class="a-d-t-right">
+				<span @click.stop="showDialog=false">×</span>
+			 </div>
+      </div>
+      <div class="a-d-box">
+				<div class="a-d-b-item" v-for="item in 24" :key="item">
+					<div class="a-d-b-i-top">
+						<img :src="require('../../../../assets/icon/classroomObservation/avatar.png')">
+						<div>学生问答情况</div>
+						<div class="a-d-b-i-t-btn">添加</div>
+					</div>
+					<div class="a-d-b-i-bottom">使用IRE模型分析学生回答情况</div>
+				</div>
+      </div>
+    </div>
+	</div>
+</template>
+
+<script>
+import analysisItem from './analysisItem'
+export default {
+	components:{
+		analysisItem
+	},
+	data(){
+		return{
+			title:"扩展分析",
+			showDialog:false,
+			tagIndex:2,
+			dialogTagList:[
+				{id:1,name:"通用课堂分析"},
+				{id:2,name:"学科课堂分析"},
+				{id:3,name:"扩展分析"},
+			],
+			dialogTagDataList:[
+				[],
+				[],
+				[],
+			],
+			analysisList:[
+				{id:1,title:"OMO 智慧课堂分析",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+				{id:2,title:"加涅教学阶段九事件",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+				{id:3,title:"课堂时间分配",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+				{id:4,title:"学生问答情况",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+			]
+		}
+	},
+	methods:{
+		addTemplate(){
+			this.showDialog = true;
+		}
+	}
+}
+</script>
+
+<style scoped>
+.analysis{
+	width: 100%;
+	height: auto;
+}
+
+.a-header{
+	width: 100%;
+	height: 50px;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	box-sizing: border-box;
+	padding-right: 40px;
+}
+
+.a-h-left{
+	display: flex;
+	align-items: center;
+}
+
+.a-h-l-icon{
+	width: 23px;
+	height: 23px;
+	background: url("../../../../assets/icon/classroomObservation/right.png") no-repeat;
+	background-size: 100% 100%;
+	margin-right: 5px;
+}
+
+.a-h-l-title{
+	font-size: 18px;
+}
+
+.a-h-r-btn{
+	font-size: 14px;
+	height: 35px;
+	width: auto;
+	box-sizing: border-box;
+	padding: 0 20px;
+	border: solid 1px #C5C5C5;
+	border-radius: 18px;
+	cursor: pointer;
+	background-color: white;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.a-main{
+	width: calc(100%);
+	height: auto;
+}
+
+.a-dialog {
+  position: fixed;
+  width: 60%;
+  height: 60%;
+  min-height: 600px;
+  box-shadow: 0px 0 8px 0px #555555;
+  border-radius: 15px;
+  z-index: 999;
+  left: 30%;
+  top: 50%;
+  margin: -18% 0 0 -300px;
+	overflow: hidden;
+}
+
+.a-d-top{
+  background: #ADADAD;
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  justify-content: space-between;
+  height: 40px;
+  border-radius: 15px 15px 0 0;
+  user-select: none;
+}
+
+.a-d-t-left{
+	width: calc(100% - 40px);
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: flex-start;
+	box-sizing: border-box;
+	padding-left: 5px;
+}
+
+.a-d-t-l-item{
+	width: auto;
+	height: 90%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	padding: 0 10px;
+	border-radius: 10px;
+	background-color: #D4D9DA;
+	margin-right: 3px;
+	cursor: pointer;
+}
+
+.a-d-t-l-item:hover{
+	background-color: white
+}
+
+.a-d-t-right{
+	width: 40px;
+	height: 40px;
+	margin-right: 10px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	color: black !important;
+}
+
+.a-d-t-right>span{
+	width: 25px;
+	height: 25px;
+	border-radius: 25px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	/* align-items: center; */
+	font-size: 22px;
+	color: #fff;
+	background-color: #ADADAD;
+	cursor: pointer;
+	background-color: #E6E6E6;
+	color: #ADADAD;
+}
+
+.a-d-box{
+	width: 100%;
+	height: calc(100% - 40px);
+	background-color: #F0F2F5;
+	overflow: auto;
+}
+
+.a-d-b-item{
+	width: 23%;
+	height: 100px;
+	background-color:#D9D9D9;
+	border-radius: 10px;
+	margin: 10px;
+	padding: 10px;
+	float: left;
+	box-sizing: border-box
+}
+.a-d-b-i-top{
+	width: 100%;
+	height: 50%;
+	display: flex;
+	justify-content: space-between;
+}
+.a-d-b-i-top>img{
+	width: 35px;
+	height: 35px;
+}
+/* .a-d-b-i-top>div{ */
+	/* width: auto;
+	height: 35px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin-left: 10px; */
+/* } */
+
+.a-d-b-i-top>div:nth-of-type(1){
+	width: calc(100% - 90px);
+	height: 35px;
+	display: flex;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 0 10px;
+	/* 字体溢出显示... */
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+
+}
+
+.a-d-b-i-bottom{
+	width: 100%;
+	height: 50%;
+	display: flex;
+	font-size: 14px;
+	align-items: center;
+}
+
+.a-d-b-i-t-btn{
+	font-size: 14px;
+	height: 30px;
+	position: relative;
+	top: 5px;
+	box-sizing: border-box;
+	padding: 0 10px;
+	background-color: #F3F3F3;
+	border-radius: 5px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+}
+</style>

+ 108 - 0
src/components/pages/classroomObservation/components/messageArea.vue

@@ -0,0 +1,108 @@
+<template>
+	<div class="messageArea">
+		<div class="m-operation">
+			<div class="m-o-btn" @click.stop="useAnalysisTemplate()">使用分析模板</div>
+			<div class="m-o-btn" @click.stop="saveAsTemplate()">另存为模板</div>
+			<div class="m-o-switch">
+				<span class="m-o-s-text" @click.stop="changeShowBrief(!showBrief)">显示模块简介</span>
+				<el-switch
+				  v-model="showBrief"
+				  active-color="#3681FC"
+				  inactive-color="#b2bfc3">
+				</el-switch>
+			</div>
+		</div>
+		<div class="ma-main">
+			<baseMessage/>
+
+			<currencyAnalysis/>
+
+			<scienceAnalysis/>
+
+			<extendAnalysis/>
+			<!-- <div style="height: 10000px;"></div> -->
+		</div>
+	</div>
+</template>
+
+<script>
+import baseMessage from './baseMessage.vue';	//基本信息
+import currencyAnalysis from './currencyAnalysis.vue';//通用课堂分析
+import scienceAnalysis from './scienceAnalysis.vue';//科学课堂分析
+import extendAnalysis from './extendAnalysis.vue';//扩展分析
+export default {
+	components:{
+		baseMessage,
+		currencyAnalysis,
+		scienceAnalysis,
+		extendAnalysis
+	},
+	data(){
+		return{
+			showBrief:true,//是否显示模块简介
+		}
+	},
+	methods:{
+		// 切换显示模板简介
+		changeShowBrief(newValue){
+			this.showBrief = newValue;
+		},
+		// 使用分析模板
+		useAnalysisTemplate(){
+			this.$message.info("使用分析模板")
+		},
+		//另存为模板
+		saveAsTemplate(){
+			this.$message.info("另存为模板")
+		}
+	}
+}
+</script>
+
+<style scoped>
+.messageArea{
+	width: 100%;
+	height: 100%;
+	box-sizing: border-box;
+	padding: 20px 10px;
+}
+.m-operation{
+	width: 100%;
+	height: 30px;
+	display: flex;
+	justify-content: flex-end;
+	align-items: center;
+	font-size: 14px;
+	box-sizing: border-box;
+	padding-right: 30px;
+	margin-bottom: 10px;
+}
+.m-o-btn{
+	width: auto;
+	height: 33px;
+	padding: 0 12px;
+	background-color: #FFFFFF;
+	box-sizing: border-box;
+	border: solid 1px #BDBDBD;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin-right: 10px;
+	border-radius: 17px;
+	cursor: pointer;
+}
+.m-o-switch{
+	display: flex;
+	align-items: center;
+	margin-right: 10px;
+}
+.m-o-s-text{
+	margin-right: 4px;
+	cursor: pointer;
+}
+.ma-main{
+	width: 100%;
+	height: calc(100vh - 173px);
+	overflow: auto;
+}
+</style>

+ 281 - 0
src/components/pages/classroomObservation/components/pdf.vue

@@ -0,0 +1,281 @@
+<template>
+  <div class="pdf">
+    <div class="show">
+      <pdf
+        ref="pdf"
+        :src="pdfUrl"
+        :page="pageNum"
+        :rotate="pageRotate"
+        @password="password"
+        @progress="loadedRatio = $event"
+        @page-loaded="pageLoaded($event)"
+        @num-pages="pageTotalNum = $event"
+        @error="pdfError($event)"
+        @link-clicked="page = $event"
+      ></pdf>
+    </div>
+
+    <!-- <div class="pdf_footer">
+      <div class="info">
+        <div>当前页数/总页数:{{pageNum}}/{{pageTotalNum}}</div>
+      </div>
+      <div class="operate">
+        <div class="btn" @click.stop="prePage">上一页</div>
+        <div class="btn" @click.stop="nextPage">下一页</div>
+      </div>
+    </div>-->
+  </div>
+</template>
+
+<script>
+import pdf from "vue-pdf";
+export default {
+  name: "vue_pdf_preview",
+  props: {
+    // 当前pdf路径
+    pdfUrl: {
+      type: String,
+      default:
+        "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/0629%E5%AE%9E%E6%97%B6%E8%AF%BE%E5%A0%82%E6%A8%A1%E6%8B%9F%E6%BC%94%E7%A4%BA%E8%AF%BE%E4%BB%B61656920880446.pdf",
+    },
+    ppage: {
+      type: Number,
+      default: 1,
+    },
+  },
+  components: {
+    pdf,
+  },
+  data() {
+    return {
+      // 总页数
+      pageTotalNum: 1,
+      // 当前页数
+      pageNum: 1,
+      // 加载进度
+      loadedRatio: 0,
+      // 页面加载完成
+      curPageNum: 0,
+      // 放大系数 默认百分百
+      scale: 69,
+      // 旋转角度 ‘90’的倍数才有效
+      pageRotate: 0,
+      // 单击内部链接时触发 (目前我没有遇到使用场景)
+      page: 0,
+      loading: null,
+    };
+  },
+  watch: {
+    ppage(val) {
+      this.pageNum = val;
+    },
+    pageTotalNum(val) {
+      if (val) {
+        this.loading.close();
+        // this.$parent.setData();
+        this.$parent.getRealTimeClass();
+      }
+      this.$emit("getPageTotal", val);
+    },
+  },
+  computed: {},
+  created() {},
+  mounted() {
+    this.loading = this.$loading.service({
+      background: "rgba(255, 255, 255, 0.7)",
+      target: document.querySelector(".pdf"),
+    });
+    this.pageNum = this.ppage;
+    let dwidth = document.body.offsetWidth;
+    let cwidth = document.getElementsByClassName("pdf")[0].offsetHeight * 1.77;
+    let owidth = "";
+    if (cwidth > dwidth) {
+      owidth = dwidth + "px";
+    } else {
+      owidth = cwidth + "px";
+    }
+    var a = document.getElementsByClassName("pdf")[0].offsetWidth;
+    let _this = this;
+    this.$refs.pdf.$el.style.width = owidth;
+    this.$emit("getWidth", owidth);
+    window.addEventListener("resize", () => {
+      dwidth = document.body.offsetWidth;
+      cwidth = document.getElementsByClassName("pdf")[0].offsetHeight * 1.77;
+      if (cwidth > dwidth) {
+        owidth = dwidth + "px";
+      } else {
+        owidth = cwidth + "px";
+      }
+      this.$refs.pdf.$el.style.width = owidth;
+      this.$emit("getWidth", owidth);
+    });
+  },
+  methods: {
+    //下载PDF
+    fileDownload(data, fileName) {
+      let blob = new Blob([data], {
+        //type类型后端返回来的数据中会有,根据自己实际进行修改
+        type: "application/pdf;charset-UTF-8",
+      });
+      let filename = fileName || "pdf.pdf";
+      if (typeof window.navigator.msSaveBlob !== "undefined") {
+        window.navigator.msSaveBlob(blob, filename);
+      } else {
+        var blobURL = window.URL.createObjectURL(blob);
+        // 创建隐藏<a>标签进行下载
+        var tempLink = document.createElement("a");
+        tempLink.style.display = "none";
+        tempLink.href = blobURL;
+        tempLink.setAttribute("download", filename);
+        if (typeof tempLink.download === "undefined") {
+          tempLink.setAttribute("target", "_blank");
+        }
+        document.body.appendChild(tempLink);
+        tempLink.click();
+        document.body.removeChild(tempLink);
+        window.URL.revokeObjectURL(blobURL);
+      }
+    },
+
+    //放大
+    scaleD() {
+      this.scale += 5;
+      this.$refs.pdf.$el.style.width = parseInt(this.scale) + "%";
+    },
+
+    //缩小
+    scaleX() {
+      // scale 是百分百展示 不建议缩放
+      if (this.scale == 100) {
+        return;
+      }
+      this.scale += -5;
+      console.log(parseInt(this.scale) + "%");
+      this.$refs.pdf.$el.style.width = parseInt(this.scale) + "%";
+    },
+    // 切换上一页
+    prePage() {
+      var p = this.pageNum;
+      p = p > 1 ? p - 1 : this.pageTotalNum;
+      this.pageNum = p;
+      // this.getPage(p);
+    },
+    // 切换下一页
+    nextPage() {
+      var p = this.pageNum;
+      p = p < this.pageTotalNum ? p + 1 : 1;
+      this.pageNum = p;
+      // this.getPage(p);
+    },
+    // 顺时针选中角度
+    clock() {
+      this.pageRotate += 90;
+    },
+    // 逆时针旋转角度
+    counterClock() {
+      this.pageRotate -= 90;
+    },
+    // pdf 有密码 则需要输入秘密
+    password(updatePassword, reason) {
+      updatePassword(prompt('password is "test"'));
+      console.log("...reason...");
+      console.log(reason);
+      console.log("...reason...");
+    },
+    // 页面加载成功  当前页数
+    pageLoaded(e) {
+      this.$emit("current", e);
+      this.curPageNum = e;
+    },
+    // 异常监听
+    pdfError(error) {
+      console.error(error);
+    },
+    // 打印所有
+    pdfPrintAll() {
+      this.$refs.pdf.print();
+    },
+    // 打印 第一页和第二页
+    pdfPrint() {
+      // 第一个参数 文档打印的分辨率
+      // 第二个参数 文档打印的页数
+      this.$refs.pdf.print(100, [1, 2]);
+    },
+    // 获取当前页面pdf的文字信息内容
+    logContent() {
+      this.$refs.pdf.pdf.forEachPage(function (page) {
+        return page.getTextContent().then(function (content) {
+          let text = content.items.map((item) => item.str);
+          let allStr = content.items.reduce(
+            (initVal, item) => (initVal += item.str),
+            ""
+          );
+          console.log(allStr); // 内容字符串
+          console.log(text); // 内容数组
+        });
+      });
+    },
+  },
+};
+</script>
+
+<style scoped>
+.pdf {
+  height: 100%;
+  position: relative;
+  box-sizing: border-box;
+}
+.pdf .show {
+  overflow: auto;
+  margin: auto;
+  width: 100%;
+  height: calc(100%);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.pdf .pdf_footer {
+  position: absolute;
+  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 .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;
+}
+</style>

+ 281 - 0
src/components/pages/classroomObservation/components/scienceAnalysis.vue

@@ -0,0 +1,281 @@
+<template>
+	<div class="analysis">
+		<div class="a-header">
+			<div class="a-h-left">
+				<span class="a-h-l-icon"></span>
+				<span class="a-h-l-title">{{ title }}</span>
+			</div>
+			<div class="a-h-right">
+				<div class="a-h-r-btn" @click.stop="addTemplate()">添加模块</div>
+			</div>
+		</div>
+		<div class="a-main">
+			<analysisItem v-for="item in analysisList" :key="item.id" :data="item"/>
+		</div>
+		<div v-if="showDialog == true" class="a-dialog" v-el-drag-dialog>
+      <div class="a-d-top">
+       <div class="a-d-t-left">
+				<div :style="tagIndex==index?'background:white':''" class="a-d-t-l-item" v-for="(item,index) in dialogTagList" :key="item.id" @click.stop="tagIndex=index">
+					{{ item.name }}
+				</div>
+			 </div>
+			 <div class="a-d-t-right">
+				<span @click.stop="showDialog=false">×</span>
+			 </div>
+      </div>
+      <div class="a-d-box">
+				<div class="a-d-b-item" v-for="item in 24" :key="item">
+					<div class="a-d-b-i-top">
+						<img :src="require('../../../../assets/icon/classroomObservation/avatar.png')">
+						<div>学生问答情况</div>
+						<div class="a-d-b-i-t-btn">添加</div>
+					</div>
+					<div class="a-d-b-i-bottom">使用IRE模型分析学生回答情况</div>
+				</div>
+      </div>
+    </div>
+	</div>
+</template>
+
+<script>
+import analysisItem from './analysisItem'
+export default {
+	components:{
+		analysisItem
+	},
+	data(){
+		return{
+			title:"科学课堂分析",
+			showDialog:false,
+			tagIndex:1,
+			dialogTagList:[
+				{id:1,name:"通用课堂分析"},
+				{id:2,name:"学科课堂分析"},
+				{id:3,name:"扩展分析"},
+			],
+			dialogTagDataList:[
+				[],
+				[],
+				[],
+			],
+			analysisList:[
+				{id:1,title:"OMO 智慧课堂分析",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+				{id:2,title:"加涅教学阶段九事件",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+				{id:3,title:"课堂时间分配",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+				{id:4,title:"学生问答情况",content:"<p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p><p>这是一个段落</p>"},
+			]
+		}
+	},
+	methods:{
+		addTemplate(){
+			this.showDialog = true;
+		}
+	}
+}
+</script>
+
+<style scoped>
+.analysis{
+	width: 100%;
+	height: auto;
+}
+
+.a-header{
+	width: 100%;
+	height: 50px;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	box-sizing: border-box;
+	padding-right: 40px;
+}
+
+.a-h-left{
+	display: flex;
+	align-items: center;
+}
+
+.a-h-l-icon{
+	width: 23px;
+	height: 23px;
+	background: url("../../../../assets/icon/classroomObservation/right.png") no-repeat;
+	background-size: 100% 100%;
+	margin-right: 5px;
+}
+
+.a-h-l-title{
+	font-size: 18px;
+}
+
+.a-h-r-btn{
+	font-size: 14px;
+	height: 35px;
+	width: auto;
+	box-sizing: border-box;
+	padding: 0 20px;
+	border: solid 1px #C5C5C5;
+	border-radius: 18px;
+	cursor: pointer;
+	background-color: white;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.a-main{
+	width: calc(100%);
+	height: auto;
+}
+
+.a-dialog {
+  position: fixed;
+  width: 60%;
+  height: 60%;
+  min-height: 600px;
+  box-shadow: 0px 0 8px 0px #555555;
+  border-radius: 15px;
+  z-index: 999;
+  left: 30%;
+  top: 50%;
+  margin: -18% 0 0 -300px;
+	overflow: hidden;
+}
+
+.a-d-top{
+  background: #ADADAD;
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  justify-content: space-between;
+  height: 40px;
+  border-radius: 15px 15px 0 0;
+  user-select: none;
+}
+
+.a-d-t-left{
+	width: calc(100% - 40px);
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: flex-start;
+	box-sizing: border-box;
+	padding-left: 5px;
+}
+
+.a-d-t-l-item{
+	width: auto;
+	height: 90%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	padding: 0 10px;
+	border-radius: 10px;
+	background-color: #D4D9DA;
+	margin-right: 3px;
+	cursor: pointer;
+}
+
+.a-d-t-l-item:hover{
+	background-color: white
+}
+
+.a-d-t-right{
+	width: 40px;
+	height: 40px;
+	margin-right: 10px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	color: black !important;
+}
+
+.a-d-t-right>span{
+	width: 25px;
+	height: 25px;
+	border-radius: 25px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	/* align-items: center; */
+	font-size: 22px;
+	color: #fff;
+	background-color: #ADADAD;
+	cursor: pointer;
+	background-color: #E6E6E6;
+	color: #ADADAD;
+}
+
+.a-d-box{
+	width: 100%;
+	height: calc(100% - 40px);
+	background-color: #F0F2F5;
+	overflow: auto;
+}
+
+.a-d-b-item{
+	width: 23%;
+	height: 100px;
+	background-color:#D9D9D9;
+	border-radius: 10px;
+	margin: 10px;
+	padding: 10px;
+	float: left;
+	box-sizing: border-box
+}
+.a-d-b-i-top{
+	width: 100%;
+	height: 50%;
+	display: flex;
+	justify-content: space-between;
+}
+.a-d-b-i-top>img{
+	width: 35px;
+	height: 35px;
+}
+/* .a-d-b-i-top>div{ */
+	/* width: auto;
+	height: 35px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin-left: 10px; */
+/* } */
+
+.a-d-b-i-top>div:nth-of-type(1){
+	width: calc(100% - 90px);
+	height: 35px;
+	display: flex;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 0 10px;
+	/* 字体溢出显示... */
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+
+}
+
+.a-d-b-i-bottom{
+	width: 100%;
+	height: 50%;
+	display: flex;
+	font-size: 14px;
+	align-items: center;
+}
+
+.a-d-b-i-t-btn{
+	font-size: 14px;
+	height: 30px;
+	position: relative;
+	top: 5px;
+	box-sizing: border-box;
+	padding: 0 10px;
+	background-color: #F3F3F3;
+	border-radius: 5px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+}
+</style>

+ 137 - 0
src/components/pages/classroomObservation/components/startPage.vue

@@ -0,0 +1,137 @@
+<template>
+	<div class="startPage">
+		<div class="sp-introduce" v-if="showIntroduce">
+			<span class="sp-i-personIcon"></span>
+			<div class="sp-i-title">您好,我是<span>CocoClass</span>课堂观察</div>
+			<div class="sp-i-brief">基于课堂录音和实录文稿进行分析,为您提供不同启发。</div>
+			<!-- <span class="sp-i-icon1"></span>
+			<span class="sp-i-icon2"></span> -->
+			<div class="sp-i-btn" @click="showIntroduce=false">我已了解并关闭</div>
+		</div>
+		<div class="sp-main">
+			<div class="sp-m-item" @click.stop="$emit('startTape')">
+				<span class="sp-m-i-icon1"></span>
+				<div>开始录音</div>
+			</div>
+			<div class="sp-m-item" @click.stop="$emit('uploadTape')">
+				<span class="sp-m-i-icon2"></span>
+				<div>上传录音</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+	export default {
+		emits:['startTape','uploadTape'],
+		data(){
+			return{
+				showIntroduce:true,
+			}
+		},
+		methods:{
+
+		}
+	}
+</script>
+
+<style scoped>
+.startPage{
+	width: 100%;
+	height: 100%;
+	position: relative;
+}
+
+.sp-introduce{
+	width: 100%;
+	height: 116px;
+	background-color: #E2EEFF;
+	position: absolute;
+	top: 50px;
+	display: flex;
+	flex-direction: column;
+	box-sizing: border-box;
+	padding-left: 220px;
+	padding-top: 20px;
+}
+
+.sp-i-title{
+	font-size: 24px;
+	font-weight: 600;
+	color: #3681FC;
+}
+
+.sp-i-title>span{
+	margin: 0 10px;
+}
+
+.sp-i-brief{
+	font-size: 14px;
+	margin-top: 10px;
+}
+
+.sp-i-personIcon{
+	width: 200px;
+	height: 200px;
+	position: absolute;
+	left: 0px;
+	bottom: 0;
+	background: url("../../../../assets/icon/classroomObservation/aiImage.png") no-repeat;
+	background-size: 100% 100%;
+	background-position: center 20px;
+}
+
+
+.sp-i-btn{
+	width: auto;
+	height: auto;
+	padding: 5px 10px;
+	position: absolute;
+	right: 10px;
+	bottom: 10px;
+	background-color: #3A76FC;
+	font-size: 12px;
+	border-radius: 20px;
+	cursor: pointer;
+	color: white;
+}
+
+.sp-main{
+	width: 100%;
+	height: 100%;
+	display: flex;
+	align-items: flex-end;
+	justify-content: center;
+	box-sizing: border-box;
+	padding-bottom:20%;
+}
+
+.sp-m-item{
+	width: 20%;
+	height: 40%;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+	background-color: #E8E8E8;
+	margin: 20px;
+	cursor: pointer;
+}
+
+.sp-m-item>span{
+	width: 40%;
+	height: 40%;
+	background-size: 100% 100%;
+	margin-bottom: 15px;
+}
+
+.sp-m-i-icon1{
+	background: url("../../../../assets/icon/classroomObservation/tape.png") no-repeat;
+}
+
+.sp-m-i-icon2{
+	background: url("../../../../assets/icon/classroomObservation/file.png") no-repeat;
+	background-size: 85% 85% !important;
+	background-position: center 10px;
+}
+</style>

+ 284 - 0
src/components/pages/classroomObservation/components/tape.vue

@@ -0,0 +1,284 @@
+<template>
+	<div class="tape">
+		<div class="t-header">
+			<div class="t-h-title">课堂录音</div>
+			<div class="t-h-time">2024-04-13 17:30:00</div>
+		</div>
+		<div class="t-tapeAudio">
+			<mini-audio :audio-source="audioUrl" class="audio_class"></mini-audio>
+		</div>
+		<div class="t-tapeFile">
+			<div class="t-t-header">
+				<div class="t-t-h-left">
+					<div class="t-t-h-l-Item" :style="cardStatus==0&&foldStatus?'background:white':''" @click.stop="changeCardStatus(0)">
+						<span class="t-t-h-l-i-icon"></span>
+						<div class="t-t-h-l-i-text">录音原文</div>
+					</div>
+					<div class="t-t-h-l-Item" :style="cardStatus==1&&foldStatus?'background:white':''" @click.stop="changeCardStatus(1)">
+						<span class="t-t-h-l-i-icon"></span>
+						<div class="t-t-h-l-i-text">转录文稿.xlsx</div>
+					</div>
+				</div>
+				<div class="t-t-h-right" @click.stop="changeFoldStatus(!foldStatus)">
+					<span class="t-t-h-r-icon" :style="`transform: scaleY(${foldStatus==0?1:-1});`"></span>
+					<div class="t-t-h-r-text">{{ foldStatus==0 ? '展开' : '收起'}}</div>
+				</div>
+			</div>
+			<div class="t-t-main" v-show="foldStatus">
+				<div class="t-t-m-Item" v-show="cardStatus==0">
+					<h1>录音原文</h1>
+				</div>
+
+				<div class="t-t-m-Item" v-show="cardStatus==1">
+					<iframe ref="viframe" style="width: 100%; height: 99%; border: none" :src="'https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(fileUrl)"></iframe>
+				</div>
+			</div>
+		</div>
+		<div class="t-chartArea" v-show="!foldStatus">
+			<div class="t-ca-item" v-for="(item,index) in chatData" :key="index">
+				<div class="t-ca-i-left">
+					<div class="t-ca-i-l-avatar">
+						<el-avatar size="medium" :src="require('../../../../assets/icon/classroomObservation/ai.png')"></el-avatar>
+					</div>
+				</div>
+				<div class="t-ca-i-right">
+					<div class="t-ca-i-r-name">{{ item.name }}</div>
+					<div class="t-ca-i-r-time">{{ item.create_at }}</div>
+					<div class="t-ca-i-r-content">{{ item.content }}</div>
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+import pdf from './pdf.vue';
+	export default {
+		components:{
+			pdf,
+		},
+		props:{
+			chatData:{
+				type:Array,
+				default:()=>{
+					return [];
+				}
+			}
+		},
+		data(){
+			return {
+				foldStatus:false,//0--收起状态   1--展开状态
+				cardStatus:0,//0--录音原文   1--转录文稿
+				fileUrl:"https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/2024%E5%B9%B4%E6%A0%A1%E7%BA%A7%E2%80%9C%E5%AD%A6%E7%94%9F%E5%88%9B%E6%96%B0%E5%88%9B%E4%B8%9A%E8%AE%AD%E7%BB%83%E8%AE%A1%E5%88%92%E2%80%9D%E7%AB%8B%E9%A1%B9%E7%94%B3%E6%8A%A5%E6%83%85%E5%86%B5%E4%B8%80%E8%A7%88%E8%A1%A8%EF%BC%8849%E4%B8%AA%EF%BC%89%EF%BC%88%E5%85%A8%E6%8C%87%E5%AF%BC%E8%80%81%E5%B8%88%EF%BC%891713060074585.xlsx",
+				audioUrl:"https://lx-sycdn.kuwo.cn/3ad08dcac8f403bd3d38fcc13d3ab1d6/661b2f11/resource/n1/36/58/2187696883.mp3",
+			}
+		},
+		methods:{
+			// 切换折叠状态
+			changeFoldStatus(newValue){
+				this.foldStatus = newValue;
+			},
+			//切换卡片
+			changeCardStatus(newValue){
+				this.foldStatus = 1;
+				this.cardStatus = newValue;
+			}
+		}
+	}
+</script>
+
+<style scoped>
+.tape{
+	width: 100%;
+	height: 100%;
+} 
+.t-header{
+	width: 100%;
+	height: 30px;
+	display: flex;
+	align-items: center;
+}
+
+.t-h-title{
+	font-size: 20px;
+	margin-right: 10px;
+}
+.t-h-time{
+	font-size: 14px;
+	color: #A8A9AB;
+}
+
+.t-tapeAudio{
+	width: 100%;
+	height: 50px;
+	margin-top: 10px;
+	box-sizing: border-box;
+	padding-right: 30px;
+}
+
+.audio_class {
+	width: 100% !important;
+	/* height: 100% !important; */
+  background: #3680fb !important;
+  margin: 0 !important;
+}
+
+.t-tapeAudio>>>.vueAudioBetter span:before {
+  color: #fff;
+}
+
+.t-tapeAudio>>>.slider{
+	width: 80% !important;
+}
+
+.audio_class>>>.slider .process {
+  background: #000;
+}
+
+.t-tapeAudio>>>.vueAudioBetter .iconfont:active {
+  position: unset;
+}
+
+.t-tapeFile{
+	width: 100%;
+	max-height: calc(100vh - 340px);
+	overflow: auto;
+	margin-top: 10px;
+	/* background-color: red; */
+}
+
+.t-t-header{
+	width: 100%;
+	height: 35px;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	background-color: #E5E5E5;
+	border-radius: 5px 5px 0 0;
+	box-sizing: border-box;
+	padding-right: 10px;
+}
+
+.t-t-h-left{
+	width: calc(100% - 80px);
+	height: 100%;
+	overflow: auto;
+	box-sizing: border-box;
+	display: flex;
+	align-items: center;
+	box-sizing: border-box;
+	padding-left: 5px;
+}
+
+.t-t-h-l-Item{
+	width: auto;
+	height: 90%;
+	box-sizing: border-box;
+	padding: 0 20px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+	font-size: 14px;
+	margin-right: 10px;
+	border-radius: 5px;
+}
+
+.t-t-h-l-i-icon{
+	width: 20px;
+	height: 20px;
+	background: url("../../../../assets/icon/classroomObservation/file.png") no-repeat;
+	background-size: 100% 100%;
+	margin-right: 5px;
+	background-position: center;
+}
+
+.t-t-h-l-Item:hover{
+	background-color: white;
+}
+
+.t-t-h-right{
+	width: 80px;
+	height: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+}
+
+.t-t-h-r-icon{
+	width: 25px;
+	height: 25px;
+	background: url("../../../../assets/icon/classroomObservation/foldIcon.png") no-repeat;
+	background-size: 100% 100%;
+	margin-right: 10px;
+	background-position: center;
+	/* 水平镜像 */
+	transform: scaleY(-1);
+}
+
+.t-t-h-r-text{
+	font-size: 16px;
+}
+
+.t-t-main{
+	width: 100%;
+	height: calc(100vh - 400px);
+	/* height: calc(100% - 35px); */
+	overflow: auto;
+	background-color: white;
+}
+
+.t-t-m-Item{
+	width: 100%;
+	height: 100%;
+}
+
+.t-chartArea{
+	width: 100%;
+	height: calc(100vh - 400px);;
+	overflow: auto;
+}
+
+.t-ca-item{
+	width: 100%;
+	height: auto;
+	margin-top:20px ;
+	display: flex;
+	justify-content: flex-start;
+}
+
+.t-ca-i-left{
+	width: 50px;
+	height: 50px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.t-ca-i-right{
+	flex: 1;
+	height: auto;
+	padding: 10px;
+	box-sizing: border-box;
+}
+
+.t-ca-i-r-name{
+	width: 100%;
+	font-size: 16px;
+	font-weight: 600;
+}
+
+.t-ca-i-r-time{
+	width: 100%;
+	font-size: 14px;
+	color: #A8A9AB;
+	margin-top: 10px;
+}
+
+.t-ca-i-r-content{
+	margin-top: 10px;
+	width: 100%;
+	height: auto;
+}
+</style>

+ 62 - 0
src/components/pages/classroomObservation/components/transcription.vue

@@ -0,0 +1,62 @@
+<template>
+	<div class="transcription">
+		<div class="t-header">
+			<div class="t-h-title">实时转录</div>
+			<div class="t-h-time">{{ data.time }}</div>
+		</div>
+		<div class="t-content">
+			{{ data.content }}
+		</div>
+	</div>
+</template>
+
+<script>
+	export default {
+		props:{
+			data:{
+				type:Object,
+				default:()=>{
+					return {}
+				}
+			}
+		},
+		data() {
+			return {
+				
+			};
+		},
+	}
+</script>
+
+<style scoped>
+.transcription{
+	width: 100%;
+	height:100%;
+	padding-top:30px;
+}
+
+.t-header{
+	width: 100%;
+	height: 40px;
+	display: flex;
+	align-items: center;
+}
+.t-h-title{
+	font-size: 20px;
+	font-weight: bold;
+	margin-right: 10px;
+}
+.t-h-time{
+	font-size: 14px;
+	color:#AEAFB1;
+}
+
+.t-content{
+	width: 100%;
+	height: calc(100vh - 330px);
+	padding:20px 30px;
+	box-sizing: border-box;
+	overflow: auto;
+}
+
+</style>

+ 250 - 0
src/components/pages/classroomObservation/index.vue

@@ -0,0 +1,250 @@
+<template>
+	<div class="classroomObservation">
+		<div class="co-header1">
+			<div class="co-h1-left">
+				<span class="co-h1-l-icon el-icon-s-home"></span>
+				<div class="co-h1-l-router">
+						<span class="co-h1-l-r-up" @click="goTo('ai助手')">AI助手</span>
+						<span class="co-h1-l-r-rightIcon el-icon-arrow-right"></span>
+						<span class="co-j1-l-r-down">课堂观察</span>
+				 </div>
+			</div>
+
+		</div>
+		<div class="co-header2">
+			<div class="co-h2-left">
+				<span class="co-h2-l-icon"></span>
+				<span class="co-h2-l-hr"></span>
+				<span class="co-h2-l-text">{{ title }}</span>
+			</div>
+			<div class="co-h2-right">
+				<div class="co-h2-r-btn co-h2-r-blueBtn" @click.stop="getReport()">
+					<span class="co-h2-r-b-icon1"></span>
+					<div>生成报告</div>
+				</div>
+				<div class="co-h2-r-btn" @click.stop="preview()">
+					<!-- <span class="co-h2-r-b-icon2"></span> -->
+					<div>预览</div>
+				</div>
+				<div class="co-h2-r-btn" @click.stop="share()">
+					<!-- <span class="co-h2-r-b-icon2"></span> -->
+					<div>分享</div>
+				</div>
+
+			</div>
+		</div>
+		<div class="co-main">
+			<div class="co-m-left">
+				<chatArea/>
+			</div>
+			<div class="co-m-right">
+				<messageArea/>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+// 聊天区域
+import chatArea from './components/chatArea.vue'
+// 信息区域
+import messageArea from './components/messageArea.vue'
+	export default {
+		components:{
+			chatArea,
+			messageArea
+		},
+		data(){
+			return{
+				title:"20240410课堂实录"
+			}
+		},
+		methods: {
+			// 跳转
+			goTo(path){
+				this.$message.info(`去到:${path}`)
+			},
+			// 生成报告
+			getReport(){
+				this.$message.info("生成报告")
+			},
+			//预览
+			preview(){
+				this.$message.info("预览")
+			},
+			// 分享
+			share(){
+				this.$message.info("分享")
+			}
+		},
+	}
+</script>
+
+<style scoped>
+.classroomObservation{
+	width: 100%;
+	height: 100%;
+	display: flex;
+	flex-direction: column;
+	background-color: #F0F2F5;
+}
+
+.co-header1{
+	width: 100%;
+	height: 46px;
+	background-color: #060E17;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	box-sizing: border-box;
+	padding: 0 20px;
+}
+
+.co-h1-left{
+	width: auto;
+	height: 22px;
+	display: flex;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 0 20px;
+}
+
+.co-h1-l-icon{
+	color: #5D6268;
+	width: 16px;
+	height: 16px;
+	margin-right: 10px;
+}
+
+.co-h1-l-router{
+	display: flex;
+	align-items: center;
+	color: white;
+	font-size: 14px;
+}
+
+.co-h1-l-router>span{
+	margin: 0 5px;
+}
+
+.co-h1-l-r-up{
+	color: #5D6268;
+	cursor: pointer;
+}
+
+.co-h1-l-r-up:hover{
+	color: white;
+}
+
+.co-j1-l-r-down{
+	cursor: pointer;
+}
+
+.co-h1-l-r-rightIcon{
+	font-size: 16px;
+	color: #5D6268;
+}
+
+.co-header2{
+	width: 100%;
+	height: 42px;
+	background-color: white;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	box-sizing: border-box;
+	padding: 0  20px;
+}
+
+.co-h2-left{
+	width: auto;
+	height: 22px;
+	display: flex;
+	align-items: center;
+	font-size: 14px;
+}
+
+.co-h2-l-icon{
+	width: 20px;
+	height: 20px;
+	position: relative;
+	background: url('../../../assets/icon/classroomObservation/close.png') no-repeat;
+	background-size: 100% 100%;
+}
+.co-h2-l-hr{
+	width: 2px;
+	height: 20px;
+	background-color: #E7E7E7;
+	border-radius: 10px;
+	margin: 0 10px;
+}
+
+.co-h2-right{
+	width: auto;
+	height: 100%;
+	display: flex;
+	align-items: center;
+}
+
+.co-h2-r-btn{
+	width: auto;
+	box-sizing: border-box;
+	padding: 0 10px;
+	height: 30px;
+	display: flex;
+	align-items: center;
+	cursor: pointer;
+	font-size: 14px;
+	margin: 0 10px;
+	box-sizing: border-box;
+	border: solid 1px #3681FC;
+	border-radius: 20px;
+}
+
+.co-h2-r-btn>span:nth-child(1){
+	width: 20px;
+	height: 20px;
+	margin-right: 8px;
+}
+
+.co-h2-r-b-icon1{
+	background: url("../../../assets/icon/classroomObservation/six.png") no-repeat;
+	background-size: 100% 100%;
+}
+
+.co-h2-r-b-icon2{
+	background: url("../../../assets/icon/classroomObservation/close.png") no-repeat;
+	background-size: 100% 100%;
+}
+
+
+.co-h2-r-blueBtn{
+	background-color: #3681FC;
+	color: white;
+}
+
+.co-main{
+	width: 100%;
+	flex: 1;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.co-m-left{
+	height: 100%;
+	flex: 1;
+	box-sizing: border-box;
+}
+
+.co-m-right{
+	height: 100%;
+	flex: 1;
+	box-sizing: border-box;
+}
+
+
+
+
+
+</style>

+ 9 - 0
src/router/index.js

@@ -123,6 +123,7 @@ import courseIndex from '@/components/pages/course/index'
 import studentEva from '@/components/pages/studentEva'
 import kindStudentEva from '@/components/pages/kindStudentEva/index'
 import record from '@/components/pages/record/class'
+import classroomObservation from '@/components/pages/classroomObservation/index'//课堂观察
 
 // 全局修改默认配置,点击空白处不能关闭弹窗
 ElementUI.Dialog.props.closeOnClickModal.default = false
@@ -1057,5 +1058,13 @@ export default new Router({
                 requireAuth: '' // 不需要鉴权
             }
         },
+				{//课堂观察
+					path:"/classroomObservation",
+					name:"classroomObservation",
+					component:classroomObservation,
+					meta:{
+						requireAuth:''//不需要鉴权
+					}
+				}
     ]
 })

部分文件因文件數量過多而無法顯示