瀏覽代碼

Merge branch 'beta'

lsc 1 年之前
父節點
當前提交
c68a710fee

+ 1 - 1
dist/index.html

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

文件差異過大導致無法顯示
+ 0 - 0
dist/static/css/app.4a6e7c42dffade1c5647ca014e51fde0.css


文件差異過大導致無法顯示
+ 0 - 0
dist/static/css/app.4a6e7c42dffade1c5647ca014e51fde0.css.map


文件差異過大導致無法顯示
+ 0 - 0
dist/static/css/app.891bb6bf31f3e8ca8e28a339110d7756.css


文件差異過大導致無法顯示
+ 0 - 0
dist/static/js/app.97191fc9c56a3ed9016c.js


文件差異過大導致無法顯示
+ 0 - 0
dist/static/js/app.97191fc9c56a3ed9016c.js.map


文件差異過大導致無法顯示
+ 0 - 0
dist/static/js/manifest.571c38d63f24b1ae9e16.js.map


+ 24 - 0
src/assets/icon/classroomObservation/generate.svg

@@ -0,0 +1,24 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_596_2943)">
+<path d="M5.13724 5.78772C5.03644 6.20372 4.98295 6.63824 4.98295 7.08532C4.98295 9.22704 6.21038 11.0821 8.0001 11.9854C7.25816 12.3601 6.41953 12.571 5.53153 12.571C4.57518 12.571 3.67621 12.3262 2.89313 11.8961L2.59941 11.435C1.96673 10.4426 1.6001 9.26384 1.6001 7.99961C1.6001 4.90429 3.79758 2.32212 6.71758 1.7283C7.13198 1.64395 7.56078 1.59961 8.0001 1.59961C8.43941 1.59961 8.86821 1.64395 9.28261 1.7283C8.83187 1.8275 8.4017 1.98224 8.0001 2.18521C6.58387 2.89995 5.51987 4.21058 5.13724 5.78772Z" fill="url(#paint0_linear_596_2943)"/>
+<path d="M13.4008 11.4353C13.4568 11.1214 13.4858 10.7982 13.4858 10.4684C13.4858 8.48783 12.4362 6.75252 10.8629 5.78794C10.0296 5.27709 9.04921 4.98269 8.00006 4.98269C6.95092 4.98269 5.97058 5.27709 5.13721 5.78794C5.51984 4.2108 6.58384 2.90017 8.00006 2.18543C8.40166 1.98246 8.83184 1.82772 9.28258 1.72852C12.2026 2.32234 14.4001 4.90452 14.4001 7.99983C14.4001 9.26406 14.0334 10.4428 13.4008 11.4353Z" fill="url(#paint1_linear_596_2943)"/>
+<path d="M13.4861 10.4676C13.4861 10.8182 13.4534 11.1611 13.3901 11.4934L13.0563 11.9231C11.8856 13.4296 10.0561 14.399 8.00034 14.399C5.94456 14.399 4.11508 13.4296 2.94434 11.9231C3.71531 12.3361 4.59622 12.5704 5.53176 12.5704C6.46731 12.5704 7.25839 12.3595 8.00034 11.9848C9.79005 11.0815 11.0175 9.22642 11.0175 7.08471C11.0175 6.63762 10.964 6.20311 10.8632 5.78711C12.4365 6.75168 13.4861 8.487 13.4861 10.4676Z" fill="url(#paint2_linear_596_2943)"/>
+</g>
+<defs>
+<linearGradient id="paint0_linear_596_2943" x1="2.2321" y1="11.235" x2="10.5107" y2="2.95641" gradientUnits="userSpaceOnUse">
+<stop stop-color="#364EE7"/>
+<stop offset="1" stop-color="#938DFF"/>
+</linearGradient>
+<linearGradient id="paint1_linear_596_2943" x1="6.99824" y1="2.798" x2="14.518" y2="10.318" gradientUnits="userSpaceOnUse">
+<stop stop-color="#364EE7"/>
+<stop offset="1" stop-color="#2CCAFF"/>
+</linearGradient>
+<linearGradient id="paint2_linear_596_2943" x1="11.4051" y1="6.10002" x2="6.53108" y2="14.5421" gradientUnits="userSpaceOnUse">
+<stop stop-color="#364EE7"/>
+<stop offset="1" stop-color="#4DE69A"/>
+</linearGradient>
+<clipPath id="clip0_596_2943">
+<rect width="12.8" height="12.8" fill="white" transform="translate(1.6001 1.59961)"/>
+</clipPath>
+</defs>
+</svg>

+ 3 - 0
src/assets/icon/classroomObservation/success.svg

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M6.82591 11.9987C6.66084 11.9987 6.50208 11.937 6.38237 11.8248L2.96638 8.63944C2.71059 8.40129 2.70177 8.00563 2.94622 7.75615C3.19067 7.50666 3.59767 7.4991 3.85346 7.73724L6.77047 10.4577L12.0614 4.19651C12.287 3.93064 12.6914 3.89158 12.9649 4.11083C13.2383 4.33008 13.2774 4.72321 13.0531 4.99034L7.32237 11.7719C7.20896 11.9067 7.04264 11.9886 6.86497 11.9987H6.82591Z" fill="#17C469"/>
+</svg>

+ 9 - 5
src/components/pages/aiAddCourse/addCourse.vue

@@ -3649,7 +3649,7 @@
                     }">
                       {{ steps == 3 ? "确认上传" : "下一步" }}
                     </button>
-                    <button class="c_pub_button_confirm" v-if="steps < 4" @click="openSaveTips">保存模板</button>
+                    <button class="c_pub_button_confirm" v-if="steps < 4 && cidType != 1 && templateid == ''" @click="openSaveTips">保存模板</button>
                   </div>
                 </div>
               </div>
@@ -5435,7 +5435,7 @@ export default {
       aitype: "",
       aiJson: {
         aiDetail:"请根据<课程简要描述>设计一个名为<课程名字>的<课程学科>学科的,面向<面向年级>的项目式学习课程。",
-        aiOutline:"请根据<课程简要描述>及#补充参考资料为这个名为<课程名字>的<课程学科>学科的,面向<面向年级>的项目式学习课程设计序列教学活动(需要每个任务都需要至少50个token的详细描述),每个教学活动的活动设计(可以直接使用文件内容)以及每个教学活动的评价量规(学生能做到...)。",
+        aiOutline:`请为这个名为<课程名字>的<课程学科>学科的,面向<面向年级>学生,时长为<课堂时长>一堂课来设计课堂教学任务(每个任务都需要至少50个token的详细描述)。该课堂的课堂简要描述为<课程简要描述>。每个教学活动的活动设计(可以直接使用文件内容)以及每个教学活动的评价量规(学生能做到...)。`,
         aiTask:"请根据<教学任务教案>。",
         aiDetail1:"请根据<课程描述>,重新设计该教学任务。任务需要至少50个token的详细描述,包含任务设计,评价标准。",
         aiDetail2:"请你在考虑到整个课程的情况下,优化该任务描述和任务名:<任务名>:<任务描述>",
@@ -5448,7 +5448,7 @@ export default {
       aiCallBack: "",
       aiIndex: "",
       clickType: 1,
-      promptShow: true,
+      promptShow: false,
       templateid: this.$route.query.templateid != undefined ? this.$route.query.templateid : "",
       dialogVisibleTips: false,
       tipsJson: {}
@@ -10618,6 +10618,9 @@ export default {
             console.error(err);
           });
       }
+      if(this.cidType != 1 && this.templateid == ''){
+        this.promptShow = true
+      }
     },
     seleteCourseUpdate() {
       let params = {
@@ -12592,8 +12595,6 @@ ${msg} **你需要使用C-POTE教学活动设计框架,其定义参考#补充
 
 
 ## 补充参考资料
-C-POTE定义:
-C-POTE模型是一种针对跨学科主题学习的教学设计模型,它是在新课标导向下提出的,旨在帮助教师更好地开展跨学科主题学习活动。C-POTE模型的核心是以大概念为基础,以核心素养为导向,通过合理部署内容组织、问题设计、目标制定、任务设计、教学评价等环节,促进学生的深度学习和创新能力的发展。C-POTE模型的名称来源于其五个核心组成部分,分别是:概念群(Concept Group):作为模型的基础,概念群负责将不同学科的知识点进行整合,形成有意义的认知网络。教师需要遴选重要的大概念,使之形成更大的跨学科概念群,为后续的教学活动奠定基础。问题链(Problem Chain):围绕大概念设计一系列有逻辑结构的问题,从具体到抽象,形成问题链。问题链的目的是引导学生通过问题解决的过程深化对大概念的理解。目标层(Objective Layer):明确教学目标,将核心素养具体化,分为“双基—学科思维—高阶素养”三个层次。教师需要根据学科课程标准中的核心素养,将其转化为具体的教学目标。任务簇(Task Cluster):设计一系列指向核心素养的表现性任务,将大任务拆解为若干个活动序列,确保学生能够通过实践活动实现学习目标。证据集(Evidence Set):评价学生学习成果的依据,通过收集学生在跨学科实践过程中的表现证据,进行综合性评价,以促进学生核心素养的发展。
 补充资料:${url.join(",")}
 补充描述:${this.courseText2}
 
@@ -13087,6 +13088,9 @@ ${message} 以及##补充参考资料和##参考资料 以文本格式输出项
               )
             }
           }
