lsc 7 ay önce
ebeveyn
işleme
b6d7d2fcbe

Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
src/assets/icon/course/setting.svg


+ 200 - 22
src/components/pages/aiAddCourse/addCourse.vue

@@ -177,11 +177,23 @@
                       </div>
                       <div class="info_box_t" v-if="!yiKeTemplateArray.includes(templateid)">
                         <div class="info_box_t_box">
-                          <el-switch v-model="isuseT" active-text="是否从已有教案生成"
-                              style="justify-content: center; min-width: 175px"></el-switch>
+                          <!-- <el-switch v-model="isuseT" active-text="是否从已有教案生成"
+                              style="justify-content: center; min-width: 175px"></el-switch> -->
+                          <span>生成模式:</span>
+                          <el-radio-group v-model="isuseT" style="display: flex; align-items: center">
+                            <!-- <div class="all_choose info_radio">
+                              <el-radio :label="1">引导模式生成</el-radio>
+                            </div> -->
+                            <div class="all_choose info_radio" style="margin-left: 10px">
+                              <el-radio :label="true">从已有教案生成</el-radio>
+                            </div>
+                            <div class="all_choose info_radio" style="margin-left: 10px">
+                              <el-radio :label="false">从零开始生成</el-radio>
+                            </div>
+                          </el-radio-group>
                         </div>
                         <div class="info_box_t_box">
-                          <span>AI生成模式:</span>
+                          <span>生成风格:</span>
                           <div class="mode_box">
                             <span :class="{active: mode == 1}" @click="mode = 1">精确</span>
                             <!-- <span :class="{active: mode == 2}" @click="mode = 2">平衡</span> -->
@@ -374,7 +386,7 @@
                 </div>
               </div>
             </div>
-            <div class="whiteBg" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;" v-if="(!yiKeTemplateArray.includes(templateid)) && isuseT">
+            <div class="whiteBg" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;" v-if="(!yiKeTemplateArray.includes(templateid)) && isuseT === true">
               <div style="position: relative;
                             background: #fff;
                             box-sizing: border-box;
@@ -528,7 +540,7 @@
                 </div>
               </div>
             </div>
-            <div class="whiteBg" :style="{ minHeight: teacherTextLoading ? '250px' : 'auto'}" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;position: relative" v-loading="teacherTextLoading" element-loading-text="小可正在努力生成中,请稍等..." v-if="(!yiKeTemplateArray.includes(templateid)) && isuseT">
+            <div class="whiteBg" :style="{ minHeight: teacherTextLoading ? '250px' : 'auto'}" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;position: relative" v-loading="teacherTextLoading" element-loading-text="小可正在努力生成中,请稍等..." v-if="(!yiKeTemplateArray.includes(templateid)) && isuseT === true">
               <div class="c_pub_button_confirm stopBtn" v-if="teacherTextLoading && isTeacherTextCancelToken" @click="cancelAjax('teacherText')">停止</div>
               <div class="whiteBg" style="border-radius: 0; margin-top: 15px">
                 <div class="c_info_title">
@@ -560,7 +572,7 @@
                 </div>
               </div>
             </div>
-            <div class="whiteBg" :style="{ minHeight: targetTextLoading ? '250px' : 'auto'}" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;" v-loading="targetTextLoading" element-loading-text="小可正在努力生成中,请稍等..." v-if="(!yiKeTemplateArray.includes(templateid)) && isuseT && templateid != '4480d65a-1e48-11ef-bee5-005056b86db5' && templateid != 'cf5722a4-401b-11ef-b873-005056b86dc3'">
+            <div class="whiteBg" :style="{ minHeight: targetTextLoading ? '250px' : 'auto'}" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;" v-loading="targetTextLoading" element-loading-text="小可正在努力生成中,请稍等..." v-if="(!yiKeTemplateArray.includes(templateid)) && isuseT === true && templateid != '4480d65a-1e48-11ef-bee5-005056b86db5' && templateid != 'cf5722a4-401b-11ef-b873-005056b86dc3'">
               <div class="c_pub_button_confirm stopBtn" v-if="targetTextLoading && isTargetCancelToken1" @click="cancelAjax('target1')">停止</div>
               <div class="whiteBg" style="border-radius: 0; margin-top: 15px">
                 <div class="c_info_title">
@@ -887,7 +899,7 @@
                 </div>
               </div>
             </div>
-            <div class="whiteBg" :style="{ minHeight: textLoading ? '250px' : 'auto'}" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;" v-loading="textLoading" element-loading-text="小可正在努力生成中,请稍等..." v-if="(!isuseT && (!yiKeTemplateArray.includes(templateid))) || (isuseT && (!yiKeTemplateArray.includes(templateid)) && courseTextBool) || (yiKeTemplateArray.includes(templateid))">
+            <div class="whiteBg" :style="{ minHeight: textLoading ? '250px' : 'auto'}" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;" v-loading="textLoading" element-loading-text="小可正在努力生成中,请稍等..." v-if="(!(isuseT === true) && !(isuseT === 1) && (!yiKeTemplateArray.includes(templateid))) || (isuseT === true && (!yiKeTemplateArray.includes(templateid)) && courseTextBool) || (yiKeTemplateArray.includes(templateid))">
                 <div class="c_pub_button_confirm stopBtn" v-if="textLoading && isTextCancelToken" @click="cancelAjax('text')">停止</div>
                 <div class="whiteBg" style="border-radius: 0; margin-top: 15px">
                 <div class="c_info_title" style="margin: 0 20px 0 20px;">
@@ -920,7 +932,49 @@
                 </div>
               </div>
             </div>
