SanHQin преди 10 месеца
родител
ревизия
3bfc512b14

BIN
src/assets/icon/classroomObservation/isVideo.png


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

@@ -33,7 +33,6 @@ export default {
 	},
 	data() {
 		let validateNo = (rule, value, callback) => {
-			console.log(this.courseList.findIndex(i=>i.value==value))
 			if (value.trim().length == 0) {
 				callback(new Error("请输入课堂编号"));
 			}else if(this.courseList.findIndex(i=>i.value==value.trim())!=-1){
@@ -43,8 +42,6 @@ export default {
 			}
 		};
 		let validateName = (rule, value, callback) => {
-			console.log(this.courseList)
-			console.log(rule)
 			if (value.trim().length == 0) {
 				callback(new Error("请输入课堂名称"));
 			} else {

+ 11 - 2
src/components/pages/classroomObservation/components/analysis.vue

@@ -15,7 +15,7 @@
 		<div class="a-main" v-show="showItem">
 			<analysisItem
 				ref="analysisItemRef"
-				v-if="analysisItemList.length > 0"
+				v-if="item.jsonData.name!='词频词汇分析'"
 				v-for="(item, index) in analysisItemList"
 				:dialogTagDataList="dialogTagDataList"
 				:key="item.id"
@@ -23,8 +23,10 @@
 				:tid="tid"
 				:fileId="fileId"
 				:index="index"
+				:showBrief="showBrief"
 				@delItem="delItem"
 				@editItem="editItem"
+				@saveItem="saveItem"
 			/>
 			<div class="a_m_empty" v-if="analysisItemList.length == 0">
 				暂无模块...
@@ -36,12 +38,16 @@
 <script>
 import analysisItem from "./analysisItem";
 export default {
-	emits: ["delItem", "editItem"],
+	emits: ["delItem", "editItem","saveItem"],
 	props: {
 		title: {
 			type: String,
 			default: "分析",
 		},
+		showBrief:{
+			type:Boolean,
+			default:true
+		},
 		dialogTagDataList:{
 			type:Array,
 			default:()=>{
@@ -89,6 +95,9 @@ export default {
 		editItem(id, _data) {
 			this.$emit("editItem", id, _data);
 		},
+		saveItem(id,_data){
+			this.$emit("saveItem",id,_data)
+		},
 		getReport(id) {
 			if (!id) {
 				this.$refs.analysisItemRef.forEach((i) => {

+ 370 - 281
src/components/pages/classroomObservation/components/analysisItem.vue

@@ -1,23 +1,23 @@
 <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; color: red" v-if="loadNum == 2"
-          >优化失败
-        </span>
-        <span
-          :class="loading ? 'text1' : 'text2'"
-          style="width: 100px"
-          v-if="loadNum == 1"
-          >{{ loading ? "优化中..." : "优化完成" }}
-        </span>
-        <span
+	<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; color: red" v-if="loadNum == 2"
+					>优化失败
+				</span>
+				<span
+					:class="loading ? 'text1' : 'text2'"
+					style="width: 100px"
+					v-if="loadNum == 1"
+					>{{ loading ? "优化中..." : "优化完成" }}
+				</span>
+				<span
 					v-if="loadNum == 0 && !openItem"
 					class="ai-h-r-icon4"
 					@click.stop="delBtn()"
@@ -91,278 +91,367 @@
 					</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 }}
+				<!-- <mdView :text="data.jsonData.result" /> -->
+				<!-- {{ data.jsonData.result }} -->
+			</div>
+			<mdView :text="data.jsonData.content" />
+			<div v-for="(item, index) in data.jsonData.dataFileList" :key="item.uid">
+				<div v-if="imgTypeList.includes(checkFileType(item.url))">
+					<img style="max-width: 100%" :src="item.url" alt="" />
+				</div>
+				<div v-else-if="checkFileType(item.url) == 'md'">
+					<mdView :url="item.url" />
+				</div>
+				<div v-else-if="checkFileType(item.url) == 'json'">
+					<pieChart :url="item.url" />
+				</div>
+			</div>
 
-        <!-- <span class="ai-h-r-icon4" @click.stop="delBtn()"></span> -->
-      </div>
-    </div>
-    <div class="ai-main" v-if="openItem">
-      <div class="a-m-brief">
-        {{ data.jsonData.result }}
-        <!-- <mdView :text="data.jsonData.result" /> -->
-        <!-- {{ data.jsonData.result }} -->
-      </div>
-      <mdView :text="data.jsonData.content" />
-      <div v-for="(item, index) in data.jsonData.dataFileList" :key="item.uid">
-        <div v-if="imgTypeList.includes(checkFileType(item.url))">
-          <img style="max-width: 100%" :src="item.url" alt="" />
-        </div>
-        <div v-else-if="checkFileType(item.url) == 'md'">
-          <mdView :url="item.url" />
-        </div>
-        <div v-else-if="checkFileType(item.url) == 'json'">
-          <pieChart :url="item.url" />
-        </div>
-      </div>
-
-      <div v-for="(item, index) in data.jsonData.fileList" :key="item.uid">
-        <div v-if="imgTypeList.includes(checkFileType(item.url))">
-          <img style="max-width: 100%" :src="item.url" alt="" />
-        </div>
-        <div v-else-if="checkFileType(item.url) == 'md'">
-          <mdView :url="item.url" />
-        </div>
-        <div v-else-if="checkFileType(item.url) == 'json'">
-          <pieChart :url="item.url" />
-        </div>
-      </div>
-    </div>
-  </div>
+			<div v-for="(item, index) in data.jsonData.fileList" :key="item.uid">
+				<div v-if="imgTypeList.includes(checkFileType(item.url))">
+					<img style="max-width: 100%" :src="item.url" alt="" />
+				</div>
+				<div v-else-if="checkFileType(item.url) == 'md'">
+					<mdView :url="item.url" />
+				</div>
+				<div v-else-if="checkFileType(item.url) == 'json'">
+					<pieChart :url="item.url" />
+				</div>
+			</div>
+		</div>
+	</div>
 </template>
 
 <script>
 import mdView from "./mdView.vue";
 import pieChart from "./pieChart.vue";
+// import { v4 as uuidv4 } from "uuid";
+// import MarkdownIt from "markdown-it";
 export default {
-  emits: ["delItem", "editItem"],
-  components: {
-    mdView,
-    pieChart
-  },
-  props: {
-    data: {
-      type: Object,
-      default: () => {
-        return {};
-      }
-    },
-    dialogTagDataList: {
-      type: Array,
-      default: () => {
-        return [];
-      }
-    },
-    index: {
-      type: Number,
-      default: 0
-    },
-    tid: {
-      type: String,
-      require: true
-    },
-    fileId: {
-      type: String,
-      require: true
-    }
-  },
-  data() {
-    return {
-      openItem: false,
-      loading: false,
-      loadNum: 0,
-      showIndex: 0,
-      historyResult: [],
-      imgTypeList: [
-        "png",
-        "jpg",
-        "jpeg",
-        "bmp",
-        "gif",
-        "webp",
-        "psd",
-        "svg",
-        "tiff"
-      ]
-    };
-  },
-  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() {
-      this.$nextTick(() => {
-        this.loading = true;
-        this.openItem = false;
-        this.loadNum = 1;
-        let assistant = this.dialogTagDataList.find(
-          i => i.title == this.data.jsonData.name
-        );
-        let parm = {
-          assistant_id: assistant ? assistant.value : null,
-          message:
-            "请使用代码解析器获取文件,帮我根据要求完整的分析,输出请按照要求。",
-          session_name: new Date().getTime(),
-          userId: "1cf9dc4b-d95f-11ea-af4c-52540005ab01",
-          file_ids: this.fileId ? [this.fileId] : ""
-        };
+	emits: ["delItem", "editItem", "saveItem"],
+	components: {
+		mdView,
+		pieChart,
+	},
+	props: {
+		data: {
+			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,
+			showIndex: 0,
+			historyResult: [],
+			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() {
+			this.$nextTick(() => {
+				this.loading = true;
+				this.openItem = false;
+				this.loadNum = 1;
+				let assistant = this.dialogTagDataList.find(
+					(i) => i.title == this.data.jsonData.name
+				);
+				let parm = {
+					assistant_id: assistant?assistant.value:null,
+					message:
+						"请使用代码解析器分析,帮我根据要求完整的分析,输出请按照要求。",
+					session_name: new Date().getTime(),
+					userId: "1cf9dc4b-d95f-11ea-af4c-52540005ab01",
+					file_ids: this.fileId?[this.fileId]:'',
+				};
 
-        if (!parm.assistant_id) {
-          this.loading = false;
-          this.loadNum = 2;
-          return this.$message.error("未找到对应的AI助手");
-        }
+				// 👇
+				// const _uid = uuidv4();
+				// let parm = {
+				// 	assistant_id: assistant ? assistant.value : null,
+				// 	userId: "1cf9dc4b-d95f-11ea-af4c-52540005ab01", //602def61-005d-11ee-91d8-005056b86db5
+				// 	message:
+				// 		"请使用代码解析器获取文件,帮我根据要求完整的分析,输出请按照要求。",
+				// 	session_name: new Date().getTime(),
+				// 	uid: _uid,
+				// 	file_ids: this.fileId ? [this.fileId] : [],
+				// };
+				if (!parm.assistant_id) {
+					this.loading = false;
+					this.loadNum = 2;
+					return this.$message.error("未找到对应的AI助手");
+				}
+				// this.ajax
+				// 	.post("https://gpt4.cocorobo.cn/ai_agent_park_chat_new", parm)
+				// 	.then((res) => {
+				// 		if (res.data.FunctionResponse.result == "发送成功") {
+				// 		} else {
+				// 			this.$message.warning(res.data.FunctionResponse.result);
+				// 		}
+				// 	})
+				// 	.catch((err) => {
+				// 		console.log(err);
+				// 	});
+				// this.getAtAuContent(_uid);
+				// 👆
 
-        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;
-              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.$message.error("AI无法识别优化");
-            this.loading = false;
-          });
-      });
-    },
-    delBtn() {
-      this.$confirm("确定删除?", "提示", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "error"
-      }).then(() => {
-        this.$emit("delItem", this.data.id);
-      });
-    },
-    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.$emit("editItem", this.data.id, _copyData);
-    }
-  },
-  mounted() {
-    if (this.data.jsonData.content) {
-      this.historyResult.push(this.data.jsonData);
-    }
-  }
+				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);
+					// 处理流数据
+				}
+			};
+		},
+		delBtn() {
+			this.$confirm("确定删除?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "error",
+			}).then(() => {
+				this.$emit("delItem", this.data.id);
+			});
+		},
+		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);
+		},
+	},
+	mounted() {
+		if (this.data.jsonData.content) {
+			this.historyResult.push(this.data.jsonData);
+		}
+	},
 };
 </script>
 
 <style scoped>
 .analysisItem {
-  width: 100%;
-  height: auto;
+	width: 100%;
+	height: auto;
 
-  margin: 11.7px 0px;
+	margin: 11.7px 0px;
 
-  padding-right: 10px;
-  box-sizing: border-box;
+	padding-right: 10px;
+	box-sizing: border-box;
 }
 .text1 {
-  color: rgba(54, 129, 252, 1);
+	color: rgba(54, 129, 252, 1);
 }
 .text2 {
-  color: rgba(23, 196, 105, 1);
+	color: rgba(23, 196, 105, 1);
 }
 .ai-header {
-  width: 100%;
-  height: 50px;
-  display: flex;
-  background-color: white;
-  border-radius: 5px;
+	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;
+	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.png")
-    no-repeat;
-  background-size: 100% 100%;
-  margin-right: 10px;
-  transition: 0.3s;
+	width: 16px;
+	height: 16px;
+	background: url("../../../../assets/icon/classroomObservation/right.png")
+		no-repeat;
+	background-size: 100% 100%;
+	margin-right: 10px;
+	transition: 0.3s;
 }
 
 .ai-h-l-iconActive {
-  transform: rotate(90deg);
+	transform: rotate(90deg);
 }
 .ai-h-l-text {
-  font-size: 18px;
+	font-size: 18px;
 }
 
 .ai-h-right {
-  width: auto;
-  height: 100%;
-  display: flex;
-  align-items: center;
-  justify-content: space-around;
-  position: relative;
+	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;
+	width: 18px;
+	height: 18px;
+	background-size: 100% 100%;
+	margin: 0 10px;
+	cursor: pointer;
 }
 
 .ai-h-right > span > img {
@@ -371,61 +460,61 @@ export default {
 }
 
 .ai-h-r-icon1 {
-  background: url("../../../../assets/icon/classroomObservation/back.png");
-  /* 镜像 */
-  transform: scaleX(-1);
+	background: url("../../../../assets/icon/classroomObservation/back.png");
+	/* 镜像 */
+	transform: scaleX(-1);
 }
 
 .ai-h-r-icon2 {
-  background: url("../../../../assets/icon/classroomObservation/back.png");
+	background: url("../../../../assets/icon/classroomObservation/back.png");
 }
 
 .ai_h_r_iconOpacity {
-  opacity: 0.5;
-  cursor: not-allowed !important;
+	opacity: 0.5;
+	cursor: not-allowed !important;
 }
 
 .ai-h-r-icon3 {
-  background: url("../../../../assets/icon/classroomObservation/edit.png");
-  /* background: url("../../../../assets/icon/classroomObservation/del.png"); */
-  /* display: none; */
+	background: url("../../../../assets/icon/classroomObservation/edit.png");
+	/* background: url("../../../../assets/icon/classroomObservation/del.png"); */
+	/* display: none; */
 }
 
 .ai-header:hover .ai-h-r-icon4 {
-  display: block;
+	display: block;
 }
 
 .ai-h-r-icon4 {
-  background: url("../../../../assets/icon/classroomObservation/del.png");
-  /* position: absolute; */
-  /* right: -40px; */
-  display: none;
+	background: url("../../../../assets/icon/classroomObservation/del.png");
+	/* position: absolute; */
+	/* right: -40px; */
+	display: none;
 }
 
 .analysisItem:hover .ai-h-r-icon4 {
-  display: block;
+	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;
+	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;
+	font-size: 16px;
+	/* 斜体 */
+	font-style: italic;
+	margin-bottom: 10px;
+	color: #6b798e;
 }
 
 td,
 th {
-  padding: 10px;
+	padding: 10px;
 }
 </style>

+ 319 - 121
src/components/pages/classroomObservation/components/baseMessage.vue

@@ -1,12 +1,12 @@
 <template>
-	<div class="message" >
+	<div class="message">
 		<div class="m-header" @click.stop="changeShowMain(!showMain)">
 			<span :class="['m-h-icon', showMain ? 'm-h-icon-active' : '']"></span>
 			<span class="m-h-title">{{ title }}</span>
 		</div>
 		<div class="m-main" v-show="showMain">
-			<div class="baseInfoLeft">
-				<div class="m-m-formItem">
+			<div class="m-m-form">
+				<div class="m-m-formItem" style="width: clamp(50%, 50%, 50%)">
 					<div class="m-m-fi-label">课程名称</div>
 					<div class="m-m-fi-input">
 						<el-input
@@ -17,62 +17,83 @@
 					</div>
 				</div>
 
-				<div class="baseInfoLeftBot">
-					<div class="m-m-formItemBot">
-						<div class="m-m-fi-label">授课年级</div>
-						<div class="m-m-fi-input">
-							<el-select v-model="data.grade" @change="changeData()" placeholder="请选择年级">
-								<el-option
-									v-for="(item, index) in gradeList"
-									:key="index"
-									:value="item.value"
-									:label="item.label"
-								></el-option>
-							</el-select>
-						</div>
+				<div class="m-m-formItem" style="width: clamp(21%,21%,21%)">
+					<div class="m-m-fi-label">授课老师</div>
+					<div class="m-m-fi-input">
+						<el-input
+							v-model="data.teacherName"
+							placeholder="请输入授课老师"
+							@change="changeData()"
+						></el-input>
 					</div>
+				</div>
 
-					<div class="m-m-formItemBot">
-						<div class="m-m-fi-label">授课科目</div>
-						<div class="m-m-fi-input">
-							<el-select v-model="data.subject" @change="changeData()" placeholder="请选择年级">
-								<el-option
-									v-for="(item, index) in subjectList"
-									:key="index"
-									:value="item.value"
-									:label="item.label"
-								></el-option>
-							</el-select>
-						</div>
+				<div class="m-m-formItem" style="width: clamp(22%,22%,22%)"">
+					<div class="m-m-fi-label">授课时间</div>
+					<div class="m-m-fi-input">
+						<el-date-picker
+							v-model="data.time"
+							type="datetime"
+							format="yyyy-MM-dd HH:mm:ss"
+							value-format="yyyy-MM-dd HH:mm:ss"
+							style="width: 100%"
+							@change="changeData()"
+							placeholder="请选择授课时间"
+						>
+						</el-date-picker>
 					</div>
+				</div>
 
-					<div class="m-m-formItemBot">
-						<div class="m-m-fi-label">教材版本</div>
-						<div class="m-m-fi-input">
-							<el-input
-								v-model="data.textbook"
-								placeholder="请输入教材版本"
-								@change="changeData()"
-							></el-input>
-						</div>
+				<div class="m-m-formItem" style="width: clamp(24%,24%,24%)"">
+					<div class="m-m-fi-label">授课年级</div>
+					<div class="m-m-fi-input">
+						<el-select
+							style="width: 100%"
+							v-model="data.grade"
+							@change="changeData()"
+							placeholder="请选择年级"
+						>
+							<el-option
+								v-for="(item, index) in gradeList"
+								:key="index"
+								:value="item.value"
+								:label="item.label"
+							></el-option>
+						</el-select>
 					</div>
 				</div>
-			</div>
 
-			<!-- 授课老师,学生人数 -->
-			<div class="baseInfoRight">
-				<div class="m-m-formItem">
-					<div class="m-m-fi-label">授课老师</div>
+				<div class="m-m-formItem" style="width: clamp(24.5%,24.5%,24.5%)">
+					<div class="m-m-fi-label">授课科目</div>
+					<div class="m-m-fi-input">
+						<el-select
+							style="width: 100%"
+							v-model="data.subject"
+							@change="changeData()"
+							placeholder="请选择年级"
+						>
+							<el-option
+								v-for="(item, index) in subjectList"
+								:key="index"
+								:value="item.value"
+								:label="item.label"
+							></el-option>
+						</el-select>
+					</div>
+				</div>
+
+				<div class="m-m-formItem" style="width: clamp(21%,21%,21%)"">
+					<div class="m-m-fi-label">教材版本</div>
 					<div class="m-m-fi-input">
 						<el-input
-							v-model="data.teacherName"
-							placeholder="请输入授课老师"
+							v-model="data.textbook"
+							placeholder="请输入教材版本"
 							@change="changeData()"
 						></el-input>
 					</div>
 				</div>
 
-				<div class="m-m-formItem" style="margin: 10px 0">
+				<div class="m-m-formItem" style="width: clamp(22%,22%,22%)"">
 					<div class="m-m-fi-label">学生人数</div>
 					<div class="m-m-fi-input">
 						<el-input
@@ -83,76 +104,155 @@
 					</div>
 				</div>
 			</div>
-			<div class="imgTit">
-				<span>添加课堂图片</span>
-				<span>(建议图片比例16:9,最多上传3张图片)</span>
-			</div>
-			<div class="m-m-formImage" v-loading="uploadImageLoading">
-				<div class="m-m-fi-imageList">
-					<div class="m-m-fi-imageList">
-						<div
-							class="m-m-fi-imageItem"
-							v-for="(value,key,index) in imageList"
-							:key="index"
-							v-if="key.indexOf('fileList')!=-1&&index!=0 && value.length>0"
-							@click.stop="previewImg(value[0].url)"
-						>
-						<el-image
-						class="itemUrl"
-      			:src="value[0].url"
-      			fit="cover"></el-image>
-						<span @click.stop="delImage(key)">x</span>
-							<!-- <img class="itemUrl" :src="value[0].url" alt="" /> -->
+			<div class="fileList">
+				<div class="fl_img">
+					<div class="imgTit">
+						<span>课堂图片</span>
+						<span>(建议图片比例16:9,最多上传3张)</span>
+					</div>
+					<div class="m-m-formImage" v-loading="uploadImageLoading">
+						<div class="m-m-fi-imageList">
+							<div class="m-m-fi-imageList">
+								<div
+									class="m-m-fi-imageItem"
+									v-for="(value, key, index) in imageList"
+									:key="index"
+									v-if="(key == 'fileList1' || key == 'fileList2' || key == 'fileList3') && value.length >0"
+									@click.stop="previewImg(value[0].url)"
+									style="max-width: 32%;"
+								>
+									<el-image
+										class="itemUrl"
+										:src="value[0].url"
+										fit="cover"
+									></el-image>
+									<span @click.stop="delImage(key)">x</span>
+									<!-- <img class="itemUrl" :src="value[0].url" alt="" /> -->
+								</div>
+								<!-- 图片区域 -->
+							</div>
+
+							<div
+								class="m-m-fi-imageItem"
+								@click.stop="addImage()"
+								v-if="
+									imageList.fileList1 &&
+									imageList.fileList1.length +
+										imageList.fileList2.length +
+										imageList.fileList3.length <
+										3
+								"
+							>
+								<img
+									src="../../../../assets/icon/classroomObservation/Union.png"
+									alt=""
+								/>
+								<div
+									style="
+										font-size: 12px;
+										font-weight: 400;
+										margin-top: 5px;
+										color: rgba(0, 0, 0, 0.4);
+									"
+								>
+									点击上传图片
+								</div>
+							</div>
+							<!-- 图片区域 -->
 						</div>
-						<!-- 图片区域 -->
+						<!-- <div class="m-m-fi-btn" >添加课堂图片</div> -->
+					</div>
+				</div>
+				<div class="fl_video">
+					<div class="imgTit">
+						<span>课堂视频</span>
+						<span>(建议图片比例16:9,最多上传1个)</span>
 					</div>
+					<div class="m-m-formImage" v-loading="uploadVideoLoading">
+						<div class="m-m-fi-imageList">
+							<div class="m-m-fi-imageList">
+								<div
+									class="m-m-fi-imageItem"
+									v-for="(item, index) in imageList.videoList?imageList.videoList:[]"
+									:key="index"
+									@click.stop="previewVideo(item.url)"
+								>
+								<!-- <div>{{ item }}</div> -->
+									<el-image
+										class="itemUrl"
+										:src="require('../../../../assets/icon/classroomObservation/isVideo.png')"
+										fit="cover"
+									></el-image>
+									<span @click.stop="delVideo('videoList')">x</span>
+								</div>
+							</div>
 
-					<div class="m-m-fi-imageItem"  @click.stop="addImage()" v-if="imageList.fileList1&&(imageList.fileList1.length+imageList.fileList2.length+imageList.fileList3.length)<3">
-						<img
-							src="../../../../assets/icon/classroomObservation/Union.png"
-							alt=""
-						/>
-						<div
-							style="
-								font-size: 12px;
-								font-weight: 400;
-								margin-top: 5px;
-								color: rgba(0, 0, 0, 0.4);
-							"
-						>
-							点击上传图片
+							<div
+								class="m-m-fi-imageItem"
+								@click.stop="addVideo()"
+								v-if="
+									(imageList.videoList&&imageList.videoList.length<=0) || !imageList.videoList
+								"
+							>
+								<img
+									src="../../../../assets/icon/classroomObservation/Union.png"
+									alt=""
+								/>
+								<div
+									style="
+										font-size: 12px;
+										font-weight: 400;
+										margin-top: 5px;
+										color: rgba(0, 0, 0, 0.4);
+									"
+								>
+									点击上传视频
+								</div>
+							</div>
+							<!-- 图片区域 -->
 						</div>
+						<!-- <div class="m-m-fi-btn" >添加课堂图片</div> -->
 					</div>
-					<!-- 图片区域 -->
 				</div>
-				<!-- <div class="m-m-fi-btn" >添加课堂图片</div> -->
 			</div>
 		</div>
+		<previewVideoDialog ref="previewVideoDialogRef"/>
 	</div>
 </template>
 
 <script>
+import previewVideoDialog from './previewVideoDialog.vue';
 export default {
-	emits:["saveData","saveImage","delImage"],
-	props:{
-		data:{
-			type:Object,
-			default:()=>{
-				return {}
-			}
+	emits: ["saveData", "saveImage", "saveVideo","delImage"],
+	components:{
+		previewVideoDialog
+	},
+	props: {
+		data: {
+			type: Object,
+			default: () => {
+				return {};
+			},
 		},
-		imageList:{
-			type:Object,
-			default:()=>{
-				return {}
-			}
+		imageList: {
+			type: Object,
+			default: () => {
+				return {
+					fileList:[],
+					fileList1:[],
+					fileList2:[],
+					fileList3:[],
+					videoList:[],
+				};
+			},
 		},
 	},
 	data() {
 		return {
 			title: "基本信息",
 			showMain: true,
-			uploadImageLoading:false,
+			uploadImageLoading: false,
+			uploadVideoLoading:false,
 			from: {
 				courseName: "",
 				teacherName: "",
@@ -238,11 +338,11 @@ export default {
 							if (err) {
 								_this.$message.error("上传失败");
 							} else {
-								_this.$emit("saveImage",{
-									name:data.key,
-									status:"success",
-									uid:"1",
-									url:data.Location
+								_this.$emit("saveImage", {
+									name: data.key,
+									status: "success",
+									uid: "1",
+									url: data.Location,
 								});
 								// _this.from.audioUrl = data.Location;
 								// _this.from.audioName = file.name;
@@ -258,15 +358,84 @@ export default {
 			// this.mainBtnStatus = 1;
 			// this.barNum = 4;
 		},
+		// 添加视频
+		addVideo(){
+			let input = document.createElement("input");
+			input.type = "file";
+			input.accept = "video/*";
+			input.click();
+			input.onchange = () => {
+				this.uploadVideoLoading = true;
+				let file = input.files[0];
+				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) {
+							if (err) {
+								_this.$message.error("上传失败");
+							} else {
+								_this.$emit('saveVideo',{
+										name: data.key,
+										status: "success",
+										uid: "1",
+										url: data.Location,
+								})
+							}
+							_this.uploadVideoLoading = false;
+						});
+				}
+			};
+		},
+
 		// 删除图片
-		delImage(key){
-			this.$confirm('确定删除该图片吗?', '提示', {
-				confirmButtonText: '确定',
-				cancelButtonText: '取消',
-				type: 'warning'
+		delImage(key) {
+			this.$confirm("确定删除该图片吗?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "warning",
 			}).then(() => {
-				this.$emit("delImage",key);
-			})
+				this.$emit("delImage", key);
+			});
+		},
+		// 删除视频
+		delVideo(key){
+			this.$confirm("确定删除该视频吗?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "warning",
+			}).then(() => {
+				this.$emit("delImage", key);
+			});
 		},
 		changeShowMain(newValue) {
 			this.showMain = newValue;
@@ -274,13 +443,15 @@ export default {
 		previewImg(url) {
 			this.$hevueImgPreview(url);
 		},
-		changeData(){
+		previewVideo(url){
+			this.$refs.previewVideoDialogRef.open(url)
+			// this.$message.info(`预览:${url}`)
+		},
+		changeData() {
 			this.$emit("saveData");
 		},
 	},
-	mounted(){
-		
-	}
+	mounted() {},
 };
 </script>
 
@@ -289,9 +460,9 @@ export default {
 	width: 100%;
 	height: auto;
 }
-.imgTit{
-  height: 40px;
-  line-height: 40px;
+.imgTit {
+	height: 40px;
+	line-height: 40px;
 }
 .imgTit :first-child {
 	font-size: 16px;
@@ -305,8 +476,7 @@ export default {
 	font-weight: 400;
 	line-height: 20px;
 	text-align: left;
-  color: rgba(0, 0, 0, 0.4);
-
+	color: rgba(0, 0, 0, 0.4);
 }
 .baseInfoLeft {
 	display: flex;
@@ -370,6 +540,14 @@ export default {
 	box-sizing: border-box;
 	display: flex;
 	flex-wrap: wrap;
+	flex-direction: column;
+}
+
+.m-m-form {
+	display: flex;
+	flex-wrap: wrap;
+	width: 100%;
+
 }
 
 .m-m-formItem {
@@ -378,11 +556,13 @@ export default {
 	display: flex;
 	flex-direction: column;
 	align-items: left;
+	margin-top: 10px;
+	margin-right: 1.5%;
 	/* margin-bottom: 10px; */
 }
 
 .m-m-fi-input {
-	width: 100%;
+	max-width: 100%;
 }
 
 .m-m-fi-label {
@@ -418,7 +598,7 @@ export default {
 	background-color: rgba(238, 238, 238, 1);
 	width: 140px;
 	height: 100px;
-	margin-right: 10px;
+	margin-right: 1%;
 	display: flex;
 	justify-content: center;
 	align-items: center;
@@ -427,14 +607,15 @@ export default {
 	font-size: 14px;
 	cursor: pointer;
 	position: relative;
+	margin-bottom: 10px;
 }
 .m-m-fi-imageItem > .itemUrl {
 	width: 100%;
 	height: 100%;
 }
 
-.m-m-fi-imageItem>span{
-	width:30px;
+.m-m-fi-imageItem > span {
+	width: 30px;
 	height: 30px;
 	position: absolute;
 	right: 0;
@@ -451,7 +632,7 @@ export default {
 	display: none;
 }
 
-.m-m-fi-imageItem:hover>span{
+.m-m-fi-imageItem:hover > span {
 	display: flex;
 }
 
@@ -478,4 +659,21 @@ export default {
 	cursor: pointer;
 	padding: 0 10px;
 }
+
+.fileList{
+	width: 100%;
+	position: relative;
+	display: flex;
+}
+
+.fl_img{
+	width: 50%;
+	height: auto;
+}
+
+.fl_video{
+	width: 48.5%;
+	margin-left: 1.5%;
+	height: auto;
+}
 </style>

+ 14 - 2
src/components/pages/classroomObservation/components/chatArea.vue

@@ -1055,6 +1055,8 @@ export default {
 					_this.editorBarData.type = "0";
 					flag = false;
 					_this.uploadFileLoading = false;
+					_this.transcriptionData.content = ""
+					_this.editorBarData.content = ""
 				}
 				_this.showGetTextLoading = true;
 				let privText = e.privText;
@@ -1088,6 +1090,7 @@ export default {
 			var _this = this;
 
 			if (file) {
+				this.loading = true;
 				var params = {
 					Key:
 						file.name.split(".")[0] +
@@ -1114,6 +1117,7 @@ export default {
 						if (err) {
 							_this.$message.error("上传失败");
 							_this.uploadFileLoading = false;
+							_this.loading = false;
 						} else {
 							// 判断是不是音频文件
 							const audioRegex = /\.(mp3|wav|ogg|flac|m4a)$/i;
@@ -1134,6 +1138,7 @@ export default {
 							if (audioRegex.test(data.Location)) {
 								_this.wavFileGetText(file);
 								_this.$emit("changeAudioUrl", data);
+								_this.loading = false;
 								return;
 							}
 							_this.ajax
@@ -1169,7 +1174,7 @@ export default {
 											_this.saveEditorBar();
 											// console.log("pdf、xlsx、doc、docx文件处理");
 										}
-
+										_this.loading = false;
 										if (!_this.fileIdId) return;
 										let pram2 = {
 											id: _this.fileIdId,
@@ -1289,9 +1294,13 @@ export default {
 			}
 		},
 		getData() {
+			this.loading = true;
 			this.getRoleList();
 			this.getPublicRoleList();
-			this.getChatList().then((_) => this.scrollBottom());
+			this.getChatList().then((_) => {
+				this.loading = false;
+				this.scrollBottom()
+			});
 		},
 		// 保存转录文稿和原文速览
 		saveEditorBar(flag = false) {
@@ -1305,9 +1314,12 @@ export default {
 				blob.name = `${this.tid}-classroomObservation.txt`;
 				this.uploadFile(blob);
 			} else {
+				this.loading = true;
 				this.$emit("updateTranscription", {
 					transcriptionData: this.transcriptionData.content,
 					editorBarData: this.editorBarData,
+				},()=>{
+					this.loading = false;
 				});
 			}
 		},

+ 141 - 28
src/components/pages/classroomObservation/components/messageArea.vue

@@ -23,6 +23,7 @@
 				:imageList="imageList.jsonData"
 				@saveData="saveBaseData"
 				@saveImage="saveBaseImage"
+				@saveVideo="saveBaseVideo"
 				@delImage="delBaseImageList"
 				v-loading="baseMessageLoading"
 			/>
@@ -30,8 +31,10 @@
 			<analysis
 				@updateMessage="updateMessage"
 				ref="analysis0"
+				:showBrief="showBrief"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
+				@saveItem="saveAnalysis"
 				title="通用课堂分析"
 				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 0)"
@@ -43,9 +46,11 @@
 			<analysis
 				@updateMessage="updateMessage"
 				ref="analysis1"
+				:showBrief="showBrief"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
-				title="科学课堂分析"
+				@saveItem="saveAnalysis"
+				title="学科课堂分析"
 				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 1)"
 				:type="1"
@@ -56,8 +61,10 @@
 			<analysis
 				@updateMessage="updateMessage"
 				ref="analysis2"
+				:showBrief="showBrief"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
+				@saveItem="saveAnalysis"
 				title="扩展分析"
 				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 2)"
@@ -69,6 +76,7 @@
 			<!-- <analysis
 				@updateMessage="updateMessage"
 				ref="analysis3"
+				:showBrief="showBrief"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
 				title="增值性分析"
@@ -110,7 +118,7 @@
 			/> -->
 			<!-- <div style="height: 10000px;"></div> -->
 		</div>
-		<el-dialog :center="true" :visible.sync="dialogVisible" width="1200px">
+		<el-dialog :center="true" :visible.sync="dialogVisible" width="1200px" class="addTemplateDialog">
 			<!-- <div v-if="showDialog == true" class="a-dialog" v-el-drag-dialog> -->
 			<div class="a-d-top">
 				<div class="a-d-topTit"><div style="width: 136px">添加模块</div></div>
@@ -145,6 +153,10 @@
 					</div>
 				</div>
 				<div class="a-d-box">
+					<div class="a-d-b-subject">
+						<el-button :type="tagSubject==item?'primary':'default'" v-for="(item,index) in tagSubjectList" :key="index+'-'+tagIndex" @click.stop="tagSubject=item">{{ item }}</el-button>
+						<!-- {{ tagSubjectList }} -->
+					</div>
 					<div
 						style="
 							font-family: PingFang SC;
@@ -234,6 +246,7 @@ export default {
 			showBrief: true, //是否显示模块简介
 			dialogVisible: false,
 			tagIndex: 0,
+			tagSubject:'',
 			loading: false,
 			baseMessageLoading: false,
 			currencyLoading: false,
@@ -243,7 +256,7 @@ export default {
 			input2: "",
 			dialogTagList: [
 				{ id: 0, name: "通用课堂分析" },
-				{ id: 1, name: "学课堂分析" },
+				{ id: 1, name: "学课堂分析" },
 				{ id: 2, name: "扩展分析" },
 				//{ id: 3, name: "增值性分析" },
 			],
@@ -264,21 +277,21 @@ export default {
 				},
 				{
 					title: "布鲁姆问题分类",
-					brief: "多维度分析课堂整体情况",
+					brief: "不同认知层次问题分布情况",
 					value: "eac63117-00a7-11ef-aaca-12e77c4cb76b",
 					type: 0,
 					sum:405
 				},
 				{
 					title: "麦卡锡问题分类",
-					brief: "多维度分析课堂整体情况",
+					brief: "不同类型问题分布情况",
 					value: "18545cf7-0125-11ef-aaca-12e77c4cb76b",
 					type: 0,
 					sum:360
 				},
 				{
 					title: "学生回答情况",
-					brief: "多维度分析课堂整体情况",
+					brief: "学生回答情况分析",
 					value: "d3f75199-eb4e-11ee-aaca-12e77c4cb76b",
 					type: 0,
 					sum:206
@@ -300,43 +313,49 @@ export default {
 				// },
 				{
 					title: "课堂活动类型",
-					brief: "多维度分析课堂整体情况",
+					brief: "识别特定的课堂活动类型",
 					value: "41d2d2d4-0125-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:430
 				},
 				{
 					title: "学科核心素养发展",
-					brief: "学科核心素养发展",
+					brief: "分析与学科核心素养的匹配情况",
 					value: "b13a98de-0125-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:234
 				},
 				{
 					title: "科学教育目标分析",
-					brief: "科学教育目标分析",
+					brief: "分析四类科学教育目标的情况",
 					value: "b13a98de-0125-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:513
 				},
 				{
 					title: "PORTAAL课堂观察",
-					brief: "PORTAAL课堂观察",
+					brief: "使用PORTAAL框架分析科学课堂",
 					value: "8ab07d41-e143-11ee-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:173
 				},
 				{
 					title: "UTOP课堂观察",
-					brief: "UTOP课堂观察",
+					brief: "使用UTOP框架分析科学课堂",
 					value: "8e3a389b-014f-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:329
 				},
 				{
 					title:"L-PST模型",
-					brief: "L-PST模型",
+					brief: "使用L-PST框架分析科学课堂",
 					value: "e649112e-0150-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:421
 				},
@@ -348,8 +367,9 @@ export default {
 				// },
 				{
 					title: "RTOP课堂观察",
-					brief: "多维度分析课堂整体情况",
+					brief: "使用RTOP框架分析科学课堂",
 					value: "68265b18-0151-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:527
 				},
@@ -357,26 +377,84 @@ export default {
 					title: "课程质量评价",
 					brief: "多维度分析课堂整体情况", 
 				 	value:"25e53379-0152-11ef-aaca-12e77c4cb76b",
+					 subject:"科学",
 					type: 1,
 					sum:391
 				},
 				{
 					title: "SCOP课堂观察",
-					brief: "多维度分析课堂整体情况",
+					brief: "使用SCOP框架分析科学课堂",
 					value: "d0c76d35-0152-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:407
 				},
+				{
+					title:"KWL教学策略",
+					brief:"分析课前、课中、课后的教学成果",
+					value:"a5d8664b-1748-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:135
+				},
+				{
+					title:"LICC课堂观察",
+					brief:"崔允漷教授团队的观察框架",
+					value:"9e8e6356-1769-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:614
+				},
+				{
+					title:"读思达教学法",
+					brief:"分析课堂阅读、思考、表达的情况",
+					value:"d139ed78-176c-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:346
+				},
+				{
+					title:"教学内容分析",
+					brief:"从教学内容角度观课评教",
+					value:"9e8e6356-1769-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:527
+				},
+				{
+					title:"提问策略分析",
+					brief:"基于提问观察表分析课堂提问",
+					value:"eb815b01-1769-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:389
+				},
+				{
+					title:"教师反馈分析",
+					brief:"分析语文课堂师生言语互动行为",
+					value:"55ae5176-176a-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:319
+				},
+				{
+					title:"师生互动分析",
+					brief:"分析语文课堂四种不同的互动状态",
+					value:"8e4b6b48-176a-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:191
+				},
 				{
 					title: "5E课程改编",
-					brief: "5E课程改编",
+					brief: "基于5E教学模型设计一堂课",
 					value: "f757826e-0125-11ef-aaca-12e77c4cb76b",
 					type: 2,
 					sum:510
 				},
 				{
 					title: "5EX课程改编",
-					brief: "5EX课程改编",
+					brief: "基于5EX教学模型设计一堂课",
 					value: "0b6b08b7-0126-11ef-aaca-12e77c4cb76b",
 					type: 2,
 					sum:611
@@ -390,13 +468,30 @@ export default {
 	},
 	computed: {
 		searchDataList() {
-			let _data = this.dialogTagDataList.filter((i) => i.type == this.tagIndex);
+			let _result = this.dialogTagDataList.filter((i) => i.type == this.tagIndex);
 			if (this.input2) {
-				return _data.filter((i) => i.title.indexOf(this.input2) > -1);
-			} else {
-				return _data;
+				_result = _result.filter((i) => i.title.indexOf(this.input2) > -1);
 			}
+			if(this.tagSubject){
+				_result = _result.filter((i) => i.subject == this.tagSubject);
+			}
+
+			return _result
 		},
+		tagSubjectList(){
+			let _result = [];
+			this.dialogTagDataList.filter((i) => i.type == this.tagIndex).forEach(i=>{
+				if(i.subject && !_result.includes(i.subject)){
+					_result.push(i.subject)
+				}
+			})
+			return _result;
+		}
+	},
+	watch:{
+		tagIndex(){
+			this.tagSubject = ''
+		}
 	},
 	methods: {
 		delAnalysisItem(id) {
@@ -425,7 +520,7 @@ export default {
 			let _index = this.dataList.findIndex((i) => i.id == id);
 			if (_index != -1) {
 				this.dataList[_index] = _data;
-				this.saveData(this.dataList[_index])
+				// this.saveData(this.dataList[_index])
 				this.$forceUpdate();
 			} else {
 				this.$message.info("执行错误");
@@ -671,6 +766,14 @@ export default {
 					console.log(e)
 				});
 		},
+		saveAnalysis(id,_data){
+			let data = this.dataList.find(i=>i.id==id);
+			if(data){
+				this.saveData(data).then(()=>{
+					this.$message.success("保存成功");
+				})
+			}
+		},
 		getData() {
 			this.dataList = [];
 			this.getCurrencyAndBaseMessageData();
@@ -758,6 +861,17 @@ export default {
 			this.imageList.json_data = JSON.stringify(this.imageList.jsonData);
 			this.saveData(this.imageList);
 		},
+		saveBaseVideo(newVideo){
+			if((this.imageList.jsonData.videoList && this.imageList.jsonData.videoList.length==0) || !this.imageList.jsonData.videoList){
+				this.imageList.jsonData.videoList = [];
+				this.imageList.jsonData.videoList.push(newVideo)
+			}else{
+				this.$message.error("最多只能上传3张图片");
+				return;
+			}
+			this.imageList.json_data = JSON.stringify(this.imageList.jsonData);
+			this.saveData(this.imageList);
+		},
 		delBaseImageList(key){
 			this.imageList.jsonData[key] = [];
 			this.imageList.json_data = JSON.stringify(this.imageList.jsonData);
@@ -815,6 +929,7 @@ export default {
 						fileList1: [],
 						fileList2: [],
 						fileList3: [],
+						videoList:[],
 					}),
 				};
 				this.ajax
@@ -842,17 +957,15 @@ export default {
 			});
 		},
 		// 修改基本信息的原文速览和转录文稿
-		updateMessageTranscription({transcriptionData,editorBarData}){
+		updateMessageTranscription({transcriptionData,editorBarData},fn){
 			this.bmData.jsonData['transcriptionData'] = transcriptionData;
 			this.bmData.jsonData['editorBarData'] = editorBarData;
 			this.saveData(this.bmData).then(res=>{
 				this.$message.success("保存成功");
+				fn?fn():'';
 			})
 		},
 	},
-	mounted() {
-		
-	},
 };
 </script>
 
@@ -1113,7 +1226,7 @@ export default {
 	align-items: center;
 	cursor: pointer;
 }
-.messageArea >>> .el-dialog {
+.addTemplateDialog >>> .el-dialog {
 	min-width: 1200px;
 
 	height: 700px;
@@ -1124,7 +1237,7 @@ export default {
 	/* margin: 0 auto; */
 	overflow: hidden;
 }
-.messageArea >>> .el-dialog__body {
+.addTemplateDialog >>> .el-dialog__body {
 	height: 100%;
 	min-width: 1200px;
 	flex-shrink: 0;
@@ -1132,7 +1245,7 @@ export default {
 	padding-bottom: 50px;
 	padding-top: 10px;
 }
-.messageArea >>> .el-dialog__header {
+.addTemplateDialog >>> .el-dialog__header {
 	display: none;
 }
 .itemTit {

+ 103 - 0
src/components/pages/classroomObservation/components/previewVideoDialog.vue

@@ -0,0 +1,103 @@
+<template>
+    <!-- <el-dialog
+      title="视频预览"
+      :visible.sync="dialogVisible"
+
+    >
+		<video-player
+			v-if="option.url"
+      style="width: 100%;height: 100%;"
+      :playsinline="true"
+      :options="option"
+    ></video-player>
+    </el-dialog> -->
+
+		<el-dialog
+		  title="视频预览"
+		  :visible.sync="dialogVisible"
+			show-close
+			top="3vh"
+			width="60vw"
+			:before-close="handleClose">
+			<div class="video-player-box" v-if="option.sources!=''">
+				<video-player
+    	  style="width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;"
+    	  :playsinline="true"
+    	  :options="option"
+    	></video-player>
+			</div>
+		  <span slot="footer" class="dialog-footer">
+		    <el-button @click="close()">取 消</el-button>
+		    <el-button type="primary" @click="close()">确 定</el-button>
+		  </span>
+		</el-dialog>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      dialogVisible: false,
+      loading: false,
+      option:{
+				playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
+        autoplay: false, //如果true,浏览器准备好时开始回放。
+        muted: false, // 默认情况下将会消除任何音频。
+        loop: false, // 导致视频一结束就重新开始。
+        preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+        language: 'zh-CN',
+        aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+        fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+        sources: "",
+        // poster: "https://p1.music.126.net/5zs7IvmLv7KahY3BFzUmrg==/109951163635241613.jpg?param=600y500", // 你的封面地址
+        notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
+        controlBar: {
+            timeDivider: true,
+            durationDisplay: true,
+            remainingTimeDisplay: false,
+            fullscreenToggle: true  // 全屏按钮
+        }
+
+			}
+    };
+  },
+  watch: {
+    
+  },
+  methods: {
+    open(url) {
+      this.dialogVisible = true;
+			this.option.sources = url;
+    },
+    close() {
+      this.dialogVisible = false;
+      this.option.sources = "";
+    },
+		handleClose(){
+			this.close();
+		}
+  }
+};
+</script>
+
+<style scoped>
+
+.video-player-box{
+	width: 100%;
+	height: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.video-player-box >>> .video-js{
+	width: 100%;
+	height: 100%;
+}
+
+.video-player-box >>> .vjs-big-play-button{
+	top: 50%;
+	left: 50%;
+	transform: translate(-50%, -50%);
+}
+</style>

+ 34 - 12
src/components/pages/classroomObservation/index.vue

@@ -52,25 +52,32 @@
 			</div>
 			<div class="co-h2-right">
 				<div
-					class="co-h2-r-btn co-h2-r-blueBtn"
+					:class="['co-h2-r-btn',fileId?'':'ca-h2-r-noActive']"
 					style="background: rgba(54, 129, 252, 1)"
 					@click.stop="getReport()"
 				>
 					<span class="co-h2-r-b-icon1"></span>
-					<div>生成报告</div>
+					<div style="color:white">一键分析</div>
 				</div>
-				<div class="co-h2-r-btn2" @click.stop="preview()">
-					<!-- <span class="co-h2-r-b-icon2"></span> -->
+
+				<div
+				:class="['co-h2-r-btn',fileId?'':'ca-h2-r-noActive']"
+					style="background: #FFFFFF"
+					@click.stop="preview()"
+				>
+					<span class="co-h2-r-b-icon2"></span>
+					<div style="color:black">查看报告</div>
+				</div>
+				<!-- <div class="co-h2-r-btn2" @click.stop="preview()">
 					<el-tooltip class="item" effect="light" content="预览" placement="top">
 						<img
 						src="../../../assets/icon/classroomObservation/Syan.png"
 						alt=""
 					/>
     			</el-tooltip>
-					
-					<!-- <div>预览</div> -->
-				</div>
-				<div class="co-h2-r-btn2" @click.stop="shareBtn">
+				</div> -->
+
+				<div :class="['co-h2-r-btn2']" @click.stop="shareBtn">
 					<!-- <span class="co-h2-r-b-icon3"></span> -->
 					<el-tooltip class="item" effect="light" content="分享" placement="top">
 						<img
@@ -206,6 +213,7 @@ export default {
 		},
 		// 生成报告
 		getReport() {
+			if(!this.fileId)return;
 			this.$refs.messageAreaRef.getReport();
 			// let assistant_title = [
 			// 	"课堂观察",
@@ -245,6 +253,7 @@ export default {
 		},
 		//预览
 		preview() {
+			if(!this.fileId)return;
 			window.parent.postMessage(
 				{
 					tools: "classroom_observation_board",
@@ -255,6 +264,7 @@ export default {
 		},
 		// 分享
 		shareBtn() {
+			// if(!this.fileId)return;
 			this.dialogVisibleShare = !this.dialogVisibleShare;
 		},
 		delCourse(_value = this.tid) {
@@ -339,11 +349,11 @@ export default {
 					});
 			});
 		},
-		updateTranscription({ transcriptionData, editorBarData }) {
+		updateTranscription({ transcriptionData, editorBarData },fn) {
 			this.$refs.messageAreaRef.updateMessageTranscription({
 				transcriptionData,
 				editorBarData,
-			});
+			},fn);
 		},
 		changeTranscription({ transcriptionData, editorBarData }) {
 			this.$refs.chatAreaRef.changeEditorBar({
@@ -498,6 +508,12 @@ export default {
 	/* border: solid 1px #3681FC; */
 	border-radius: 5px;
 }
+
+.ca-h2-r-noActive{
+	opacity: .5 !important; 
+	cursor: not-allowed !important;
+}
+
 .co-h2-r-btn2 {
 	width: auto;
 	box-sizing: border-box;
@@ -525,6 +541,12 @@ export default {
 	background-size: 100% 100%;
 }
 
+.co-h2-r-b-icon2{
+	background: url("../../../assets/icon/classroomObservation/Syan.png")
+		no-repeat;
+	background-size: 100% 100%;
+}
+
 /* .co-h2-r-b-icon2 {
 	background: url("../../../assets/icon/classroomObservation/daoChu.png")
 		no-repeat;
@@ -536,11 +558,11 @@ export default {
 	background-size: 100% 100%;
 } */
 
-.co-h2-r-blueBtn {
+/* .co-h2-r-blueBtn {
 	background: rgba(134, 179, 253, 1);
 
 	color: white;
-}
+} */
 
 .co-main {
 	width: 100%;