+          if (_this.infoData.length) {
+            _this.unitJson[0].chapterInfo[0].taskJson[0].chapterData = JSON.parse(JSON.stringify(_this.infoData))
+          }
           _this.unitJson2 = JSON.parse(JSON.stringify(_this.unitJson))
           _this.$forceUpdate();
         }

+ 2 - 4
src/components/pages/aiAddCourse/addCourse3.vue

@@ -5435,7 +5435,7 @@ export default {
       aitype: "",
       aiJson: {
         aiDetail:"请根据<课程简要描述>设计一个名为<课程名字>的<课程学科>学科的,面向<面向年级>的项目式学习课程。",
-        aiOutline:"请根据<课程简要描述>及#补充参考资料为这个名为<课程名字>的<课程学科>学科的,面向<面向年级>的项目式学习课程设计序列教学活动(需要每个任务都需要至少50个token的详细描述),每个教学活动的活动设计(可以直接使用文件内容)以及每个教学活动的评价量规(学生能做到...)。",
+        aiOutline:`请为这个名为<课程名字>的<课程学科>学科的,面向<面向年级>学生,时长为<课堂时长>一堂课来设计课堂教学任务(每个任务都需要至少50个token的详细描述)。该课堂的课堂简要描述为<课程简要描述>。每个教学活动的活动设计(可以直接使用文件内容)以及每个教学活动的评价量规(学生能做到...)。`,
         aiTask:"请根据<教学任务教案>。",
         aiDetail1:"请根据<课程描述>,重新设计该教学任务。任务需要至少50个token的详细描述,包含任务设计,评价标准。",
         aiDetail2:"请你在考虑到整个课程的情况下,优化该任务描述和任务名:<任务名>:<任务描述>",
@@ -12583,7 +12583,7 @@ User: Please generate a recipe for chocolate chip cookies in JSON format.
 
 # Context
 ## 要求 
-${msg} **你需要使用C-POTE教学活动设计框架,其定义参考#补充参考资料 中的C-POTE**。以及##补充参考资料和##参考资料,
+${msg} 以及##补充参考资料和##参考资料,
 然后根据Format example的要求返回要以数组的格式
 
 ## 参考资料
@@ -12594,8 +12594,6 @@ ${msg} **你需要使用C-POTE教学活动设计框架,其定义参考#补充
 
 
 ## 补充参考资料
-C-POTE定义:
-C-POTE模型是一种针对跨学科主题学习的教学设计模型,它是在新课标导向下提出的,旨在帮助教师更好地开展跨学科主题学习活动。C-POTE模型的核心是以大概念为基础,以核心素养为导向,通过合理部署内容组织、问题设计、目标制定、任务设计、教学评价等环节,促进学生的深度学习和创新能力的发展。C-POTE模型的名称来源于其五个核心组成部分,分别是:概念群(Concept Group):作为模型的基础,概念群负责将不同学科的知识点进行整合,形成有意义的认知网络。教师需要遴选重要的大概念,使之形成更大的跨学科概念群,为后续的教学活动奠定基础。问题链(Problem Chain):围绕大概念设计一系列有逻辑结构的问题,从具体到抽象,形成问题链。问题链的目的是引导学生通过问题解决的过程深化对大概念的理解。目标层(Objective Layer):明确教学目标,将核心素养具体化,分为“双基—学科思维—高阶素养”三个层次。教师需要根据学科课程标准中的核心素养,将其转化为具体的教学目标。任务簇(Task Cluster):设计一系列指向核心素养的表现性任务,将大任务拆解为若干个活动序列,确保学生能够通过实践活动实现学习目标。证据集(Evidence Set):评价学生学习成果的依据,通过收集学生在跨学科实践过程中的表现证据,进行综合性评价,以促进学生核心素养的发展。
 补充资料:${url.join(",")}
 补充描述:${this.courseText2}
 

+ 9 - 3
src/components/pages/aiAddCourse/templateDialog.vue

@@ -41,9 +41,15 @@
                         <div class="a-d-b-i-top">
                             <img style="height: 22px; width: 22px" :src="require('../../../assets/icon/classroomObservation/digImg.svg')
                                 " />
-                            <div class="a-d-b-i-t-title">{{ item.name }}</div>
+                            <el-tooltip :content="item.name" placement="top" effect="dark">
+                                <!-- content to trigger tooltip here -->
+                                <div class="a-d-b-i-t-title">{{ item.name }}</div>
+                            </el-tooltip>
                         </div>
-                        <div class="a-d-b-i-bottom">{{ item.detail }}</div>
+                        <div class="a-d-b-i-top" v-if="item.uname">创建人:{{ item.uname }}</div>
+                        <el-tooltip :content="item.detail" placement="top" effect="dark">
+                            <div class="a-d-b-i-bottom">{{ item.detail }}</div>
+                        </el-tooltip>
                         <div class="a-d-b-i-bottomBtn">
                             <div style="
 										display: flex;
@@ -360,7 +366,7 @@ export default {
     width: 100%;
     /* height: 50%; */
     height: 20px;
-    margin-bottom: 15px;
+    margin-bottom: 5px;
     display: flex;
     align-items: center;
     /* justify-content: space-between; */

+ 43 - 3
src/components/pages/classroomObservation/components/analysisItem.vue

@@ -8,14 +8,21 @@
 				<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 style="width: 100px;" class="generateError" v-if="loadNum == 2"
 					>优化失败
 				</span>
 				<span
-					:class="loading ? 'text1' : 'text2'"
 					style="width: 100px"
 					v-if="loadNum == 1"
-					>{{ loading ? "优化中..." : "优化完成" }}
+					>
+					<span v-if="loading" class="generate">
+						<img :src="require('../../../../assets/icon/classroomObservation/generate.svg')">
+						生成中...
+					</span>
+					<span v-else class="generateSuccess">           
+						<img :src="require('../../../../assets/icon/classroomObservation/success.svg')">
+						生成完成
+					</span>
 				</span>
 				<span
 					v-if="loadNum == 0 && !openItem"
@@ -515,4 +522,37 @@ td,
 th {
 	padding: 10px;
 }
+
+.generate{
+	color: #00000099;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+
+.generate>img{
+	margin-right: 5px;
+	width: 20px;
+	height: 20px;
+}
+
+.generateSuccess{ 
+	color: #17C469;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+
+.generateSuccess>img{
+	margin-right: 5px;
+	width: 20px;
+	height: 20px;
+}
+
+.generateError{
+	color: #e60012;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
 </style>

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

@@ -170,6 +170,7 @@
 					<div class="m-m-formImage" v-loading="uploadVideoLoading">
 								<div
 									class="m-m-fi-imageItem"
+									style="max-width:33%;"
 									v-for="(item, index) in imageList.videoList?imageList.videoList:[]"
 									:key="index"
 									@click.stop="previewVideo(item.url)"
@@ -186,6 +187,7 @@
 							<div
 								class="m-m-fi-imageItem"
 								@click.stop="addVideo()"
+								style="max-width:33%;"
 								v-if="
 									(imageList.videoList&&imageList.videoList.length<=0) || !imageList.videoList
 								"

+ 340 - 0
src/components/pages/classroomObservation/components/bindingFormDialog.vue

@@ -0,0 +1,340 @@
+<template>
+	<div>
+		<el-dialog
+			:center="true"
+			:visible.sync="dialogVisible"
+			width="800px"
+			class="bindingFormDialog"
+		>
+			<div class="a-d-top">
+				<div class="a-d-topTit">
+					<div>绑定表单</div>
+				</div>
+				<div class="a_d_t_input">
+					<el-input
+						placeholder="请输入标题"
+						prefix-icon="el-icon-search"
+						v-model="text"
+						@submit.native.prevent="search()"
+						clearable
+					>
+					</el-input>
+					<el-button
+						size="mini"
+						:disabled="loading"
+						style="margin-left: 10px"
+						@click="search()"
+						type="primary"
+						>搜索</el-button
+					>
+				</div>
+				<div class="a-d-t-right">
+					<span @click.stop="dialogVisible = false">×</span>
+				</div>
+			</div>
+			<div class="bfd_box" v-loading="loading">
+				<el-table :data="list" border>
+					<el-table-column
+						prop="title"
+						label="标题"
+						style="width: 33%"
+						align="center"
+					>
+					</el-table-column>
+					<el-table-column
+						prop="uname"
+						label="创建人"
+						style="width: 33%"
+						align="center"
+					>
+					</el-table-column>
+					<el-table-column
+						prop="uname"
+						label="操作"
+						style="width: 33%"
+						align="center"
+					>
+						<template slot-scope="scope">
+							<el-button
+								type="info"
+								size="small"
+								:disabled="true"
+								v-if="scope.row.courseId == chooseForm.testId"
+								>已绑定</el-button
+							>
+							<el-button
+								v-else
+								size="small"
+								type="primary"
+								@click.stop="choose(scope.row)"
+								>绑定</el-button
+							>
+						</template>
+					</el-table-column>
+				</el-table>
+			</div>
+			<div class="bfd_bottom">
+				<div class="bfd_b_left">
+					<el-pagination
+						background
+						:current-page="pageData.nowPage"
+						layout="prev, pager, next"
+						@current-change="currentChange"
+						:page-size="pageData.pageSize"
+						:total="pageData.total"
+					>
+					</el-pagination>
+				</div>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+export default {
+	emits: ["success"],
+	props: {
+		tid: {
+			type: String,
+			default: "",
+		},
+	},
+	data() {
+		return {
+			loading: false,
+			dialogVisible: false,
+			userId: this.$route.query["userid"],
+			oid: this.$route.query["oid"],
+			org: this.$route.query["org"],
+			chooseForm: {
+				testId: "",
+				checkUrl: "",
+				doUrl: "",
+			},
+			list: [],
+			pageData: {
+				nowPage: 1,
+				total: 0,
+				pageSize: 20,
+			},
+			text: "",
+		};
+	},
+	methods: {
+		open(_json) {
+			if (_json.testData) {
+				this.chooseForm = _json.testData;
+			} else {
+				this.chooseForm = {};
+			}
+			this.text = "";
+			this.pageData.nowPage = 1;
+			this.loading = false;
+			this.dialogVisible = true;
+			this.getData();
+		},
+		close() {
+			this.text = "";
+			this.dialogVisible = false;
+			this.chooseForm = {
+				testId: "",
+				checkUrl: "",
+				doUrl: "",
+			};
+			this.pageData.nowPage = 1;
+			this.list = [];
+			this.pageData.total = 0;
+		},
+		search(){
+			this.pageData.nowPage = 1
+			this.getData();
+		},
+		choose(row) {
+			this.$confirm("确定绑定该表单吗?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "warning",
+			})
+				.then(() => {
+					let _result = {
+						testId: row.courseId,
+						checkUrl: `https://beta.pbl.cocorobo.cn/pbl-teacher-table/dist/#/checkToTest?cid=${row.courseId}&userid=${this.userId}&oid=${this.oid}&org=${this.org}&tcid=${this.tid}&isN=1&role=0&type=2,`,
+						doUrl: `https://beta.pbl.cocorobo.cn/pbl-teacher-table/dist/#/doTest?cid=${row.courseId}&userid=${this.userId}&oid=${this.oid}&org=${this.org}&tcid=${this.tid}&isN=1&role=0&type=2`,
+					};
+					this.loading = true;
+					this.submitBtn(_result);
+				})
+				.catch(() => {
+					this.$message({
+						type: "info",
+						message: "已取消绑定",
+					});
+				});
+		},
+		submitBtn(_data) {
+			if (!_data.testId) return this.$message.error("未选择表单");
+			this.$emit("success", _data);
+		},
+		currentChange(page) {
+			this.pageData.nowPage = page;
+			this.getData();
+		},
+		getData() {
+			if (this.loading) return this.$message.info("请稍等...");
+			this.loading = true;
+
+			this.list = [];
+			let params = {
+				type: 4,
+				uid: this.userId,
+				oid: this.oid,
+				org: this.org,
+				typea: "",
+				typeb: "",
+				typec: "",
+				typed: "",
+				typef: "",
+				typeE: "",
+				cu: "",
+				cn: this.text,
+				page: this.pageData.nowPage,
+				pageSize: this.pageData.pageSize,
+			};
+			this.ajax
+				.get(this.$store.state.api + "selectTesttCourse", params)
+				.then((res) => {
+					let _data = res.data[0];
+					this.pageData.total = 0
+					if (_data.length > 0) {
+						this.list = _data;
+						this.pageData.total = _data[0].num;
+					}
+					this.loading = false;
+				})
+				.catch((err) => {
+					console.log(err);
+					this.$message.error("获取表单失败");
+					this.loading = false;
+				});
+		},
+	},
+};
+</script>
+
+<style scoped>
+.bindingFormDialog >>> .el-dialog {
+	min-width: 800px;
+
+	height: 700px;
+	box-shadow: 0px 0 8px 0px #555555;
+	border-radius: 8px;
+	background-color: #fff;
+	/* top: 0px; */
+	/* margin: 0 auto; */
+	overflow: hidden;
+}
+.bindingFormDialog >>> .el-dialog__body {
+	height: 100%;
+	min-width: 800px;
+	flex-shrink: 0;
+	box-sizing: border-box;
+	padding-bottom: 50px;
+	padding-top: 10px;
+}
+.bindingFormDialog >>> .el-dialog__header {
+	display: none !important;
+}
+
+.a-d-top {
+	/* background: #adadad; */
+	display: flex;
+	flex-direction: row;
+	flex-wrap: nowrap;
+	align-items: center;
+	justify-content: space-between;
+	height: 54px;
+	border-radius: 8px 8px 0 0;
+	user-select: none;
+	border-bottom: 1px #ccc solid;
+}
+.a-d-top >>> .el-input__inner {
+	width: 320px;
+	height: 32px;
+}
+.a-d-top >>> .el-input__icon {
+	line-height: 32px;
+}
+
+.a-d-topTit {
+	/* width: 171px; */
+	/* margin-left: 20px; */
+	height: 32px;
+	display: flex;
+	align-items: center;
+	font-family: PingFang SC;
+	box-sizing: border-box;
+	padding: 5px;
+	line-height: 22px;
+	justify-content: center;
+	/* text-align: left; */
+}
+
+.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;
+}
+
+.bfd_box {
+	width: 100%;
+	height: calc(100% - 80px);
+	overflow: auto;
+}
+
+.bfd_bottom {
+	width: 100%;
+	height: calc(70px);
+	margin-top: 10px;
+	display: flex;
+}
+
+.bfd_b_left {
+	flex: 1;
+	height: 100%;
+	display: flex;
+	align-items: center;
+}
+
+.a_d_t_input {
+	display: flex;
+	align-items: center;
+}
+
+/* .bfd_b_right {
+	width: 200px;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: flex-end;
+} */
+</style>

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


+ 24 - 2
src/components/pages/classroomObservation/components/messageArea.vue

@@ -16,6 +16,7 @@
 				使用分析模板
 			</div>
 			<div class="m-o-btn" @click.stop="saveAsTemplate()">另存为模板</div>
+			<div class="m-o-btn" :disabled="bmData.jsonData?false:true" @click="$refs.bindingFormDialogRef.open(bmData.jsonData)">绑定表单</div>
 		</div>
 		<div class="ma-main">
 			<baseMessage
@@ -137,7 +138,7 @@
 			</div>
 			<div style="display: flex; height: 100%">
 				<div class="a-d-t-left">
-					<div class="itemTit">我的模块</div>
+					<!-- <div class="itemTit">我的模块</div> -->
 					<div
 						:style="
 							tagIndex == index
@@ -213,6 +214,8 @@
 			</div>
 			<!-- </div> -->
 		</el-dialog>
+		<!-- 绑定 表单 -->
+		<bindingFormDialog ref="bindingFormDialogRef" :tid="tid" @success="bindingForm"/>
 	</div>
 </template>
 
@@ -222,6 +225,7 @@ import baseMessage from "./baseMessage.vue"; //基本信息
 // import scienceAnalysis from "./scienceAnalysis.vue"; //科学课堂分析
 // import extendAnalysis from "./extendAnalysis.vue"; //扩展分析
 import analysis from "./analysis.vue";
+import bindingFormDialog from './bindingFormDialog.vue'
 
 export default {
 	emits:["changeChatAreaAudioUrl","changeTranscription","changeOptionData","updateTime"],
@@ -231,6 +235,7 @@ export default {
 		// scienceAnalysis,
 		// extendAnalysis,
 		analysis,
+		bindingFormDialog,
 	},
 	props: {
 		tid: {
@@ -496,6 +501,15 @@ export default {
 		}
 	},
 	methods: {
+		// 绑定表单
+		bindingForm(obj){
+			this.bmData.jsonData.testData = obj;
+			this.saveData(this.bmData).then(_=>{
+				this.$message.success("绑定成功");
+				this.$refs.bindingFormDialogRef.close();
+			})
+			
+		},
 		delAnalysisItem(id) {
 			let _index = this.dataList.findIndex((i) => i.id == id);
 			if (_index > -1) {
@@ -1085,7 +1099,8 @@ export default {
 	font-weight: 600;
 	line-height: 22px;
 	text-align: left;
-	margin-bottom: 20px;
+	margin-top: 20px;
+	/* margin-bottom: 20px; */
 }
 
 .a-d-t-l-item:hover {
@@ -1141,8 +1156,15 @@ export default {
 	box-sizing: border-box;
 	margin-bottom: 10px;
 	margin-right: 20px;
+	transform: .3s;
+	box-shadow: 0 16px 24px 2px #f0f2f5;
 	/* position: relative; */
 }
+
+.a-d-b-item:hover{
+	box-shadow: 0 16px 24px 2px #0000001c;
+}
+
 .a-d-b-item:hover .a-d-b-i-bottomBtn {
 	display: block !important;
 }

+ 37 - 11
src/components/pages/classroomObservation/index.vue

@@ -292,15 +292,32 @@ export default {
 				type: "warning",
 			})
 				.then(() => {
-					this.optionData.splice(
-						this.optionData.findIndex((item) => item.value == _value),
-						1
-					);
-					this.tid = this.optionData[0] ? this.optionData[0].value : "";
-					this.changeTid(this.tid);
-					this.$message({
-						type: "success",
-						message: "删除成功!",
+					// this.optionData.splice(
+					// 	this.optionData.findIndex((item) => item.value == _value),
+					// 	1
+					// );
+					// this.tid = this.optionData[0] ? this.optionData[0].value : "";
+					// this.changeTid(this.tid);
+					// this.$message({
+					// 	type: "success",
+					// 	message: "删除成功!",
+					// });
+					let params = {
+						tid: _value,
+					}
+					this.ajax
+					.post("https://gpt4.cocorobo.cn/update_classroom_observation_isdel", params)
+					.then((res) => {
+						this.$message({
+							type: "success",
+							message: "删除成功!",
+						});
+						this.getCourseList().then((_) => {
+							if (!this.tid) return;
+							this.getFileIdId();
+							this.$refs.messageAreaRef.getData();
+							this.$refs.chatAreaRef.getData();
+						});
 					});
 				})
 				.catch(() => {});
@@ -344,8 +361,17 @@ export default {
 					.post("https://gpt4.cocorobo.cn/get_classroom_observation_all")
 					.then((res) => {
 						let _data = res.data.FunctionResponse.result;
-						let _result = _data ? JSON.parse(_data) : [];
-						if (_result.length <= 0) return;
+						let _result = []
+						try {
+							_result = _data ? JSON.parse(_data) : [];
+						} catch (error) {
+							_result = []
+						}
+
+						if (_result.length <= 0) { 
+							this.loading = false;
+							return
+						};
 						let _optionData = _result.map((item) => {
 							item.jsonData = item.jsonData ? JSON.parse(item.jsonData) : {};
 							return {

+ 489 - 440
src/components/pages/pblCourse/component/chatArea.vue

@@ -1,559 +1,608 @@
 <template>
-  <div class="chat" v-loading="loading">
-    <div class="c_chat" ref="chatRef">
-      <div class="c_c_item" v-for="item in chatList" :key="item.uid">
-        <div class="c_c_i_user" v-if="item.content">
-          <div class="c_c_i_u_message">
-            <div class="c_c_i_u_m_top">
-              <span class="chatTime">{{ item.createtime }}</span>
-              <span>科科</span>
-            </div>
-            <div class="c_c_i_u_m_bottom">
-              <span class="coptText" @click="copyText(item.aiContent)"></span>
-              <div
-                class="c_c_i_u_m_content chatContent"
-                v-html="item.content"
-              ></div>
-            </div>
-          </div>
-          <div class="c_c_i_u_avatar">
-            <el-avatar
-              style="width: 100%; height: 100%"
-              :src="require('../../../../assets/icon/pblCourse/userAvatar.png')"
-              fit="fit"
-            ></el-avatar>
-          </div>
-        </div>
-        <div class="c_c_i_ai">
-          <div class="c_c_i_ai_avatar">
-            <el-avatar
-              style="width: 100%; height: 100%"
-              :src="
-                require('../../../../assets/icon/pblCourse/aiTeacherAvatar.png')
-              "
-              fit="fit"
-            ></el-avatar>
-          </div>
-          <div class="c_c_i_ai_message">
-            <div class="c_c_i_ai_m_top">
-              <span>小可老师</span>
-              <span class="chatTime">{{ item.createtime }}</span>
-            </div>
-            <div class="c_c_i_ai_m_bottom">
-              <div
-                v-loading="item.loading"
-                class="c_c_i_ai_m_content chatContent"
-                v-html="item.aiContent"
-              ></div>
-              <span class="coptText" @click="copyText(item.aiContent)"></span>
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-    <!-- <div class="c_controls">
+	<div class="chat" v-loading="loading">
+		<div class="c_chat" ref="chatRef">
+			<div class="c_c_i_ai">
+				<div class="c_c_i_ai_avatar">
+					<el-avatar
+						style="width: 100%; height: 100%"
+						:src="
+							require('../../../../assets/icon/pblCourse/aiTeacherAvatar.png')
+						"
+						fit="fit"
+					></el-avatar>
+				</div>
+				<div class="c_c_i_ai_message">
+					<div class="c_c_i_ai_m_top">
+						<span>小可老师</span>
+						<span class="chatTime">{{ new Date().toLocaleString().replaceAll('/','-') }}</span>
+					</div>
+					<div class="c_c_i_ai_m_bottom">
+						<div
+							v-loading="false"
+							class="c_c_i_ai_m_content chatContent"
+						>
+						<p>同学你好,我是你的助教老师小可,你有什么问题要问我吗?</p>
+
+						<p style="margin-top:5px">我很擅长协助你探索以下问题哦~</p>
+						<ul style="color:#3673E8;margin-top: 10px;">
+							<li style="margin-top: 5px;cursor: pointer;" @click="sendChat('作业思路讨论')">作业思路讨论</li>
+							<li style="margin-top: 5px;cursor: pointer;" @click="sendChat('回答学习疑惑')">回答学习疑惑</li>
+							<li style="margin-top: 5px;cursor: pointer;" @click="sendChat('查找资源资料')">查找资源资料</li>
+							<li style="margin-top: 5px;cursor: pointer;" @click="sendChat('整理学习资料')">整理学习资料</li>
+						</ul>
+					</div>
+						<!-- <span class="coptText" @click="copyText(item.aiContent)"></span> -->
+					</div>
+				</div>
+			</div>
+			<div class="c_c_item" v-for="item in chatList" :key="item.uid">
+				<div class="c_c_i_user" v-if="item.content">
+					<div class="c_c_i_u_message">
+						<div class="c_c_i_u_m_top">
+							<span class="chatTime">{{ item.createtime }}</span>
+							<span>科科</span>
+						</div>
+						<div class="c_c_i_u_m_bottom">
+							<span class="coptText" @click="copyText(item.aiContent)"></span>
+							<div
+								class="c_c_i_u_m_content chatContent"
+								v-html="item.content"
+							></div>
+						</div>
+					</div>
+					<div class="c_c_i_u_avatar">
+						<el-avatar
+							style="width: 100%; height: 100%"
+							:src="require('../../../../assets/icon/pblCourse/userAvatar.png')"
+							fit="fit"
+						></el-avatar>
+					</div>
+				</div>
+				<div class="c_c_i_ai">
+					<div class="c_c_i_ai_avatar">
+						<el-avatar
+							style="width: 100%; height: 100%"
+							:src="
+								require('../../../../assets/icon/pblCourse/aiTeacherAvatar.png')
+							"
+							fit="fit"
+						></el-avatar>
+					</div>
+					<div class="c_c_i_ai_message">
+						<div class="c_c_i_ai_m_top">
+							<span>小可老师</span>
+							<span class="chatTime">{{item.createtime}}</span>
+						</div>
+						<div class="c_c_i_ai_m_bottom">
+							<div
+								v-loading="item.loading"
+								class="c_c_i_ai_m_content chatContent"
+								v-html="item.aiContent"
+							></div>
+							<span class="coptText" @click="copyText(item.aiContent)"></span>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<!-- <div class="c_controls">
 			<span class="c_controls_item" @click="clearChat">清空对话</span>
 		</div> -->
-    <div class="c_bottom" v-loading="chatLoading">
-      <!-- <div class="c_b_record">
+		<div class="c_bottom" 	v-loading="chatLoading">
+			<!-- <div class="c_b_record">
 				<span></span>
 			</div> -->
-      <div class="c_b_inputArea">
-        <el-input
-          class="c_b_input"
-          @keyup.enter.native="send()"
-          v-model="textValue"
-        >
-        </el-input>
-        <!-- <span></span> -->
-      </div>
-      <div class="c_b_send" @click="send">
-        <span></span>
-      </div>
-    </div>
-  </div>
+			<div class="c_b_inputArea">
+				<el-input
+					class="c_b_input"
+					@keyup.enter.native="send()"
+					v-model="textValue"
+				
+				>
+				</el-input>
+				<!-- <span></span> -->
+			</div>
+			<div class="c_b_send" @click="send">
+				<span></span>
+			</div>
+		</div>
+	</div>
 </template>
 
 <script>
 import { v4 as uuidv4 } from "uuid";
 import MarkdownIt from "markdown-it";
 export default {
-  data() {
-    return {
-      loading: false,
-      chatLoading: false,
-      userId: this.$route.query["userid"],
-      chatList: [],
-      textValue: ""
-    };
-  },
-  methods: {
-    // 发送消息
-    send() {
-      if (this.chatLoading || this.loading)
-        return this.$message.info("请稍等...");
-      if (!this.textValue.trim()) return this.$message.info("请输入内容");
-      const _uuid = uuidv4();
-      this.chatLoading = true;
-      this.chatList.push({
-        role: "user",
-        content: `${this.textValue}`,
-        uid: _uuid,
-        AI: "AI",
-        aiContent: "",
-        oldContent: "",
-        filename: "",
-        index: this.chatList.length,
-        createtime: new Date().toLocaleString().replaceAll("/", "-"),
-        loading: true
-      });
-
-      // let params = {
-      // 	model: "gpt-3.5-turbo",
-      // 		temperature: 0,
-      // 		max_tokens: 4096,
-      // 		top_p: 1,
-      // 		frequency_penalty: 0,
-      // 		presence_penalty: 0,
-      // 		messages: [{role:"user",content:this.textValue}],
-      // 		uid: _uuid,
-      // 		mind_map_question: "",
-      // }
-      let params = JSON.stringify({
+	data() {
+		return {
+			loading: false,
+			chatLoading:false,
+			userId:this.$route.query['userid'],
+			chatList: [],
+			textValue: "",
+		};
+	},
+	methods: {
+		// 发送消息
+		send() {
+			if(this.chatLoading || this.loading)return this.$message.info("请稍等...")
+			if(!this.textValue.trim())return this.$message.info("请输入内容");
+			const _uuid = uuidv4();
+			this.chatLoading = true;
+			this.chatList.push({
+				role: "user",
+				content: `${this.textValue}`,
+				uid: _uuid,
+				AI: "AI",
+				aiContent: "",
+				oldContent: "",
+				filename: "",
+				index: this.chatList.length,
+				createtime:new Date().toLocaleString().replaceAll("/",'-'),
+				loading: true,
+			})
+
+			let history = [];
+			let _msg = ''
+			if(this.textValue=='作业思路讨论'){
+				this,$message.info("作业思路讨论")
+				_msg = `作业思路讨论`
+			}else if(this.textValue=='回答学习疑惑'){
+				this,$message.info("回答学习疑惑")
+				_msg = `回答学习疑惑`
+			}else if(this.textValue=='查找资源资料'){
+				this,$message.info("查找资源资料")
+				_msg = `查找资源资料`
+			}else if(this.textValue=='整理学习资料'){
+				this,$message.info("整理学习资料")
+				_msg = `整理学习资料`
+			}
+			if(_msg){
+				history.push({role:"user",content:_msg})
+			}
+			history.push({role:"user",content:this.textValue})
+			// let params = {
+			// 	model: "gpt-3.5-turbo",
+			// 		temperature: 0,
+			// 		max_tokens: 4096,
+			// 		top_p: 1,
+			// 		frequency_penalty: 0,
+			// 		presence_penalty: 0,
+			// 		messages: history,
+			// 		uid: _uuid,
+			// 		mind_map_question: this.textValue,
+			// }
+			let params = JSON.stringify({
         message: {
           anthropic_version: "bedrock-2023-05-31",
           max_tokens: 4096,
           temperature: 0,
           top_p: 1,
-          messages: [
-            {
-              role: "user",
-              content: this.textValue
-            }
-          ]
+          messages: history
         },
         uid: _uuid,
         model: "Claude 3 Sonnet" // Claude 3 Sonnet或者Claude 3 Haiku
       });
-      this.scrollBottom();
-      this.textValue = "";
-      this.ajax
-        // .post("https://gpt4.cocorobo.cn/chat", params)
-        .post("https://claude3.cocorobo.cn/chat", params)
-        .then(res => {
-          if (res.data.FunctionResponse.result == "发送成功") {
-          } else {
-            this.chatLoading = false;
-            this.$message.warning(res.data.FunctionResponse.result);
-          }
-        })
-        .catch(e => {
-          this.chatLoading = false;
-          console.log(e);
-        });
-      // this.$message.info(`发送:${this.textValue}`);
-      // this.textValue = "";
-      this.getAiContent(_uuid);
-    },
-    getAiContent(_uid) {
+			this.scrollBottom();
+			this.textValue = "";
+			this.ajax
+					 // .post("https://gpt4.cocorobo.cn/chat", params)
+					 .post("https://claude3.cocorobo.cn/chat", params)
+					.then((res) => {
+						if (res.data.FunctionResponse.result == "发送成功") {
+						} else {
+							this.chatLoading = false;
+							this.$message.warning(res.data.FunctionResponse.result);
+						}
+					})
+					.catch((e) => {
+						this.chatLoading = false;
+						console.log(e);
+					});
+			// this.$message.info(`发送:${this.textValue}`);
+			// this.textValue = "";
+			this.getAiContent(_uuid)
+		},
+		getAiContent(_uid) {
 			let _source = new EventSource(`https://claude3.cocorobo.cn/streamChat/${_uid}`);
       // let _source = new EventSource(`https://gpt4.cocorobo.cn/stream/${_uid}`); //http://gpt4.cocorobo.cn:8011/stream/     https://gpt4.cocorobo.cn/stream/
-      let _allText = "";
-      let _mdText = "";
-      const md = new MarkdownIt();
-      _source.onmessage = _e => {
-        if (_e.data.replace("'", "").replace("'", "") == "[DONE]") {
-          //对话已经完成
-          _mdText = _mdText.replace("_", "");
-          _source.close();
-          this.chatList.find(i => i.uid == _uid).aiContent = _mdText;
-          this.chatList.find(i => i.uid == _uid).isalltext = true;
-          this.chatList.find(i => i.uid == _uid).isShowSynchronization = true;
-          this.chatList.find(i => i.uid == _uid).loading = false;
-          this.chatLoading = false;
-          this.insertChat(_uid);
-          return;
-        } else {
-          //对话还在继续
-          let _text = "";
-          _text = _e.data.replaceAll("'", "");
-          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);
-          this.chatList.find(i => i.uid == _uid).aiContent = _mdText;
-          this.chatList.find(i => i.uid == _uid).loading = false;
-          this.scrollBottom();
-          // 处理流数据
-        }
-      };
-    },
-    // 复制
-    copyText(_html) {
-      const div = document.createElement("div");
-      div.innerHTML = _html;
-      const _text = div.innerText;
-      navigator.clipboard.writeText(_text).then(
-        _ => {
-          this.$message.success("复制成功");
-        },
-        function(err) {
-          this.$message.error(`无法复制:${err}`);
-        }
-      );
-    },
-    // 保存对话
-    //保存消息
-    insertChat(_uid) {
-      let _data = this.chatList.find(i => i.uid == _uid);
-      if (!_data) return;
-      let params = {
-        userId: this.userId,
-        userName: "qgt",
-        groupId: "602def61-005d-11ee-91d8-005056b8q12w",
-        answer: _data.aiContent,
-        problem: _data.content,
-        file_id: "",
-        alltext: _data.aiContent,
-        type: "chat",
-        filename: _data.filename,
-        session_name: `${this.userId}-pblCourse`
-      };
-      this.ajax
-        .post("https://gpt4.cocorobo.cn/insert_chat", params)
-        .then(res => {
-          console.log("保存对话");
-        });
-    },
-    // 获取对话记录
-    getChatList() {
-      return new Promise((resolve, reject) => {
-        this.chatList = [];
-        this.loading = true;
-        this.chatLoading = true;
-        let params = {
-          userid: this.userId,
-          groupid: "602def61-005d-11ee-91d8-005056b8q12w",
-          // session_name:``
-          session_name: `${this.userId}-pblCourse`
-        };
-        this.ajax
-          .post("https://gpt4.cocorobo.cn/get_agent_park_chat", params)
-          .then(res => {
-            let _data = JSON.parse(res.data.FunctionResponse);
-            if (_data.length > 0) {
-              console.log(_data);
-              let _chatList = [];
-              for (let i = 0; i < _data.length; i++) {
-                _chatList.push({
-                  loading: false,
-                  role: "user",
-                  content: _data[i].problem,
-                  uid: _data[i].id,
-                  AI: "AI",
-                  aiContent: _data[i].answer,
-                  oldContent: _data[i].answer,
-                  isShowSynchronization: false,
-                  filename: _data[i].filename,
-                  index: i,
-                  is_mind_map: false,
-                  fileid: _data[i].fileid,
-                  createtime: _data[i].createtime
-                });
-              }
-              this.chatList = _chatList;
-              this.chatLoading = false;
-              this.loading = false;
-            } else {
-              //没有对话记录
-              this.loading = false;
-              this.chatLoading = false;
-            }
-            resolve();
-            this.scrollBottom();
-          })
-          .catch(err => {
-            console.log(err);
-            this.$message.error("获取对话记录失败");
-            this.chatLoading = false;
-            this.scrollBottom();
-            resolve();
-          });
-      });
-    },
-    //对话触底
-    scrollBottom() {
-      this.$nextTick(() => {
-        this.$refs.chatRef.scrollTop = this.$refs.chatRef.scrollHeight;
-      });
-    },
-    //清除对话
-    clearChat() {
-      this.chatList = [];
-      this.scrollBottom();
-    }
-  },
-
-  mounted() {
-    this.getChatList().then(_ => {
-      this.scrollBottom();
-    });
-  }
+			let _allText = "";
+			let _mdText = "";
+			const md = new MarkdownIt();
+			_source.onmessage = (_e) => {
+				if (_e.data.replace("'", "").replace("'", "") == "[DONE]") {
+					//对话已经完成
+					_mdText = _mdText.replace("_", "");
+					_source.close();
+					this.chatList.find((i) => i.uid == _uid).aiContent = _mdText;
+					this.chatList.find((i) => i.uid == _uid).isalltext = true;
+					this.chatList.find((i) => i.uid == _uid).isShowSynchronization = true;
+					this.chatList.find((i) => i.uid == _uid).loading = false;
+					this.chatLoading = false;
+					this.insertChat(_uid);
+					return;
+				} else {
+					//对话还在继续
+					let _text = "";
+					_text = _e.data.replaceAll("'", "");
+					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);
+					this.chatList.find((i) => i.uid == _uid).aiContent = _mdText;
+					this.chatList.find((i) => i.uid == _uid).loading = false;
+					this.scrollBottom();
+					// 处理流数据
+				}
+			};
+		},
+		// 复制
+		copyText(_html) {
+			const div = document.createElement("div")
+			div.innerHTML = _html
+			const _text = div.innerText
+			navigator.clipboard.writeText(_text).then(_=>{
+			  this.$message.success("复制成功")
+			}, function(err) {
+				this.$message.error(`无法复制:${err}`)
+			});
+		},
+		// 保存对话
+		//保存消息
+		insertChat(_uid) {
+			let _data = this.chatList.find((i) => i.uid == _uid);
+			if (!_data) return;
+			let params = {
+				userId: this.userId,
+				userName: "qgt",
+				groupId: "602def61-005d-11ee-91d8-005056b8q12w",
+				answer: _data.aiContent,
+				problem: _data.content,
+				file_id: "",
+				alltext: _data.aiContent,
+				type: "chat",
+				filename: _data.filename,
+				session_name: `${this.userId}-pblCourse`,
+			};
+			this.ajax
+				.post("https://gpt4.cocorobo.cn/insert_chat", params)
+				.then((res) => {
+					console.log("保存对话")
+				});
+		},
+		// 获取对话记录
+		getChatList() {
+			return new Promise((resolve, reject) => {
+				this.chatList = [];
+				this.loading = true;
+				this.chatLoading = true;
+				let params = {
+					userid: this.userId,
+					groupid: "602def61-005d-11ee-91d8-005056b8q12w",
+					// session_name:``
+					session_name: `${this.userId}-pblCourse`,
+				};
+				this.ajax
+					.post("https://gpt4.cocorobo.cn/get_agent_park_chat", params)
+					.then((res) => {
+						let _data = JSON.parse(res.data.FunctionResponse);
+						if (_data.length > 0) {
+							console.log(_data)
+							let _chatList = [];
+							for (let i = 0; i < _data.length; i++) {
+								_chatList.push({
+									loading: false,
+									role: "user",
+									content: _data[i].problem,
+									uid: _data[i].id,
+									AI: "AI",
+									aiContent: _data[i].answer,
+									oldContent: _data[i].answer,
+									isShowSynchronization: false,
+									filename: _data[i].filename,
+									index: i,
+									is_mind_map: false,
+									fileid: _data[i].fileid,
+									createtime:_data[i].createtime
+								});
+							}
+							this.chatList = _chatList;
+							this.chatLoading = false;
+							this.loading = false;
+						} else {
+							//没有对话记录
+							this.loading = false;
+							this.chatLoading = false;
+						}
+						resolve();
+						this.scrollBottom();
+					})
+					.catch((err) => {
+						console.log(err);
+						this.$message.error("获取对话记录失败");
+						this.chatLoading = false;
+						this.scrollBottom();
+						resolve();
+					});
+			});
+		},
+		//对话触底
+		scrollBottom(){
+			this.$nextTick(()=>{
+				this.$refs.chatRef.scrollTop = this.$refs.chatRef.scrollHeight;
+			})
+		},
+		//清除对话
+		clearChat(){
+			this.chatList = [];
+			this.scrollBottom();
+		},
+		sendChat(_text){
+			this.textValue = _text;
+			this.send();
+		}
+	},
+
+	mounted() {
+		this.getChatList().then(_=>{
+			this.scrollBottom();
+		})
+	},
 };
 </script>
 
 <style scoped>
 .chat {
-  width: 100%;
-  height: 100%;
-  background-color: #ffffff;
-  border-radius: 12px;
-  box-sizing: border-box;
-  border: solid 1px #f3f7fd;
-  box-shadow: 0 4px 10px 0 #1d388321;
+	width: 100%;
+	height: 100%;
+	background-color: #ffffff;
+	border-radius: 12px;
+	box-sizing: border-box;
+	border: solid 1px #f3f7fd;
+	box-shadow: 0 4px 10px 0 #1d388321;
 }
 
 .c_chat {
-  width: 100%;
-  height: calc(100% - 56px);
-  box-sizing: border-box;
-  padding: 15px;
-  overflow: auto;
+	width: 100%;
+	height: calc(100% - 56px);
+	box-sizing: border-box;
+	padding: 15px;
+	overflow: auto;
 }
 
 .c_c_item {
-  background-color: none;
+	background-color: none;
 }
 
 .c_c_i_user {
-  width: 100%;
-  height: auto;
-  display: flex;
-  justify-content: flex-end;
-  align-items: flex-start;
-  margin-bottom: 10px;
+	width: 100%;
+	height: auto;
+	display: flex;
+	justify-content: flex-end;
+	align-items: flex-start;
+	margin-bottom: 10px;
 }
 
 .c_c_i_u_message {
-  height: auto;
-  width: auto;
-  max-width: calc(100% - 50px - 40px);
-  display: flex;
-  flex-direction: column;
-  align-items: flex-end;
-  margin-right: 5px;
+	height: auto;
+	width: auto;
+	max-width: calc(100% - 50px - 40px);
+	display: flex;
+	flex-direction: column;
+	align-items: flex-end;
+	margin-right: 5px;
 }
 .c_c_i_u_m_top {
-  margin-bottom: 10px;
-  display: flex;
-  align-items: flex-end;
+	margin-bottom: 10px;
+	display: flex;
+	align-items: flex-end;
 }
 
 .c_c_i_u_m_top > span {
-  margin-left: 5px;
+	margin-left: 5px;
 }
 
 .c_c_i_u_m_bottom {
-  display: flex;
-  align-items: flex-end;
+	display: flex;
+	align-items: flex-end;
 }
 
 .coptText {
-  min-width: 15px;
-  min-height: 15px;
-  display: block;
-  background: url("../../../../assets/icon/pblCourse/copyIcon.png") no-repeat;
-  background-size: 100% 100%;
-  margin: 0px 10px 6px 10px;
-  cursor: pointer;
+	min-width: 15px;
+	min-height: 15px;
+	display: block;
+	background: url("../../../../assets/icon/pblCourse/copyIcon.png") no-repeat;
+	background-size: 100% 100%;
+	margin: 0px 10px 6px 10px;
+	cursor: pointer;
 }
 
 .c_c_i_u_m_content {
-  width: auto;
-  height: auto;
-  padding: 10px;
-  background-color: #e2eeff;
-  border-radius: 8px 2px 8px 8px;
-  border: solid 1px #000000e5;
+	width: auto;
+	height: auto;
+	padding: 10px;
+	background-color: #e2eeff;
+	border-radius: 8px 2px 8px 8px;
+	border: solid 1px #000000e5;
 }
 
 .c_c_i_u_avatar {
-  width: 45px;
-  height: 45px;
-  margin: 0px 0 0 10px;
+	width: 45px;
+	height: 45px;
+	margin: 0px 0 0 10px;
 }
 
 .c_c_i_ai {
-  margin-top: 10px;
-  width: 100%;
-  height: auto;
-  display: flex;
-  align-items: flex-start;
-  margin-bottom: 10px;
+	margin-top: 10px;
+	width: 100%;
+	height: auto;
+	display: flex;
+	align-items: flex-start;
+	margin-bottom: 10px;
 }
 
 .c_c_i_ai_avatar {
-  width: 45px;
-  height: 45px;
-  margin: 0px 0 0 10px;
+	width: 45px;
+	height: 45px;
+	margin: 0px 0 0 10px;
 }
 
 .c_c_i_ai_message {
-  height: auto;
-  width: auto;
-  max-width: calc(100% - 50px - 40px);
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  margin-left: 5px;
+	height: auto;
+	width: auto;
+	max-width: calc(100% - 50px - 40px);
+	display: flex;
+	flex-direction: column;
+	align-items: flex-start;
+	margin-left: 5px;
 }
 .c_c_i_ai_m_top {
-  display: flex;
-  align-items: flex-end;
-  margin-bottom: 10px;
+	display: flex;
+	align-items: flex-end;
+	margin-bottom: 10px;
 }
 
 .c_c_i_ai_m_top > span {
-  margin-left: 5px;
+	margin-left: 5px;
 }
 
 .c_c_i_ai_m_bottom {
-  display: flex;
-  align-items: flex-end;
+	display: flex;
+	align-items: flex-end;
 }
 
 .c_c_i_ai_m_content {
-  min-width: 40px;
-  min-height: 25px;
-  width: auto;
-  height: auto;
-  padding: 10px;
-  background-color: #ffffff;
-  border-radius: 2px 8px 8px 8px;
-  border: solid 1px #000000e5;
+	min-width: 40px;
+	min-height: 25px;
+	width: auto;
+	height: auto;
+	padding: 10px;
+	background-color: #ffffff;
+	border-radius: 2px 8px 8px 8px;
+	border: solid 1px #000000e5;
 }
 
 .chatContent >>> ol {
-  margin-left: 25px;
+	margin-left: 25px;
 }
 
 .chatContent >>> ul {
-  margin-left: 25px;
+	margin-left: 25px;
 }
 
-.chatTime {
-  font-size: 14px;
-  margin: 0 10px;
-  color: #2c2f3b;
+.chatTime{
+	font-size: 14px;
+	margin: 0 10px;
+	color: #2c2f3b;
 }
 
-.c_controls {
-  width: 100%;
-  height: 30px;
+.c_controls{
+	width: 100%;
+	height: 30px;
 }
 
-.c_controls > span {
-  max-height: 30px;
-  width: auto;
-  padding: 5px 10px;
-  font-size: 14px;
-  border-radius: 15px;
-  box-shadow: 0 0 2px 0px gray;
-  margin-left: 10px;
-  cursor: pointer;
+.c_controls>span{
+	max-height: 30px;
+	width: auto;
+	padding: 5px 10px;
+	font-size: 14px;
+	border-radius: 15px;
+	box-shadow: 0 0 2px 0px gray;
+	margin-left: 10px;
+	cursor: pointer;
 }
 
-.c_controls > span:hover {
-  background-color: #f3f7fd;
+.c_controls>span:hover{
+	background-color: #f3f7fd;
 }
 
 .c_bottom {
-  width: 100%;
-  height: 56px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  box-sizing: border-box;
-  border-top: solid 0.5px #e7e7e7;
+	width: 100%;
+	height: 56px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	box-sizing: border-box;
+	border-top: solid 0.5px #e7e7e7;
 }
 
 .c_b_record {
-  width: 30px;
-  height: 30px;
-  display: flex;
-  justify-content: center;
-  align-items: center;
+	width: 30px;
+	height: 30px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
 }
 
 .c_b_record > span {
-  width: 24px;
-  height: 24px;
-  background-image: url("../../../../assets/icon/pblCourse/recordIcon.png");
-  background-size: 100% 100%;
-  display: flex;
-  justify-content: center;
-  align-items: center;
+	width: 24px;
+	height: 24px;
+	background-image: url("../../../../assets/icon/pblCourse/recordIcon.png");
+	background-size: 100% 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
 }
 
 .c_b_inputArea {
-  width: calc(100% - 100px);
-  background-color: #f3f3f3;
-  border-radius: 50px;
-  height: 80%;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  margin: 0 15px;
+	width: calc(100% - 100px);
+	background-color: #f3f3f3;
+	border-radius: 50px;
+	height: 80%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin: 0 15px;
 }
 
 .c_b_input {
-  width: calc(100% - 40px);
-  margin-right: 10px;
+	width: calc(100% - 40px);
+	margin-right: 10px;
 }
 
 .c_b_input >>> .el-input__inner {
-  border: none;
-  background-color: #f3f3f3;
-  outline: none;
-  border-radius: 50px 0 0 50px;
-  font-size: 1.2em;
+	border: none;
+	background-color: #f3f3f3;
+	outline: none;
+	border-radius: 50px 0 0 50px;
+	font-size: 1.2em;
 }
 
 .c_b_inputArea > span {
-  width: 24px;
-  height: 24px;
-  background-image: url("../../../../assets/icon/pblCourse/fileIcon.png");
-  background-size: 100% 100%;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  margin-right: 10px;
-  cursor: pointer;
+	width: 24px;
+	height: 24px;
+	background-image: url("../../../../assets/icon/pblCourse/fileIcon.png");
+	background-size: 100% 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin-right: 10px;
+	cursor: pointer;
 }
 
 .c_b_send {
-  width: 40px;
-  height: 40px;
-  border-radius: 50%;
-  background-color: #3681fc;
-  cursor: pointer;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  cursor: pointer;
+	width: 40px;
+	height: 40px;
+	border-radius: 50%;
+	background-color: #3681fc;
+	cursor: pointer;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
 }
 
 .c_b_send > span {
-  width: 60%;
-  height: 60%;
-  background-image: url("../../../../assets/icon/pblCourse/sendIcon.png");
-  background-size: 100% 100%;
+	width: 60%;
+	height: 60%;
+	background-image: url("../../../../assets/icon/pblCourse/sendIcon.png");
+	background-size: 100% 100%;
 }
 </style>

+ 10 - 9
src/components/pages/test/check/index.vue

@@ -397,6 +397,7 @@ export default {
       org: this.$route.query.org,
       role: this.$route.query.role,
       cid: this.$route.query.cid,
+      isN: this.$route.query.isN,
       title: "",
       testType: [],
       see: false,
@@ -624,7 +625,7 @@ export default {
                 courseid: this.works[i].courseid,
                 id: this.works[i].id,
                 userid: this.works[i].userid,
-                name: this.works[i].username,
+                name: this.works[i].username ? this.works[i].username : '匿名',
                 time: this.works[i].time,
                 array: _json,
                 courseJson: JSON.parse(this.works[i].courseJson),
@@ -1068,7 +1069,7 @@ export default {
       let score = this.score(JSON.parse(data.courseJson))
       let isScore = this.score2(JSON.parse(data.courseJson))
       let scoreContent = score ? `<b>(得分/总分)${isScore}/${score}</b>` : ''
-      let _content = `<div style="text-align:center;margin-top: 20px;"><b style="margin-right:40px">(答题人)${_data.username}</b>${scoreContent}(填写范围)${this.testJson.juriP ? this.testJson.juriP : '所有人'}(提交时间)${_data.time}</div>`
+      let _content = `<div style="text-align:center;margin-top: 20px;"><b style="margin-right:40px">(答题人)${_data.username ? _data.username : '匿名'}</b>${scoreContent}(填写范围)${this.testJson.juriP ? this.testJson.juriP : '所有人'}(提交时间)${_data.time}</div>`
       let _detail = this.testJson.brief ? `<div style="text-align:center;margin-top: 20px;">${this.testJson.brief}</div>` : ''
 
       let _test = `<div style='margin-top:40px;'>`
@@ -1102,7 +1103,7 @@ export default {
       }
       _test += `</div>`
       let _html = _title + _content + _detail + _test;
-      this.exportToWord(_data.username + '-' + _data.time, _html);
+      this.exportToWord(_data.username ? _data.username : '匿名' + '-' + _data.time, _html);
     },
     async exportToWord(a, html) {
       // 将html文件中需要用到的数据挂载到store上
@@ -1187,7 +1188,7 @@ export default {
       let score = this.score(JSON.parse(data.courseJson))
       let isScore = this.score2(JSON.parse(data.courseJson))
       let scoreContent = score ? `<b>(得分/总分)${isScore}/${score}</b>` : ''
-      let _content = `<div style="text-align:center;margin-top: 20px;"><b style="margin-right:40px">(答题人)${_data.username}</b>${scoreContent}(填写范围)${this.testJson.juriP ? this.testJson.juriP : '所有人'}(提交时间)${_data.time}</div>`
+      let _content = `<div style="text-align:center;margin-top: 20px;"><b style="margin-right:40px">(答题人)${_data.username ? _data.username : '匿名'}</b>${scoreContent}(填写范围)${this.testJson.juriP ? this.testJson.juriP : '所有人'}(提交时间)${_data.time}</div>`
       let _detail = this.testJson.brief ? `<div style="text-align:center;margin-top: 20px;">${this.testJson.brief}</div>` : ''
 
       let _test = `<div style='margin-top:40px;'>`
@@ -1222,7 +1223,7 @@ export default {
       }
       _test += `</div>`
       let _html = _title + _content + _detail + _test;
-      return this.exportToWordAll(_data.username + '-' + _data.time, _html);
+      return this.exportToWordAll(_data.username ? _data.username : '匿名' + '-' + _data.time, _html);
     },
     async exportToWordAll(a, html) {
       // 将html文件中需要用到的数据挂载到store上
@@ -1329,7 +1330,7 @@ export default {
       for (var i = 0; i < res.length; i++) {
         var _json = {};
         _json["序号"] = i + 1;
-        _json["提交人"] = res[i].name;
+        _json["提交人"] = res[i].name ? res[i].name : '匿名';
         _json["提交时间"] = res[i].time;
         for (var j = 0; j < chapters.length; j++) {
           _json[j + 1 + "." + chapters[j].json.title] = '';
@@ -1412,7 +1413,7 @@ export default {
 			let downFileArray = [];
 			let uniqueArr = data.filter((v,i,a)=>a.map(mb=>mb.userid).indexOf(v.userid)==i);
 			uniqueArr.forEach(i=>{
-				downFileArray.push({userid:i.userid,username:i.username,urlList:data.filter(d=>d.userid==i.userid).map(m=>m)});
+				downFileArray.push({userid:i.userid,username:i.username ? i.username : '匿名',urlList:data.filter(d=>d.userid==i.userid).map(m=>m)});
 			})
 			let promises = [];
 			if(downFileArray.length==1){//只有一位老师的情况
@@ -1444,12 +1445,12 @@ export default {
 						promises.push(getFile(i.urlList[0].url).then((data) => {
 						  if (data.data != 1) {
         	      // 下载文件, 并存成ArrayBuffer对象
-        	      const file_name = `${i.username}-${i.urlList[0].name}`; // 获取文件名
+        	      const file_name = `${i.username ? i.username : '匿名'}-${i.urlList[0].name}`; // 获取文件名
 								zip.file(file_name, data.data, { binary: true }); // 逐个添加文件
         	    }
 						}))
 					}else if(i.urlList.length>1){//有多个文件的
-						const folder = zip.folder(`${i.username}`);
+						const folder = zip.folder(`${i.username ? i.username : '匿名'}`);
 						i.urlList.forEach(ui=>{
 						  const promise = getFile(ui.url).then((data) => {
 								if (data.data != 1) {

+ 7 - 1
src/components/pages/testStudent/index.vue

@@ -230,6 +230,8 @@ export default {
       org: this.$route.query.org,
       role: this.$route.query.role,
       classid: this.$route.query.classid,
+      isN: this.$route.query.isN,
+      tcid: this.$route.query.tcid,
       Juri: "",
       groupList: [],
       JuriList: [],
@@ -326,7 +328,11 @@ export default {
         this.org +
         "&type=2" +
         "&role=" +
-        this.role
+        this.role +
+        "&isN=" +
+        this.isN +
+        "&tcid=" +
+        this.tcid
       );
     },
     checkTest(cid) {

+ 29 - 5
src/components/pages/testStudent/view/preview.vue

@@ -25,7 +25,11 @@
       '&org=' +
       org +
       '&role=' +
-      role,
+      role +
+      '&isN=' +
+      isN +
+      '&tcid=' +
+      tcid ,
   }" v-else>表单中心</el-breadcrumb-item>
               <el-breadcrumb-item>
                 <span style="color: rgb(15, 126, 255)">{{ title }}</span>
@@ -68,6 +72,8 @@ export default {
       tid: this.$route.query.tid,
       type: this.$route.query.type,
       updateType: this.$route.query.type,
+      isN: this.$route.query.isN,
+      tcid: this.$route.query.tcid,
       steps: 1,
       title: "",
       brief: "",
@@ -119,7 +125,11 @@ export default {
               "&org=" +
               this.org +
               "&role=" +
-              this.role
+              this.role +
+              "&isN=" +
+              this.isN +
+              "&tcid=" +
+              this.tcid 
             );
           }
         })
@@ -492,7 +502,11 @@ export default {
             "&org=" +
             this.org +
             "&role=" +
-            this.role
+            this.role +
+            "&isN=" +
+            this.isN +
+            "&tcid=" +
+            this.tcid 
           );
         })
         .catch((err) => {
@@ -503,9 +517,15 @@ export default {
     publish() {
       let cjson = this.$refs['topicVue'].checkArray
       console.log(cjson);
+      let _uid = ''
+      if(this.isN == 1){
+        _uid = this.tcid
+      }else { 
+        _uid = (this.tid) ? this.tid : this.userid
+      }
       let params = [
         {
-          uid: (this.tid) ? this.tid : this.userid,
+          uid: _uid,
           cid: this.cid,
           cjson: JSON.stringify(cjson),
           type: '2',
@@ -535,7 +555,11 @@ export default {
               "&org=" +
               this.org +
               "&role=" +
-              this.role
+              this.role +
+              "&isN=" +
+              this.isN +
+              "&tcid=" +
+              this.tcid 
             );
           }
         })

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