-            <div class="whiteBg" :style="{ minHeight: targetTextLoading2 ? '250px' : 'auto'}" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;" v-loading="targetTextLoading2" element-loading-text="小可正在努力生成中,请稍等..." v-if="((!isuseT && (!yiKeTemplateArray.includes(templateid))) || (isuseT && (!yiKeTemplateArray.includes(templateid)) && courseTextBool)) && templateid != '4480d65a-1e48-11ef-bee5-005056b86db5' && templateid != 'cf5722a4-401b-11ef-b873-005056b86dc3'">
+            <div class="whiteBg" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;" v-loading="textLoading" element-loading-text="小可正在努力生成中,请稍等..." v-if="(isuseT === 1)">
+                <div class="whiteBg" style="border-radius: 0; margin-top: 15px">
+                <div class="c_info_title" style="margin: 0 20px 0 20px;position:relative;">
+                  课程概况<span class="inter_setting" @click="openInterPanSetting"></span>
+                  <div class="inter_setting_panel" v-show="interSetting">
+                    <div class="panel_title">配置工作流</div>
+                    <div class="panel_tips">您可在创作者中心中创建工作流后,复制工作流链接并贴入</div>
+                    <div class="panel_input">
+                      <input type="text" :placeholder="this.aiJson.agentid ? this.aiJson.agentid : '请输入agentid'" class="binfo_input" v-model="agentid"/>
+                    </div>
+                    <div class="panel_button">
+                      <button class="c_pub_button_confirm" @click="setAgentid">确认</button>
+                      <button class="c_pub_button_confirm" @click="rebuildAgentid" v-if="istemplate != 1">复原</button>
+                      <button class="c_pub_button_return" @click="cancelInterSetting">取消</button>
+                    </div>
+                  </div>
+                  <button class="c_pub_button_confirm" style="margin: 0 0 0 auto;" @click="interPan = !interPan">{{ interPan ? '折叠' : '展开'}}</button>
+                </div>
+                <div style="width: 100%; padding: 0px 20px; box-sizing: border-box;display:flex;">
+                  <div class="inter_box" v-show="interPan">
+                    <iframe :src="interUrl" frameborder="0"></iframe>
+                  </div>
+                  <div style="width: calc(100%);height: 100%" class='op_task_box'>
+                    <textarea style="height: 500px" class="binfo_input binfo_textarea" cols v-model="courseText"
+                      placeholder="请输入课程简要描述" v-if="courseTextB"></textarea>
+                    <div class="markBox vditor-reset" style="white-space:pre-wrap;height: 500px;overflow-y:auto" v-text="courseText" v-else-if="textLoading"></div>
+                    <div class="markBox vditor-reset" style="height: 500px;overflow-y:auto" v-html="MarkdownT(courseText)" v-else></div>
+                      <div class="op_box">
+                        <div class="op_remark"></div>
+                        <div style="display: flex;">
+                          <!-- <el-tooltip effect="light" content="右键单击可配置提示词" placement="bottom">
+                            <div class="r_pub_button_op"
+                              @contextmenu.prevent="openAiDialog(1, 'aiDetail', 2)"
+                              @click="openAiDialog(2, 'aiDetail', 2)">智能优化</div>
+                          </el-tooltip> -->
+                          <div class="r_pub_button_edit" style="margin-left:10px" @click="courseTextB = !courseTextB">{{ courseTextB ? '确定' : '编辑'}}</div>
+                        </div>
+                      </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div class="whiteBg" :style="{ minHeight: targetTextLoading2 ? '250px' : 'auto'}" style="background: #fff; margin: 0 0 10px;padding: 0 0 15px;" v-loading="targetTextLoading2" element-loading-text="小可正在努力生成中,请稍等..." v-if="((!(isuseT === true) && (!yiKeTemplateArray.includes(templateid))) || (isuseT === true && (!yiKeTemplateArray.includes(templateid)) && courseTextBool)) && templateid != '4480d65a-1e48-11ef-bee5-005056b86db5' && templateid != 'cf5722a4-401b-11ef-b873-005056b86dc3'">
                 <div class="c_pub_button_confirm stopBtn" v-if="targetTextLoading2 && isTargetCancelToken2" @click="cancelAjax('target2')">停止</div>
                 <div class="whiteBg" style="border-radius: 0; margin-top: 15px">
                 <div class="c_info_title" style="flex-wrap: wrap; position:relative;margin:0 20px;">
@@ -1601,11 +1655,11 @@
               <button class="c_pub_button_return pub_btn_last_img" v-if="steps > 1 && steps != 5" @click="lastSteps">
                 {{ steps == 4 ? "返回课程" : "上一步" }}
               </button>
-              <button class="c_pub_button_confirm" v-if="isuseT && !isOutline && !courseTextBool && (!yiKeTemplateArray.includes(templateid)) && templateid != '4480d65a-1e48-11ef-bee5-005056b86db5' && templateid != 'cf5722a4-401b-11ef-b873-005056b86dc3'" @click="clickGenTT2">
-                {{isuseT ? "重新生成概况和目标" : "生成概况和目标"}}
+              <button class="c_pub_button_confirm" v-if="isuseT === true && !isOutline && !courseTextBool && (!yiKeTemplateArray.includes(templateid)) && templateid != '4480d65a-1e48-11ef-bee5-005056b86db5' && templateid != 'cf5722a4-401b-11ef-b873-005056b86dc3'" @click="clickGenTT2">
+                {{isuseT === true ? "重新生成概况和目标" : "生成概况和目标"}}
               </button>
-              <button class="c_pub_button_confirm" v-else-if="isuseT && !isOutline && !courseTextBool && (!yiKeTemplateArray.includes(templateid))" @click="clickGenTT2">
-                {{isuseT ? "重新生成概况" : "生成概况"}}
+              <button class="c_pub_button_confirm" v-else-if="isuseT === true && !isOutline && !courseTextBool && (!yiKeTemplateArray.includes(templateid))" @click="clickGenTT2">
+                {{isuseT === true ? "重新生成概况" : "生成概况"}}
               </button>
               <!-- ((isuseT || courseTextBool) && (!yiKeTemplateArray.includes(templateid))) &&  -->
               <el-tooltip effect="light" content="右键单击可配置提示词" placement="top"  v-if="steps < 4">
@@ -5351,6 +5405,9 @@
         <aiTips ttitle="任务详情" title="任务评价优化" :detail="aiJson.aiDetail4" pan="aiDetail4" @setAiJson="setAiJson" />
         <aiTips ttitle="任务详情" title="生成评价细则" :detail="aiJson.aiRateRule" pan="aiRateRule" @setAiJson="setAiJson"/>
       </div>
+      <div class="leftBar2" v-if="istemplate != 1 && templateid == 'cf5722a4-401b-11ef-b873-005056b86cd2'">
+        <aiBoxRight  :courseId="courseId" :unitJson="unitJson"></aiBoxRight>
+      </div>
     </div>
     <el-dialog title="提示" :visible.sync="dialogVisible" :append-to-body="true" width="25%" :before-close="handleClose"
       class="dialog_diy2 customWidth">
@@ -6885,6 +6942,7 @@ import englishRight from "../components/englishRight.vue";
 import evaBox from "../evaBox/index.vue";
 import EnglishVoice from "../EnglishVoice/index.vue";
 import aiBox from './aiBox.vue'
+import aiBoxRight from './aiBoxRight.vue'
 import aiDialog from './aiDialog'
 import aiTips from './aiTips.vue'
 import tipsDialog from './tipsDialog.vue'
@@ -6917,6 +6975,7 @@ export default {
     evaBox,
     EnglishVoice,
     aiBox,
+    aiBoxRight,
     aiDialog,
     aiTips,
     tipsDialog,
@@ -7348,7 +7407,10 @@ export default {
       isTeacherTextCancelSource: null,
       isTargetCancelSource1: null,
       isTargetCancelSource2: null,
-      fileidArray: []
+      fileidArray: [],
+      interPan: true,
+      agentid: "",
+      interSetting: false
     };
   },
   directives: {
@@ -7510,7 +7572,18 @@ export default {
         }
         return false;
       };
-    }
+    },
+    interUrl: function () {
+      let agentid = this.aiJson.agentid
+      let sagentid = this.aiJson.sagentid
+      let url = ''
+      if(sagentid){
+        url = 'https://beta.cloud.cocorobo.cn/aigpt/#/js?active_role=6&agentid='+sagentid+'&sagentid='+agentid
+      }else{
+        url = 'https://beta.cloud.cocorobo.cn/aigpt/#/js?active_role=6&agentid='+agentid+'&sagentid='+agentid
+      }
+      return url;
+    },
   },
   watch: {
     unitIndex(newValue, oldValue) {
@@ -11709,6 +11782,9 @@ export default {
             this.aiJson.aiTaskG2 = this.aiJson.aiTaskG2 ? this.aiJson.aiTaskG2 : '请根据<教学任务教案> 和 #范例 为该教学任务输出学生任务单中的互动工具列表。你的任务是,根据教案中提到的学生活动,为学生选择一些平台上有的互动工具,允许他们提交“证据”(即过程性成果)来展示他们的学习进度或者证明他们的学习成果。举例:如果学生活动有观看视频回答问题,那么你就为这一活动匹配选择【问答】工具,允许学生回答问题或者提出他们自己的疑问,如果学生活动有需要学生设计实验或者撰写报告,选用【文档】工具,如果需要学生记录数据,选用【表格】工具,如果需要学生整理或者梳理信息选用【思维导图】,如果需要学生绘制草图,选用【电子白板】,如果需要学生提交视频,图片,或者ppt,选用【作业提交】。你的输出需要符合# 输出格式与要求'
             this.aiJson.aiTaskG3 = this.aiJson.aiTaskG3 ? this.aiJson.aiTaskG3 : '请根据<教学任务教案> 和 #范例 为该教学任务输出学生任务单中的目标和评价系统。你最主要的任务是提取教案中目标以及评价标准。你的输出需要符合# 输出格式与要求'
 
+            this.aiJson.agentid = this.aiJson.agentid ? this.aiJson.agentid : 'agentid'
+            this.aiJson.sagentid = this.aiJson.sagentid ? this.aiJson.sagentid : ''
+
             // if(this.templateid == '4480d65a-1e48-11ef-bee5-005056b86db5'){
             //   this.aiJson.aiCpoteTask = this.aiJson.aiCpoteTask ? this.aiJson.aiCpoteTask : '请根据<任务簇>,帮我取出里面对应的任务名'
             // }
@@ -13698,6 +13774,8 @@ export default {
                 this.aiJson.aiTaskG2 = this.aiJson.aiTaskG2 ? this.aiJson.aiTaskG2 : '请根据<教学任务教案> 和 #范例 为该教学任务输出学生任务单中的互动工具列表。你的任务是,根据教案中提到的学生活动,为学生选择一些平台上有的互动工具,允许他们提交“证据”(即过程性成果)来展示他们的学习进度或者证明他们的学习成果。举例:如果学生活动有观看视频回答问题,那么你就为这一活动匹配选择【问答】工具,允许学生回答问题或者提出他们自己的疑问,如果学生活动有需要学生设计实验或者撰写报告,选用【文档】工具,如果需要学生记录数据,选用【表格】工具,如果需要学生整理或者梳理信息选用【思维导图】,如果需要学生绘制草图,选用【白板】,如果需要学生提交视频,图片,或者ppt,选用【作业提交】。你的输出需要符合# 输出格式与要求'
                 this.aiJson.aiTaskG3 = this.aiJson.aiTaskG3 ? this.aiJson.aiTaskG3 : '请根据<教学任务教案> 和 #范例 为该教学任务输出学生任务单中的目标和评价系统。你最主要的任务是提取教案中目标以及评价标准。你的输出需要符合# 输出格式与要求'
 
+                this.aiJson.agentid = this.aiJson.agentid ? this.aiJson.agentid : 'agentid'
+                this.aiJson.sagentid = this.aiJson.sagentid ? this.aiJson.sagentid : ''
                 this.templateid = res.data[3][0].template;
               }catch(error){
                 console.error(error)
@@ -13722,15 +13800,15 @@ export default {
                 this.xuanzeInfoData = JSON.parse(res.data[0][0].setting).xuanzeInfoData ? JSON.parse(res.data[0][0].setting).xuanzeInfoData : [];
                 this.pingjiaInfoData = JSON.parse(res.data[0][0].setting).pingjiaInfoData ? JSON.parse(res.data[0][0].setting).pingjiaInfoData : [];
                 this.infoData2 = JSON.parse(res.data[0][0].setting).infoData2 ? JSON.parse(res.data[0][0].setting).infoData2 : [];
-                this.isuseT = JSON.parse(res.data[0][0].setting).isuseT ? JSON.parse(res.data[0][0].setting).isuseT : JSON.parse(res.data[0][0].setting).isuseT === false ? false : false;
+                this.isuseT = JSON.parse(res.data[0][0].setting).isuseT ? JSON.parse(res.data[0][0].setting).isuseT : JSON.parse(res.data[0][0].setting).isuseT === false ? false : 1;
                 this.mode = JSON.parse(res.data[0][0].setting).mode ? JSON.parse(res.data[0][0].setting).mode : 1;
                 this.targetCourseText2 = JSON.parse(res.data[0][0].setting).targetCourseText2 ? JSON.parse(res.data[0][0].setting).targetCourseText2 : '';
                 if(this.targetCourseText2 || (!this.teacherCourseText)){
                   this.courseTextBool = true
                 }
-                if(!this.teacherCourseText && !this.teacherCourseText){
-                  this.isuseT = false
-                }
+                // if(!this.teacherCourseText && !this.targetCourseText2){
+                //   this.isuseT = 1
+                // }
               }catch(error){
                 console.error(error)
               }
@@ -13848,6 +13926,9 @@ export default {
             this.aiJson.aiTaskG1 = this.aiJson.aiTaskG1 ? this.aiJson.aiTaskG1 : '请根据<教学任务教案> 和 #范例 为该教学任务输出学生任务单中的任务描述。你的主要任务是输出任务描述,用亲切的口吻告诉学生他们需要做什么。你的输出需要符合# 输出格式与要求'
             this.aiJson.aiTaskG2 = this.aiJson.aiTaskG2 ? this.aiJson.aiTaskG2 : '请根据<教学任务教案> 和 #范例 为该教学任务输出学生任务单中的互动工具列表。你的任务是,根据教案中提到的学生活动,为学生选择一些平台上有的互动工具,允许他们提交“证据”(即过程性成果)来展示他们的学习进度或者证明他们的学习成果。举例:如果学生活动有观看视频回答问题,那么你就为这一活动匹配选择【问答】工具,允许学生回答问题或者提出他们自己的疑问,如果学生活动有需要学生设计实验或者撰写报告,选用【文档】工具,如果需要学生记录数据,选用【表格】工具,如果需要学生整理或者梳理信息选用【思维导图】,如果需要学生绘制草图,选用【白板】,如果需要学生提交视频,图片,或者ppt,选用【作业提交】。你的输出需要符合# 输出格式与要求'
             this.aiJson.aiTaskG3 = this.aiJson.aiTaskG3 ? this.aiJson.aiTaskG3 : '请根据<教学任务教案> 和 #范例 为该教学任务输出学生任务单中的目标和评价系统。你最主要的任务是提取教案中目标以及评价标准。你的输出需要符合# 输出格式与要求'
+
+            this.aiJson.agentid = this.aiJson.agentid ? this.aiJson.agentid : 'agentid'
+            this.aiJson.sagentid = this.aiJson.sagentid ? this.aiJson.sagentid : ''
             if(res.data[0][0].cpote){
               try {
                 this.cpote = JSON.parse(res.data[0][0].cpote);
@@ -13867,15 +13948,15 @@ export default {
                 this.xuanzeInfoData = JSON.parse(res.data[0][0].setting).xuanzeInfoData ? JSON.parse(res.data[0][0].setting).xuanzeInfoData : [];
                 this.pingjiaInfoData = JSON.parse(res.data[0][0].setting).pingjiaInfoData ? JSON.parse(res.data[0][0].setting).pingjiaInfoData : [];
                 this.infoData2 = JSON.parse(res.data[0][0].setting).infoData2 ? this.infoData2.length ? this.infoData2 : JSON.parse(res.data[0][0].setting).infoData2 : [...this.infoData2];
-                this.isuseT = JSON.parse(res.data[0][0].setting).isuseT ? JSON.parse(res.data[0][0].setting).isuseT : JSON.parse(res.data[0][0].setting).isuseT === false ? false : false;
+                this.isuseT = JSON.parse(res.data[0][0].setting).isuseT ? JSON.parse(res.data[0][0].setting).isuseT : JSON.parse(res.data[0][0].setting).isuseT === false ? false : 1;
                 this.mode = JSON.parse(res.data[0][0].setting).mode ? JSON.parse(res.data[0][0].setting).mode : 1;
                 this.targetCourseText2 = JSON.parse(res.data[0][0].setting).targetCourseText2 ? JSON.parse(res.data[0][0].setting).targetCourseText2 : '';
                 if(this.targetCourseText2 || (!this.teacherCourseText)){
                   this.courseTextBool = true
                 }
-                if(!this.teacherCourseText && !this.teacherCourseText){
-                  this.isuseT = false
-                }
+                // if(!this.teacherCourseText && !this.targetCourseText2){
+                //   this.isuseT = 1
+                // }
               }catch(error){
                 console.error(error)
               }
@@ -15887,6 +15968,33 @@ export default {
 
       this.courseTextBool = true
     },
+    openInterPanSetting(){
+      this.interSetting = !this.interSetting
+      if(this.interSetting){
+        if(this.istemplate == 1){
+          this.agentid = this.aiJson.agentid
+        }else {
+          this.agentid = this.aiJson.sagentid
+        }
+      }else {
+        this.agentid = ''
+      }
+    },
+    setAgentid(){
+      if(this.istemplate == 1){
+        this.aiJson.agentid = this.agentid
+      }else {
+        this.aiJson.sagentid = this.agentid
+      }
+      this.interSetting = false
+    },
+    rebuildAgentid(){
+      this.aiJson.sagentid = ''
+    },
+    cancelInterSetting(){
+      this.agentid = ''
+      this.interSetting = false
+    },
     openAiDialog2(clickType, type, callback, index, tindex){
       this.$confirm("重新生成会影响已生成内容,确定重新生成吗?", "提示", {
         confirmButtonText: "确定",
@@ -22356,6 +22464,8 @@ ${msg}
       this.aiJson.aiTaskG2 = this.aiJson.aiTaskG2 ? this.aiJson.aiTaskG2 : '请根据<教学任务教案> 和 #范例 为该教学任务输出学生任务单中的互动工具列表。你的任务是,根据教案中提到的学生活动,为学生选择一些平台上有的互动工具,允许他们提交“证据”(即过程性成果)来展示他们的学习进度或者证明他们的学习成果。举例:如果学生活动有观看视频回答问题,那么你就为这一活动匹配选择【问答】工具,允许学生回答问题或者提出他们自己的疑问,如果学生活动有需要学生设计实验或者撰写报告,选用【文档】工具,如果需要学生记录数据,选用【表格】工具,如果需要学生整理或者梳理信息选用【思维导图】,如果需要学生绘制草图,选用【白板】,如果需要学生提交视频,图片,或者ppt,选用【作业提交】。你的输出需要符合# 输出格式与要求'
       this.aiJson.aiTaskG3 = this.aiJson.aiTaskG3 ? this.aiJson.aiTaskG3 : '请根据<教学任务教案> 和 #范例 为该教学任务输出学生任务单中的目标和评价系统。你最主要的任务是提取教案中目标以及评价标准。你的输出需要符合# 输出格式与要求'
 
+      this.aiJson.agentid = this.aiJson.agentid ? this.aiJson.agentid : 'agentid'
+      this.aiJson.sagentid = this.aiJson.sagentid ? this.aiJson.sagentid : ''
     }
     this.loading = false;
     // this.timer2 = setInterval(() => {
@@ -22533,6 +22643,20 @@ ${msg}
   margin-right: 10px;
 }
 
+.leftBar2{
+  width: 400px;
+  min-width: 400px;
+  height: calc(100% - 50px);
+  overflow: auto;
+  border-radius: 5px;
+  margin: 25px auto;
+  box-sizing: border-box;
+  margin-right: 10px;
+  background: #fff;
+  padding: 5px;
+  border-radius: 5px;
+}
+
 .basic_box {
   margin: 0 auto;
   position: relative;
@@ -26615,6 +26739,7 @@ ol {
   font-size: 16px;
   background: #f4f4f4;
   border-radius: 5px;
+  word-break: break-word;
 }
 
 .info_box_t{
@@ -26644,6 +26769,10 @@ ol {
   margin: 0 5px 0 0;
 }
 
+.info_radio >>> .el-radio, .el-radio__input{
+  line-height: 18px;
+  height: 18px;
+}
 
 .mode_box{
   display: flex;
@@ -26710,4 +26839,53 @@ ol {
 .rateSwitch >>> .el-switch__label--right.is-active::before{
   background-image: url(../../../assets/icon/new/u_op.png);
 }
+
+.inter_box{
+  min-width: calc(50%);
+  min-height: 500px;
+  margin-right: 10px;
+
+}
+.inter_box > iframe{
+  width: 100%;
+  height: 100%;
+  border: none;
+}
+.inter_setting{
+  display: block;
+  background-image: url(../../../assets/icon/course/setting.svg);
+  background-size: 100% 100%;
+  width: 20px;
+  height: 20px;
+  cursor: pointer;
+  margin-left: 10px;
+}
+.inter_setting_panel{
+  position: absolute;
+  left: 110px;
+  top: 30px;
+  background: #fff;
+  border-radius: 5px;
+  box-shadow: 0px 0px 2px 1px #00000017;
+  padding: 10px;
+}
+.panel_title{
+  text-align: center;
+  font-size: 18px;
+  margin-bottom: 10px;
+}
+.panel_tips{
+  font-weight: 500;
+  font-size: 14px;
+  text-align: center;
+  margin-bottom: 10px;
+  color: #6d6d6d;
+}
+.panel_input{
+  margin-bottom: 10px;
+}
+.panel_button{
+  display: flex;
+  justify-content: space-between;
+}
 </style>

+ 728 - 0
src/components/pages/aiAddCourse/aiBoxRight.vue

@@ -0,0 +1,728 @@
+<template>
+  <div class="ai_body">
+    <div class="ai_body_dialog" v-loading="loading" ref="chatDialog">
+      <div
+        class="dialog_content"
+        v-for="(item) in array"
+        :key="item.uid"
+      >
+        <div v-if="item.content" style="margin-left: auto;">
+          <div class="content content2" v-html="item.content"></div>
+          <div class="role">
+            <img src="../../../assets/icon/new/role2.png" />
+          </div>
+        </div>
+        <div style="margin-top:10px; margin-right: auto;">
+          <div class="role">
+            <img src="../../../assets/icon/new/role1.png" />
+          </div>
+          <div
+           element-loading-background="#f6f9ff" 
+           :style="{minHeight: item.loading ? '50px' : 'unset'}"
+            class="content"
+            v-loading="item.loading"
+            v-html="item.aiContent"
+          ></div>
+        </div>
+      </div>
+    </div>
+    <div class="ai_body_select" v-if="false">
+      <div class="checkBox" v-if="checkBool">
+        <div class="task">
+          <div class="title">选择需要优化的任务:</div>
+          <div class="content">
+            <div class="span" @click="addAllTask()">
+              <div class="check">
+                <img
+                  :src="checkImg"
+                  alt=""
+                  v-if="checkArray.length !== course.length"
+                />
+                <img :src="checkIsImg" alt="" v-else />
+              </div>
+              <span>全选</span>
+            </div>
+            <div
+              class="span"
+              v-for="(item, index) in course"
+              :key="index"
+              @click="addTask(index)"
+            >
+              <div class="check">
+                <img
+                  :src="checkImg"
+                  alt=""
+                  v-if="checkArray.indexOf(index) === -1"
+                />
+                <img :src="checkIsImg" alt="" v-else />
+              </div>
+              <span>任务{{ index + 1 }}</span>
+            </div>
+          </div>
+        </div>
+        <div class="part">
+          <div class="title">选择优化的部分:</div>
+          <div class="content">
+            <div
+              class="span"
+              v-for="(item, index) in partArray"
+              :key="index"
+              :class="{ active: part == item.name }"
+              @click="checkPart(item.name)"
+            >
+              {{ item.name }}
+            </div>
+          </div>
+        </div>
+      </div>
+      <span
+        class="check"
+        :class="{ isCheck: checkBool }"
+        v-if="!checkArray.length && !part"
+        @click="checkBool = !checkBool"
+        >选择优化内容</span
+      >
+      <span
+        class="check"
+        :class="{ isCheck: checkBool }"
+        @click="checkBool = !checkBool"
+        v-else
+      >
+        <el-tooltip :content="taskName" placement="top" effect="dark">
+          <!-- content to trigger tooltip here -->
+          <span>{{ taskName }}</span>
+        </el-tooltip>
+      </span>
+    </div>
+    <div class="ai_body_input">
+      <textarea
+        style="padding-right: 85px;"
+        rows="3"
+        @keyup.enter="addContent"
+        class="binfo_input binfo_textarea"
+        cols
+        v-model.trim="courseText"
+        placeholder="在此输入您想了解的内容"
+      ></textarea>
+      <div
+        class="c_pub_button_confirm"
+        v-if="!loading && courseText"
+        @click="addContent"
+      >
+        发送
+      </div>
+      <div class="c_pub_button_confirm" @click="promptTit" v-else>发送</div>
+    </div>
+  </div>
+</template>
+
+<script>
+import checkImg from "../../../assets/icon/sourceFile/check.png";
+import checkIsImg from "../../../assets/icon/sourceFile/check_is.png";
+import { v4 as uuidv4 } from "uuid";
+import MarkdownIt from "markdown-it";
+export default {
+  props: {
+    unitJson: {
+      type: Array
+    },
+		courseId:{
+			type:String,
+			default:""
+		},
+  },
+  data() {
+    return {
+      array: [],
+      courseText: "",
+      checkImg: checkImg,
+      checkIsImg: checkIsImg,
+			userid: this.$route.query.userid,
+      checkArray: [],
+      course: [{ title: "任务1" }, { title: "任务2" }, { title: "任务3" }],
+      partArray: [
+        { name: "全部内容" },
+        { name: "任务设计" },
+        { name: "评价设计" }
+      ],
+      part: "全部内容",
+      checkBool: false,
+      loading: false
+    };
+  },
+  watch: {
+    unitJson: {
+      immediate: true,
+      deep: true,
+      handler(newValue, oldValue) {
+        this.course = this.unitJson[0].chapterInfo[0].taskJson;
+      }
+    }
+  },
+  methods: {
+    promptTit() {
+      if (!this.loading && !this.courseText) {
+        this.$message({
+          message: "请输入您想要了解的内容",
+          type: "warning"
+        });
+      } else {
+        this.$message({
+          message: "请回答完毕后再次发送",
+          type: "warning"
+        });
+      }
+    },
+    addContent() {
+      let message = this.courseText
+      if (this.courseText) {
+        let msg = `
+          ATTENTION: Use '##' to SPLIT SECTIONS, not '#'.Output format carefully referenced "Format example".`
+        if(this.checkArray.length){
+          let task = []
+          if(this.part == "全部内容"){
+            for(var i = 0; i < this.checkArray.length; i++){
+              let _index = this.checkArray[i]
+              task.push(this.course[_index])
+            }
+          }else if(this.part == "任务设计"){
+            for(var i = 0; i < this.checkArray.length; i++){
+              let _index = this.checkArray[i]
+              task.push(this.course[_index])
+            }
+          }else if(this.part == "评价设计"){
+            for(var i = 0; i < this.checkArray.length; i++){
+              let _index = this.checkArray[i]
+              task.push(this.course[_index].eList)
+            }
+          }
+          
+          msg += `
+          --------
+          ## 修改内容
+          ${JSON.stringify(task)}
+          `
+
+          msg += `
+          --------
+          ## 要求
+          ${this.courseText}
+          `
+          message = msg
+        }
+        let _uuid = uuidv4();
+        this.array.push({
+          role: "user",
+          content: `${this.courseText}`,
+          uid: _uuid,
+          AI: "AI",
+          aiContent: "",
+          oldContent: "",
+          isShowSynchronization: false,
+          filename: "",
+          index: this.array.length,
+          is_mind_map: false,
+          loading: true
+        });
+        this.$nextTick(() => {
+          this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
+        });
+        let params = JSON.stringify({
+          // model: "gpt-3.5-turbo",
+          model: 'gpt-4o-2024-08-06',
+          temperature: 0,
+          max_tokens: 4096,
+          top_p: 1,
+          frequency_penalty: 0,
+          presence_penalty: 0,
+          messages: [{ role: "user", content: message }],
+          uid: _uuid,
+          mind_map_question: ""
+        });
+        this.courseText = "";
+
+        this.ajax.post("https://gpt4.cocorobo.cn/chat", params).then(res => {
+            if (res.data.FunctionResponse.result == "发送成功") {
+            } else {
+              this.$message.warning(res.data.FunctionResponse.result);
+            }
+          })
+          .catch(e => {
+            console.log(e);
+          });
+        this.getAiContent(_uuid);
+      }
+    },
+    getAiContent(_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.$nextTick(() => {
+            this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
+          });
+          this.array.find(i => i.uid == _uid).aiContent = _mdText;
+          this.array.find(i => i.uid == _uid).isalltext = true;
+          this.array.find(i => i.uid == _uid).isShowSynchronization = true;
+          this.array.find(i => i.uid == _uid).loading = 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.array.find(i => i.uid == _uid).aiContent = _mdText;
+          this.array.find(i => i.uid == _uid).loading = false;
+          this.$nextTick(() => {
+            this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
+          });
+          // 处理流数据
+        }
+      };
+    },
+    //保存消息
+    insertChat(_uid) {
+      let _data = this.array.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: _data.fileid ? _data.fileid : "",
+        alltext: _data.aiContent,
+        type: "chat",
+        filename: _data.filename,
+        session_name: `${this.courseId}-addCourse` //这是对话记录位置
+      };
+      this.ajax
+        .post("https://gpt4.cocorobo.cn/insert_chat", params)
+        .then(res => {});
+    },
+    // 获取对应的聊天记录
+    getChatList() {
+      return new Promise((resolve, reject) => {
+        if (this.loading) return this.$message.info("请稍等...");
+        this.array = [];
+        this.loading = true;
+        let params = {
+          userid: this.userid,
+          groupid: "602def61-005d-11ee-91d8-005056b8q12w",
+          // session_name:``
+          session_name: `${this.courseId}-addCourse`
+        };
+        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) {
+              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
+                });
+              }
+              this.array = _chatList;
+              this.loading = false;
+            } else {
+              //没有对话记录
+              this.loading = false;
+            }
+            resolve();
+          })
+          .catch(err => {
+            console.log(err);
+            this.$message.error("获取对话记录失败");
+            this.loading = false;
+            resolve();
+          });
+      });
+    },
+    addTask(index) {
+      if (this.checkArray.indexOf(index) !== -1) {
+        this.checkArray.splice(this.checkArray.indexOf(index), 1);
+      } else {
+        this.checkArray.push(index);
+      }
+      console.log(index);
+    },
+    addAllTask() {
+      if (this.checkArray.length === this.course.length) {
+        this.checkArray = [];
+      } else {
+        this.checkArray = [];
+        this.course.forEach((item, index) => {
+          this.checkArray.push(index);
+        });
+      }
+    },
+    checkPart(name) {
+      this.part = name;
+    }
+  },
+  computed: {
+    courseTextLength() {
+      return this.courseText.length;
+    },
+    taskName() {
+      let task = "";
+      if (this.checkArray.length) {
+        task = "任务";
+        this.checkArray = this.checkArray.sort((a, b) => a - b);
+        let a = JSON.parse(JSON.stringify(this.checkArray));
+        for (let index = 0; index < a.length; index++) {
+          a[index]++;
+        }
+        task += a.join("/");
+      }
+      return task + " " + this.part;
+    }
+  },
+  mounted() {
+    this.getChatList().then(_ => {
+      this.$nextTick(() => {
+				console.log(this.$refs.chatDialog.scrollHeight)
+        this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
+      });
+    });
+  }
+};
+</script>
+
+<style scoped>
+.ai_body {
+  height: 100%;
+  width: calc(100% - 20px);
+  margin: 0 auto;
+  display: flex;
+  flex-direction: column;
+}
+
+.binfo_input {
+  width: 100%;
+  margin: 0;
+  padding: 12px 14px;
+  display: block;
+  min-width: 0;
+  outline: none;
+  box-sizing: border-box;
+  background: none;
+  border: none;
+  border-radius: 4px;
+  background: #fff;
+  font-size: 14px;
+  resize: none;
+  font-family: "Microsoft YaHei";
+  min-height: 48px;
+  /* border: 1px solid #3682fc00; */
+  border: 1.5px solid #cad1dc;
+}
+
+.binfo_textarea {
+  border: 1.5px solid #cad1dc;
+  font-size: 14px;
+  resize: none;
+  /* background: #f6f6f6; */
+  font-family: "Microsoft YaHei";
+}
+
+.binfo_textarea::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 6px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 6px;
+}
+
+/*定义滚动条轨道 内阴影+圆角*/
+.binfo_textarea::-webkit-scrollbar-track {
+  border-radius: 10px;
+  background-color: rgba(0, 0, 0, 0.1);
+}
+
+/*定义滑块 内阴影+圆角*/
+.binfo_textarea::-webkit-scrollbar-thumb {
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
+  background-color: rgba(0, 0, 0, 0.1);
+}
+
+.binfo_input:focus-visible {
+  border: 1.5px solid #3681fc !important;
+}
+
+.ai_body_input {
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: end;
+  margin-top: auto;
+  min-height: fit-content;
+}
+
+.c_pub_button_confirm {
+  /* position: absolute;
+    bottom: 13px;
+    right: 13px; */
+  margin-top: 10px;
+  width: 80px;
+  display: flex;
+  justify-content: center;
+  position: absolute;
+  right: 12px;
+  bottom: 6px;
+}
+
+.ai_body_dialog {
+  padding: 10px 0;
+  box-sizing: border-box;
+  height: calc(100%);
+  overflow: auto;
+  margin-bottom: 10px;
+}
+
+.dialog_content {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+}
+
+.dialog_content > div {
+  display: flex;
+  align-items: flex-start;
+}
+
+.dialog_content + .dialog_content {
+  margin: 15px 0;
+}
+
+.dialog_content > div .right {
+  flex-direction: row-reverse;
+}
+
+.dialog_content > div .right .role {
+  margin-right: 0;
+  margin-left: 10px;
+}
+
+.dialog_content > div .role {
+  min-width: 30px;
+  width: 30px;
+  height: 30px;
+  margin-right: 10px;
+  border-radius: 50%;
+}
+
+.dialog_content > div .role > img {
+  height: 100%;
+  width: 100%;
+}
+
+.dialog_content > div .content {
+  padding: 10px 10px;
+  border-radius: 2px 8px 8px 8px;
+  width: 100%;
+  word-break: break-word;
+  box-sizing: border-box;
+  /* white-space: pre-line; */
+  max-width: 100%;
+  background: #f6f9ff;
+  overflow: hidden;
+  margin: 0 10px;
+}
+
+.dialog_content > div .content2 {
+  background: #3681fc;
+  color: #fff;
+  border-radius: 8px 2px 8px 8px;
+}
+
+.ai_body_select {
+  position: relative;
+}
+
+.ai_body_select > .check {
+  background: #e7e7e7;
+  display: flex;
+  width: fit-content;
+  padding: 0 10px;
+  height: 30px;
+  border-radius: 21px;
+  font-size: 14px;
+  align-items: center;
+  justify-content: center;
+  color: #0061ff;
+  font-weight: 700;
+  margin: 10px 0;
+  cursor: pointer;
+}
+
+.ai_body_select > .check::before {
+  content: "";
+  width: 15px;
+  height: 15px;
+  display: block;
+  background-image: url("../../../assets/icon/course/aiPart.png");
+  background-size: 100% 100%;
+  margin-right: 5px;
+}
+
+.ai_body_select > .check::after {
+  content: "";
+  width: 15px;
+  height: 15px;
+  display: block;
+  background-image: url("../../../assets/icon/course/aiPart_arrow.png");
+  background-size: 100% 100%;
+  margin-right: 5px;
+}
+
+.ai_body_select > .isCheck {
+  background: #0061ff;
+  display: flex;
+  width: fit-content;
+  padding: 0 10px;
+  height: 30px;
+  border-radius: 21px;
+  font-size: 14px;
+  align-items: center;
+  justify-content: center;
+  color: #fff;
+  font-weight: 700;
+  margin: 10px 0;
+  cursor: pointer;
+  max-width: 100%;
+  box-sizing: border-box;
+}
+
+.ai_body_select > .isCheck > span {
+  width: calc(100% - 40px);
+  display: block;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+
+.ai_body_select > .isCheck::before {
+  content: "";
+  width: 15px;
+  height: 15px;
+  display: block;
+  background-image: url("../../../assets/icon/course/aiPart_active.png");
+  background-size: 100% 100%;
+  margin-right: 5px;
+}
+
+.ai_body_select > .isCheck::after {
+  content: "";
+  width: 15px;
+  height: 15px;
+  display: block;
+  background-image: url("../../../assets/icon/course/aiPart_arrow_active.png");
+  background-size: 100% 100%;
+  margin-right: 5px;
+}
+
+.ai_body_select > .checkBox {
+  position: absolute;
+  bottom: 40px;
+  border: 1px solid #e0eafb;
+  width: 100%;
+  height: 300px;
+  background: #fff;
+  border-radius: 5px;
+  padding: 10px;
+  box-sizing: border-box;
+}
+
+.ai_body_select > .checkBox > .task > .title,
+.ai_body_select > .checkBox > .part > .title {
+  font-size: 14px;
+  font-weight: 700;
+  margin-bottom: 5px;
+}
+
+.ai_body_select > .checkBox > .task {
+  height: calc(100% - 60px);
+}
+
+.ai_body_select > .checkBox > .part {
+}
+
+.ai_body_select > .checkBox > .task > .content {
+  height: calc(100% - 40px);
+  overflow: auto;
+}
+
+.ai_body_select > .checkBox > .task > .content > .span + .span {
+  margin-top: 5px;
+}
+
+.ai_body_select > .checkBox > .task > .content > .span {
+  display: flex;
+  align-items: center;
+  font-size: 14px;
+  cursor: pointer;
+}
+
+.ai_body_select > .checkBox > .task > .content > .span > .check {
+  width: 13px;
+  height: 13px;
+  display: flex;
+  align-items: center;
+  margin-right: 5px;
+}
+
+.ai_body_select > .checkBox > .task > .content > .span > .check > img {
+  width: 100%;
+  height: 100%;
+}
+
+.ai_body_select > .checkBox > .part > .content {
+  display: flex;
+  align-items: center;
+  font-size: 14px;
+  justify-content: space-between;
+}
+
+.ai_body_select > .checkBox > .part > .content > .span {
+  padding: 3px 6px;
+  border: 1px solid #e0eafb;
+  border-radius: 40px;
+  cursor: pointer;
+}
+
+.ai_body_select > .checkBox > .part > .content > .span.active {
+  color: #0061ff;
+  border-color: #0061ff;
+}
+</style>

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor