evaList.vue 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  1. <template>
  2. <div style="position: relative;" v-loading="loading" :style="{ minHeight: loading ? '250px' : 'auto' }"
  3. element-loading-text="小可正在努力生成中,请稍等...">
  4. <div class="c_pub_button_confirm stopBtn" v-if="loading" @click="cancelAjax('elist')">停止</div>
  5. <div class="elist_title">
  6. <div style=" display: flex; flex-direction: row;align-items: center; margin: 20px 0; ">
  7. <div class="lineTitle clineTitle">评价设置</div>
  8. <div style="margin-left:auto;display: flex;">
  9. <div class="r_pub_button_op" style="margin-left:10px;" @click="openAiDialog('elist')">{{ (eList &&
  10. eList.length) ? '重新生成评价' : '生成评价' }}</div>
  11. <div v-if="eList && eList.length" class="show_taskD" :class="{ show: interPan }" @click="toggleInterPan">
  12. <img src="../../../assets/icon/new/u_up.png" />
  13. {{ interPan ? '收起' : '展开' }}
  14. </div>
  15. </div>
  16. </div>
  17. </div>
  18. <div class="mbCss" v-show="interPan">
  19. <div class="pjCss">
  20. <div v-if="eList && eList.length" class="elist_input">
  21. <div v-for="(eItem, eIndex) in eList" :key="eIndex" class="elist_input_box">
  22. <div class="elist_inptu_text">
  23. <span>素养:</span>
  24. <input type="input" v-model="eItem.target" placeholder="填写目标"
  25. style="width: calc(100% - 280px);" />
  26. <el-switch @change="forceUpdate" class="rateSwitch" style="margin-left: auto;"
  27. v-model="eItem.isai" active-color="#0061FF" active-text="AI评分" inactive-text=""
  28. active-value="1" inactive-value="2">
  29. </el-switch>
  30. </div>
  31. <div class="elist_inptu_text">
  32. <span>评价标准:</span>
  33. <input type="input" v-model="eItem.detail" placeholder="填写评价标准" />
  34. <div class="remove" @click="
  35. deletEList(
  36. eIndex
  37. )
  38. "></div>
  39. </div>
  40. <div class="elist_inptu_text" style="align-items: flex-start;">
  41. <span>评价细则:</span>
  42. <div style="width: calc(100%);">
  43. <div @click="openRule(eIndex)" class="ruleBtn">{{ eItem.isrule ? '收起细则' : '展开细则' }}
  44. </div>
  45. <div style="width: calc(100%);" class='op_task_box' v-if="eItem.isrule" v-loading="ruleLoading.length && ruleLoading[eIndex]" element-loading-text='小可正在努力生成中,请稍等...'>
  46. <div class="c_pub_button_confirm stopBtn" v-if="ruleLoading.length && ruleLoading[eIndex]" @click="cancelAjax('rule', eIndex)">停止</div>
  47. <textarea v-autoHeight="68" rows="2" class="binfo_input binfo_textarea" cols
  48. v-model="eItem.rule" placeholder="请输入评价细则"></textarea>
  49. <div class="op_box">
  50. <div class="op_remark"></div>
  51. <div style="display: flex;">
  52. <div class="r_pub_button_op" @click="openAiDialog('rule', eIndex)">{{ eList[eIndex].rule ? '重新生成' : '生成细则'}}</div>
  53. </div>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. </div>
  59. </div>
  60. <!-- <div class="eva_btn_box">
  61. <div class="eva_btn_left_box">
  62. <button class="c_pub_button_add pub_btn_eval_img" @click="addEList()">
  63. 添加
  64. </button>
  65. </div>
  66. </div> -->
  67. </div>
  68. </div>
  69. </div>
  70. </template>
  71. <script>
  72. import { v4 as uuidv4 } from "uuid";
  73. var OpenCC = require("opencc-js");
  74. let converter2 = OpenCC.Converter({
  75. from: 'cn',
  76. to: 'hk'
  77. })
  78. export default {
  79. props: {
  80. toolsData: {
  81. type: Object,
  82. default: () => ({})
  83. },
  84. languageSetting: {
  85. type: Number,
  86. default: 0
  87. },
  88. userid: {
  89. type: String,
  90. default: ""
  91. },
  92. knowFileids: {
  93. type: Array,
  94. default: () => []
  95. },
  96. unitJson: {
  97. type: Array,
  98. default: () => []
  99. },
  100. itemTaskIndex: {
  101. type: Number,
  102. required: true
  103. },
  104. toolIndex: {
  105. type: Number,
  106. required: true
  107. },
  108. aiJson: {
  109. type: Object,
  110. default: () => { }
  111. }
  112. },
  113. data() {
  114. return {
  115. eList: [],
  116. isEvaFold: true,
  117. loading: false,
  118. cancelToken: null,
  119. ruleLoading: [],
  120. cancelRuleToken: [],
  121. interPan: true
  122. }
  123. },
  124. watch: {
  125. eList: {
  126. handler(newVal) {
  127. if (newVal.length > 0) {
  128. this.$emit('setEvaList', this.itemTaskIndex, this.toolIndex, newVal)
  129. }
  130. },
  131. immediate: true,
  132. deep: true
  133. },
  134. // unitJson: {
  135. // handler(newVal) {
  136. // debugger
  137. // let elist = this.unitJson[0].chapterInfo[0].taskJson[this.itemTaskIndex].toolChoose[this.toolIndex].eList
  138. // this.eList = elist ? JSON.parse(JSON.stringify(elist)) : []
  139. // },
  140. // immediate: true,
  141. // deep: true
  142. // }
  143. },
  144. directives: {
  145. autoHeight: {
  146. update(el, binding) {
  147. const { value } = binding;
  148. if (value && typeof value === "number") {
  149. el.style.height = `${value}px`;
  150. } else {
  151. el.style.height = "auto";
  152. }
  153. },
  154. componentUpdated(el) {
  155. el.style.height = `${el.scrollHeight + 25}px`;
  156. },
  157. },
  158. },
  159. methods: {
  160. toggleInterPan() {
  161. this.interPan = !this.interPan;
  162. this.forceUpdate();
  163. },
  164. cancelAjax(type, index) {
  165. if(type == 'elist'){
  166. this.$message.success("已经成功停止生成评价设置")
  167. if (this.cancelToken) {
  168. this.cancelToken.cancel('Request canceled by the user.');
  169. this.cancelToken = null;
  170. }
  171. if (this.loading) {
  172. this.loading = false
  173. }
  174. this.$forceUpdate()
  175. }else if(type == 'rule'){
  176. this.$message.success("已经成功停止生成评价细则")
  177. if (this.cancelRuleToken && this.cancelRuleToken[index]) {
  178. this.cancelRuleToken[index].cancel('Request canceled by the user.');
  179. this.cancelRuleToken[index] = null;
  180. }
  181. if (this.ruleLoading[index]) {
  182. this.ruleLoading[index] = false
  183. }
  184. this.$forceUpdate()
  185. }
  186. },
  187. forceUpdate() {
  188. this.$forceUpdate();
  189. },
  190. getLang() {
  191. let lang = ''
  192. if (this.languageSetting == 0) {
  193. lang = 'Chinese.'
  194. } else if (this.languageSetting == 1) {
  195. lang = 'Traditional Chinese.'
  196. } else if (this.languageSetting == 2) {
  197. lang = 'English.'
  198. }
  199. return lang
  200. },
  201. openAiDialog(type, index) {
  202. if(this.loading){
  203. this.$message.error(`生成中,请等待生成完毕后再继续`)
  204. return
  205. }
  206. if (type == 'elist') {
  207. this.aiElist();
  208. if(type == 1){
  209. this.$emit('addCourseBehavior','courseBehavior', `右键学历案-任务${this.itemTaskIndex + 1}-工具${this.toolIndex + 1}-评价设置-${(this.eList && this.eList.length) ? '重新生成评价' : '生成评价'}按钮`)
  210. }else{
  211. this.$emit('addCourseBehavior','courseBehavior', `右键学历案-任务${this.itemTaskIndex + 1}-任务${this.toolIndex + 1}-评价设置-${(this.eList && this.eList.length) ? '重新生成评价' : '生成评价'}按钮`)
  212. }
  213. this.$emit('')
  214. } else if (type == 'rule') {
  215. this.aiRule(index);
  216. this.$emit('addCourseBehavior','courseBehavior', `右键学历案-任务${this.itemTaskIndex + 1}-任务${this.toolIndex + 1}-评价设置-评价${index + 1}-重新生成细则按钮`)
  217. }
  218. },
  219. aiElist() {
  220. let _this = this
  221. if(!_this.knowFileids.length){
  222. _this.$message.error(`请上传参考标准后,再生成评价`)
  223. return
  224. }
  225. _this.loading = true
  226. let fileid = _this.knowFileids.length ? [..._this.knowFileids] : []
  227. let taskDetail = _this.unitJson[0].chapterInfo[0].taskJson[_this.itemTaskIndex].taskDetail ? _this.unitJson[0].chapterInfo[0].taskJson[_this.itemTaskIndex].taskDetail.replaceAll('\n', ' ') : ''
  228. let tool = _this.toolsData[_this.unitJson[0].chapterInfo[0].taskJson[_this.itemTaskIndex].toolChoose[_this.toolIndex].tool[0]].name
  229. let toolDetail = _this.unitJson[0].chapterInfo[0].taskJson[_this.itemTaskIndex].toolChoose[_this.toolIndex].toolDetail.replaceAll('\n', ' ')
  230. let messages = `
  231. Language: ${this.getLang()}
  232. #上下文#
  233. 你是一个资深的教师,你有丰富的项目式学习、跨学科学习、STEAM导师经验。
  234. <任务描述><工具名称>和<工具描述>是你的参考资料。任务描述中包含了多个学生活动,可能会用到多个工具。工具描述会告诉你学生要用这个工具完成怎样的作业。以下是可能出现的工具以及对应的功能。
  235. 【文档】用于记笔记、写作文、设计实验或者撰写报告等文本类作业。
  236. 【表格】用于记录数据、整理信息等
  237. 【思维导图】用于科学探究的问题分析、头脑风暴等。把各个部分主次关系能直白的展示出来,能够帮助学习和记忆。
  238. 【电子白板】用于个性化表达、自主设计类创意活动,系统支持概念图库,主要用于绘制概念图、梳理关键词/事件/问题之间的关系;或支持学生自由绘制一些方案设计图。
  239. 【作业提交】支持各类文件格式的上传与显示,如png等图片格式、pptx、docx、txt、md等。
  240. 【选择题】用于教师检查学生对知识的掌握和理解,参考指标为题目的正确率。
  241. 【排序】通过设置卡片内容及正确顺序,用于教师使用排序类题目检查学生对知识的掌握和理解,参考指标为题目的正确率。
  242. 【选择匹配】通过上传题目图片与设置正确回答,用于教师使用选择匹配(连线)检查学生对知识的掌握和理解,参考指标为题目的正确率。
  243. 选择题、排序、选择匹配工具是客观题,学生答题后会产生正确率。
  244. 上传的文件中包含了若干个学科的国家课程标准。你要学习文件中特定章节的内容:高中(高一至高三)课程标准中的“学科核心素养与课程目标”章节,义务教育阶段(一年级至九年级)课程标准中的“课程目标”章节。这些章节详细阐述了该学科的“核心素养”和“目标”。“学科核心素养”指学生应具备的,能够适应终身发展和社会发展需要的必备品格和关键能力。“目标”指课程本身要实现的具体目标和意图。它规定了某一教育阶段的学生通过课程学习以后,在发展品德、智力、体质等方面期望实现的程度,它是确定课程内容、教学目标和教学方法的基础。注意:每个学科的“核心素养”有专业用词,一般会作为文件中的小标题出现,不能随意编写,不能随意生成。举例:义务教育阶段语文学科的核心素养为“文化自信”“语言运用”“思维能力”“审美创造”;义务教育阶段数学学科的核心素养为“会用数学的眼光观察现实世界”“会用数学的思维思考现实世界”“会用数学的语言表达现实世界”。
  245. 当选择多个学科时,上传的文件中会有《跨学科素养(参考)》,跨学科素养能力指具有跨文化一致性的、能够跨越一系列情境长期存在和发挥作用的、个体用于应对和解决日常工作和生活中遇到的各种复杂挑战和需求的能力。例如“合作能力”“认知能力”“创新能力”等。
  246. 你要理解学科核心素养和学科目标之间的关系。你生成的评价标准可以被当作课程目标,评价标准要与学科的核心素养或者跨学科素养匹配。
  247. #目标#
  248. 你需要完成以下六个步骤:
  249. 1.检索并学习上传文件的指定章节(高中(高一至高三)课程标准中的“学科核心素养与课程目标”章节,义务教育阶段(一年级至九年级)课程标准中的“课程目标”章节,《跨学科素养(参考)》文件),提取学科的核心素养并学习学科目标。
  250. 2.你要参考第一步学习的学科目标,结合<任务描述:${taskDetail}><工具名称:${tool}>和<工具描述:${toolDetail}>生成适合当前作业的评价标准。评价标准用于评估学生的能力。
  251. 3.你要精准地将评价标准匹配上传文件的核心素养和课程目标内容。第二步的评价标准是根据课程目标生成的,你要将这些评价标准与第一步提取的学科核心素养一一匹配。注意:所有的核心素养信息必须以上传文件的内容为依据,不可以使用其他的默认信息或者模版!避免使用上传文件中未出现的素养。
  252. 4.只有当上传的文件包含《跨学科素养(参考)》时,执行该步骤。如果生成的评价标准难以与具体某个学科(如“语文”“英语”“劳动”)的国家课程标准匹配时,你可以将评价标准匹配该文件中提到的跨学科素养,如“合作能力”“认知能力”“创新能力”等。
  253. 5.你要根据第一步生成的评价标准制定每一条标准的六级评价细则,这个评价细则将用于对学生能力的打分。
  254. 6.你要将第2步到第5步生成的内容整理成json格式,参考json格式范例。
  255. #风格#
  256. 专业的教育教学用语,简练易懂,逻辑性强。
  257. #语气#
  258. 陈述
  259. #受众#
  260. 教师
  261. #输出要求#
  262. 1.评价标准的个数为3个。每一个评价标准不能超过30字。生成的评价标准要适用于当前工具,要适合教师用线上平台对学生作业进行评估打分。输出内容和格式要求参考#评价标准范例#。注意!输出内容不能复制范例内容。注意!不要出现#评价标准错误范例#中的情况。
  263. 2.选择题、排序、选择匹配等客观题工具只生成1个评价标准,评价细则要说明学生答题正确率分别对应哪个等级。
  264. 3.每1个评价标准只对应1个关联度最高的核心素养。学科核心素养输出参考#核心素养输出范例#。注意!1个评价标准不能对应多个核心素养。不允许出现上传文件中没有的核心素养。严格按照上传文件中检索到的核心素养输出。每个评价标准必须与文件中明确的核心素养对应。避免使用文件中未出现的任何术语。不要出现#核心素养错误范例#中的情况。
  265. 4.具体的评价细则分为6级——0星,1星,2星,3星,4星,5星。输出格式参考#评价细则范例#。
  266. 5.参考#json格式范例#,将内容整理成json格式。**之间的内容为json格式中的代码。以*[*开头,以*]*结尾。每一条评价标准、核心素养以及评价细则以*{*开头,以*}*结尾。核心素养前有*"core":*。评价标准前有*"std":*。评价细则前有*"rule":*。具体内容放在""之间。格式如下:
  267. [
  268. {"std":"评价标准","core":"核心素养(识别上传文件对应的学科)","rule":"评价细则"},
  269. {"std":"评价标准","core":"核心素养(识别上传文件对应的学科)","rule":"评价细则"},
  270. {"std":"评价标准","core":"核心素养(识别上传文件对应的学科)","rule":"评价细则"},
  271. ]
  272. 5.只输出json格式的内容,其他的不要输出!
  273. #评价标准范例#
  274. 学生能够准确描述红树林生态功能及动植物之间的关系。
  275. 学生的调查报告完整详细,说明文逻辑清晰。
  276. 艺术作品反映了对红树林生态系统的创新理解。
  277. #评价标准错误范例#
  278. 错误范例1:工具描述是“在完成动植物调查后,同学们需要使用文档工具撰写调查报告,详细描述调查过程和结果”,输出“艺术作品反映了对红树林生态系统的创新理解”。原因是:文档工具不能支持学生完成艺术作品。
  279. 错误范例2:工具描述是“在实地考察或虚拟模拟中,同学们需要使用表格工具记录观察到的红树林生态功能和动植物信息”,输出“学生能够通过数据分析解释生态系统变化”。原因是:表格工具不能支持学生完成报告的撰写,所以不能学生通过表格工具解释变化。
  280. #评价细则范例#
  281. 0 星,作业内容与作业要求无关;
  282. 1 星,没有识别问题和需求;
  283. 2 星,问题或需求没有被清晰理解或准确识别;
  284. 3 星,问题或需求的一部分被识别;
  285. 4 星,问题或需求的大部分被识别;
  286. 5 星,问题或需求都被识别。
  287. #核心素养错误范例#
  288. 错误范例1:评价标准是“学生能够展示诗歌与美术作品的创作主题和过程”。输出“审美创造(艺术)”是错误的,因为艺术学科的核心素养中没有“审美创造”。
  289. 错误范例2:评价标准是“学生能通过文档工具记录并总结对诗词的人文感悟。”。输出“表达与交流(语文)”是错误的,因为艺术学科的核心素养中没有“表达与交流”。
  290. #核心素养输出范例#
  291. 评价标准:学生应该能准确指出光合作用发生的具体部位(叶绿体),并解释叶绿体在光合作用中的重要性。
  292. 这一条标准对应了《义务教育科学课程标准(2022年版)》中“科学观念”这一条核心素养,识别上传文件对应的学科为“科学”。所以输出内容为:科学观念(科学)。
  293. 评价标准:学生能够通过文档工具清晰表达小学生活的回忆与未来期望。
  294. 这一条标准对应了《义务教育艺术课程标准(2022年版)》中“艺术表现”这一条核心素养,识别上传文件对应的学科为“艺术”。所以输出内容为:艺术表现(艺术)。
  295. 评价标准:学生能够在小组讨论中积极表达观点。
  296. 这一条标准对应了《跨学科素养参考资料》中“合作能力”这一条核心素养,识别上传文件对应的学科为“跨学科”。所以输出内容为:合作能力(跨学科)。
  297. #json格式范例#
  298. [
  299. {"std":"学生应该能清晰地解释光合作用的定义,包括植物利用光能将二氧化碳和水转化为葡萄糖和氧气的过程。","core":"科学观念(科学)","rule":"0星,未能解释光合作用的定义,与主题无关。
  300. 1星,尝试解释光合作用但描述与实际过程不符。
  301. 2星,能够识别光合作用的要素之一,如光能、二氧化碳、水、葡萄糖或氧气,但未形成完整的定义。
  302. 3星,能够部分描述光合作用的过程,例如知道植物利用光能进行转化,但未全面涵盖所有成分。
  303. 4星,能够完整描述光合作用的过程,但细节或某些元素略显不足。
  304. 5星,清晰完整地解释了光合作用的定义,包括如何利用光能将二氧化碳和水转化为葡萄糖和氧气的详细过程。
  305. "},
  306. {"std":"学生应该能正确写出光合作用的化学反应式:6CO2 + 6H2O + 光能 → C6H12O6 + 6O2,并理解每个成分的作用。","core":"科学观念(科学)","rule":"0星:未能写出任何相关的内容,完全没有涉及光合作用的化学反应式。
  307. 1星:光合作用的化学反应式错误,完全没有正确的化学分子式。
  308. 2星:能够部分写出光合作用的化学反应式,但分子式及其配比有较多错误,未能体现光能的作用。
  309. 3星:基本写出大部分的光合作用化学反应式,但有小部分错误,对于光能的作用未能准确阐述。
  310. 4星:能较完整写出光合作用的化学反应式,整体正确,但对每个成分的具体作用理解不够深入。
  311. 5星:准确无误地写出光合作用的化学反应式,并能清晰、详细地解释每个成分的作用及其在反应中的重要性。
  312. "},
  313. {"std":"学生能够通过文档工具清晰表达小学生活的回忆与未来期望。","core":"艺术表现(艺术)","rule":"
  314. 0星,未能使用文档工具表达任何想法。
  315. 1星,尝试使用文档工具但表达不清晰。
  316. 2星,能够部分表达小学生活的回忆或未来期望。
  317. 3星,能够表达小学生活的回忆或未来期望,但不够完整。
  318. 4星,能够完整表达小学生活的回忆与未来期望,但细节略显不足。
  319. 5星,清晰完整地表达了小学生活的回忆与未来期望,细节丰富。
  320. "},
  321. ]`
  322. _this.loading = true
  323. _this.cancelToken = _this.ajax.setCancelSource();
  324. let params = {
  325. assistant_id: '6063369f-289a-11ef-8bf4-12e77c4cb76b',
  326. message: [{ "type": "text", "text": this.languageSetting == 1 ? converter2(messages.replaceAll('\n', " ").replaceAll('*', "")) : messages.replaceAll('\n', " ").replaceAll('*', "") }],
  327. session_name: uuidv4(),
  328. userId: _this.userid,
  329. file_ids: fileid.length ? [...fileid] : '',
  330. model: 'gpt-4o-2024-08-06',
  331. temperature: 0.1,
  332. }
  333. _this.ajax.post('https://gpt4.cocorobo.cn/ai_agent_park_chat', params, _this.cancelToken).then(function (response) {
  334. console.log(response);
  335. let data = response.data.FunctionResponse
  336. if (data.message) {
  337. console.log(data.message);
  338. let elist = []
  339. try {
  340. elist = JSON.parse(data.message.replaceAll("```json", "").replaceAll("```", ""))
  341. elist = elist.map(el => {
  342. return {
  343. isai: "1",
  344. target: el.core,
  345. value: "",
  346. detail: el.std,
  347. rule: el.rule.replace(/([;。])/g, '$1\n')
  348. }
  349. })
  350. } catch (e) {
  351. console.log("error_________________" + e);
  352. try {
  353. let regex = new RegExp(/```json([\s\S]*?)```/);
  354. let match = data.message.match(regex);
  355. elist = JSON.parse(match[1])
  356. elist = elist.map(el => {
  357. return {
  358. isai: "1",
  359. target: el.core,
  360. value: "",
  361. detail: el.std,
  362. rule: el.rule.replace(/([;。])/g, '$1\n')
  363. }
  364. })
  365. } catch (error) {
  366. }
  367. }
  368. console.log(elist);
  369. _this.eList = elist
  370. _this.$forceUpdate()
  371. }
  372. _this.cancelToken = null
  373. _this.loading = false
  374. }).catch(function (error) {
  375. _this.cancelToken = null
  376. _this.loading = false
  377. console.log(error);
  378. });
  379. },
  380. aiRule(index) {
  381. if(!this.knowFileids.length){
  382. this.$message.error(`请上传参考标准后,再生成评价`)
  383. return
  384. }
  385. if (!this.eList[index].target || !this.eList[index].detail) {
  386. this.$message.error(`评价信息完善信息后再生成细则`)
  387. return;
  388. }
  389. this.ruleLoading[index] = true
  390. this.$forceUpdate();
  391. let message = `NOTICE
  392. Role: 你是一个专业的项目式学习导师
  393. Language: ${this.getLang()}
  394. ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
  395. Instruction: Based on the context, follow "Format example", write content.
  396. #Context
  397. ##要求
  398. ${this.aiJson['aiRateRule']}
  399. <评价标准:${this.eList[index].detail}>
  400. <素养:${this.eList[index].target}>
  401. 参考#Format example#,将内容整理成字符串格式。。以*====*开头,以*====*结尾。格式如下:
  402. ====
  403. 0 星,作业内容与作业要求无关;
  404. 1 星,没有识别问题和需求;
  405. 2 星,问题或需求没有被清晰理解或准确识别;
  406. 3 星,问题或需求的一部分被识别;
  407. 4 星,问题或需求的大部分被识别;
  408. 5 星,问题或需求都被识别。
  409. ====
  410. # Format example
  411. ====
  412. 0 星,作业内容与作业要求无关;
  413. 1 星,没有识别问题和需求;
  414. 2 星,问题或需求没有被清晰理解或准确识别;
  415. 3 星,问题或需求的一部分被识别;
  416. 4 星,问题或需求的大部分被识别;
  417. 5 星,问题或需求都被识别。
  418. ==== `
  419. this.cancelRuleToken[index] = this.ajax.setCancelSource();
  420. let parm = {
  421. assistant_id: 'b19f1a1a-7586-11ef-8ce0-12e77c4cb76b',
  422. message: [{ "type": "text", "text": this.languageSetting == 1 ? converter2(message.replaceAll('\n', " ").replaceAll('*', "")) : message.replaceAll('\n', " ").replaceAll('*', "") }],
  423. session_name: uuidv4(),
  424. userId: this.userid,
  425. file_ids: [...this.knowFileids],
  426. model: 'gpt-4o-2024-08-06',
  427. temperature: this.mode == 3 ? 0.5 : 0.1,
  428. }
  429. this.ajax
  430. .post("https://gpt4.cocorobo.cn/ai_agent_park_chat", parm, this.cancelRuleToken[index])
  431. .then(async (response) => {
  432. console.log(response);
  433. let data = response.data.FunctionResponse
  434. if (data.message) {
  435. console.log(data.message);
  436. let content = data.message;
  437. var regex = new RegExp('====([^=]+)====');
  438. let match = content.match(regex);
  439. if (match) {
  440. content = match[1].trim().replaceAll(' ', '');
  441. // 获取匹配到的内容并去除两端空格
  442. console.log('contentInsideDoubleEquals', content);
  443. if (content.indexOf('0星') == -1 || content.indexOf('2星') == -1 || content.indexOf('3星') == -1 || content.indexOf('4星') == -1 || content.indexOf('5星') == -1) {
  444. console.log("未有星级。");
  445. this.cancelRuleToken[index] = null
  446. this.aiRule(index)
  447. return
  448. }
  449. //  return
  450. } else {
  451. console.log("未找到匹配的内容。");
  452. this.cancelRuleToken[index] = null
  453. this.aiRule(index)
  454. return
  455. }
  456. let elist = JSON.parse(JSON.stringify(this.eList[index]))
  457. elist.rule = JSON.parse(JSON.stringify(content.replaceAll("#", "")))
  458. this.$set(this.eList, index, elist)
  459. this.$forceUpdate();
  460. this.ruleLoading[index] = false
  461. this.cancelRuleToken[index] = null
  462. this.$message.success(`评价细则生成成功`)
  463. } else {
  464. this.ruleLoading[index] = false
  465. this.cancelRuleToken[index] = null
  466. }
  467. this.$forceUpdate();
  468. })
  469. .catch((error) => {
  470. this.cancelRuleToken[index] = null
  471. this.ruleLoading[index] = false
  472. this.$forceUpdate();
  473. console.log(error);
  474. });
  475. },
  476. addEList() {
  477. },
  478. deletEList(index) {
  479. this.$confirm('确定删除吗?').then(() => {
  480. this.eList.splice(index, 1)
  481. if (!this.eList.length) {
  482. this.$emit('setEvaList', this.itemTaskIndex, this.toolIndex, this.eList)
  483. }
  484. })
  485. },
  486. openRule(i) {
  487. if (this.eList[i].isrule) {
  488. this.eList[i].isrule = false
  489. } else {
  490. this.eList[i].isrule = true
  491. }
  492. setTimeout(() => {
  493. this.eList[i].rule += "*0*%*";
  494. setTimeout(() => {
  495. this.eList[i].rule = this.eList[i].rule.replaceAll("*0*%*", "");
  496. }, 0);
  497. }, 100);
  498. this.$forceUpdate();
  499. },
  500. },
  501. mounted() {
  502. let elist = this.unitJson[0].chapterInfo[0].taskJson[this.itemTaskIndex].toolChoose[this.toolIndex].eList
  503. this.eList = elist ? JSON.parse(JSON.stringify(elist)) : []
  504. for (let i = 0; i < this.eList.length; i++) {
  505. setTimeout(() => {
  506. this.eList[i].rule += "*0*%*";
  507. setTimeout(() => {
  508. this.eList[i].rule = this.eList[i].rule.replaceAll("*0*%*", "");
  509. }, 0);
  510. }, 500);
  511. }
  512. }
  513. }
  514. </script>
  515. <style scoped>
  516. /* 评价样式 */
  517. .elist_css {
  518. padding-bottom: 75px !important;
  519. }
  520. .elist_title {
  521. margin-bottom: 10px;
  522. }
  523. .elist_input {
  524. width: 100%;
  525. }
  526. .elist_input_box {
  527. display: flex;
  528. align-items: center;
  529. flex-wrap: wrap;
  530. }
  531. .elist_input_box+.elist_input_box {
  532. margin-top: 30px;
  533. }
  534. .elist_input .elist_input_box input {
  535. font: inherit;
  536. color: currentColor;
  537. width: 100%;
  538. /* max-width: calc(100% - 385px); */
  539. max-width: calc(100% - 150px);
  540. padding: 8px 14px;
  541. display: block;
  542. min-width: 0;
  543. outline: none;
  544. border: 1px solid rgba(0, 0, 0, 0.23);
  545. border-radius: 4px;
  546. box-sizing: border-box;
  547. background: #fff;
  548. margin: 0 20px 0 0;
  549. }
  550. .elist_input .elist_input_box span {
  551. height: 36px;
  552. line-height: 36px;
  553. color: rgb(82, 82, 82);
  554. min-width: 80px;
  555. }
  556. .remove {
  557. background-image: url("../../../assets/icon/new/delete_u.png");
  558. cursor: pointer;
  559. opacity: 0.5;
  560. width: 30px;
  561. min-width: 30px;
  562. height: 30px;
  563. background-size: 100% 100%;
  564. background-repeat: no-repeat;
  565. margin-left: 10px;
  566. }
  567. .elist_input .elist_input_box .remove {
  568. height: 20px;
  569. width: 20px;
  570. min-height: 20px;
  571. min-width: 20px;
  572. background-size: 100% 100%;
  573. background-position: unset;
  574. margin-left: 5px;
  575. }
  576. .elist_input_box>>>.el-rate {
  577. display: flex;
  578. height: 36px;
  579. align-items: center;
  580. }
  581. .elist_input_box .elist_inptu_text {
  582. width: 100%;
  583. display: flex;
  584. align-items: center;
  585. margin-top: 10px;
  586. }
  587. .elist_input_box .elist_inptu_text input {
  588. /* width: 500px; */
  589. width: 100%;
  590. max-width: unset;
  591. }
  592. .elist_input_box>>>.el-rate__icon {
  593. font-size: 24px;
  594. }
  595. .elist_btn {
  596. margin-top: 10px;
  597. }
  598. .lineTitle {
  599. /* margin-top: 15px; */
  600. width: 110px;
  601. font-size: 16px;
  602. display: flex;
  603. align-items: center;
  604. line-height: 20px;
  605. }
  606. .lineTitle::before {
  607. content: "";
  608. display: block;
  609. width: 3px;
  610. height: 20px;
  611. background: #0061ff;
  612. border-radius: 3px;
  613. margin: 0 5px 0 0;
  614. }
  615. .clineTitle::before {
  616. content: "";
  617. display: block;
  618. min-width: 10px;
  619. width: 10px;
  620. height: 10px;
  621. background: #0061ff;
  622. border-radius: 50%;
  623. margin: 0 5px 0 0;
  624. }
  625. .courseTop {
  626. display: flex;
  627. flex-direction: row;
  628. justify-content: space-between;
  629. align-items: center;
  630. width: calc(100% - 40px);
  631. margin: 0 auto;
  632. padding: 10px 0;
  633. }
  634. .stepsNav {
  635. display: flex;
  636. flex-direction: row;
  637. justify-content: flex-start;
  638. align-items: center;
  639. }
  640. .stepsWord {
  641. font-size: 18px;
  642. color: #fff;
  643. font-weight: bold;
  644. margin-left: auto;
  645. background: rgb(15, 126, 255);
  646. border-radius: 5px;
  647. padding: 3px 25px;
  648. box-sizing: border-box;
  649. }
  650. .stepBox {
  651. width: calc(100% - 40px);
  652. height: calc(100% - 50px);
  653. overflow: hidden;
  654. border-radius: 5px;
  655. margin: 0 auto;
  656. }
  657. .rightBox {
  658. width: calc(100%);
  659. background: #f0f2f5;
  660. /* border-radius: 10px; */
  661. overflow: auto;
  662. height: calc(100% - 150px);
  663. margin: 0 auto;
  664. position: relative;
  665. box-sizing: border-box;
  666. }
  667. .e_add_top {
  668. display: flex;
  669. justify-content: space-between;
  670. background: #fff;
  671. position: absolute;
  672. right: 20px;
  673. height: 50px;
  674. align-items: center;
  675. }
  676. .e_add_title2 {
  677. display: flex;
  678. align-items: center;
  679. }
  680. .e_add_title2 span {
  681. width: 40px;
  682. }
  683. .e_add_title {
  684. display: flex;
  685. align-items: center;
  686. color: #b8b8b8;
  687. font-size: 18px;
  688. position: relative;
  689. height: 40px;
  690. }
  691. .e_add_title span {
  692. margin-right: 10px;
  693. }
  694. .e_add_title .el_input {
  695. width: 300px;
  696. }
  697. .e_add_title>>>.el-input__inner {
  698. width: 400px;
  699. }
  700. .e_add_btn {}
  701. .e_add_content {
  702. display: flex;
  703. width: 100%;
  704. }
  705. .e_add_list {
  706. background: #fff;
  707. height: 500px;
  708. width: 210px;
  709. position: relative;
  710. margin: 15px 5px 0 0;
  711. flex-shrink: 0;
  712. display: flex;
  713. flex-direction: column;
  714. }
  715. .e_add_list_title {
  716. font-size: 20px;
  717. width: 100%;
  718. box-sizing: border-box;
  719. padding: 15px 40px;
  720. text-align: center;
  721. border-bottom: 1px solid #eaeaea;
  722. position: relative;
  723. display: flex;
  724. align-items: center;
  725. justify-content: center;
  726. height: 57px;
  727. background: #f6f6f6;
  728. }
  729. .e_add_list_title span {
  730. overflow: hidden;
  731. white-space: nowrap;
  732. text-overflow: ellipsis;
  733. }
  734. .e_add_list_title img {
  735. position: absolute;
  736. right: 15px;
  737. width: 25px;
  738. cursor: pointer;
  739. top: 50%;
  740. transform: translateY(-50%);
  741. }
  742. .e_add_list_body {
  743. height: calc(100% - 187px);
  744. overflow: auto;
  745. }
  746. .e_add_list_child {
  747. width: 100%;
  748. display: flex;
  749. align-items: center;
  750. justify-content: center;
  751. position: relative;
  752. box-sizing: border-box;
  753. padding: 15px 40px;
  754. text-align: center;
  755. }
  756. .e_add_list_child span {
  757. overflow: hidden;
  758. white-space: nowrap;
  759. text-overflow: ellipsis;
  760. cursor: pointer;
  761. }
  762. .e_add_list_child img {
  763. position: absolute;
  764. right: 10px;
  765. width: 21px;
  766. cursor: pointer;
  767. top: 50%;
  768. transform: translateY(-50%);
  769. }
  770. .e_add_list_child+.e_add_list_child {
  771. border-top: 1px solid #eaeaea;
  772. }
  773. .e_add_list_child .active {
  774. color: #409eff;
  775. }
  776. .e_add_list_btn {
  777. position: absolute;
  778. bottom: 0;
  779. height: 50px;
  780. background: rgb(120, 120, 254);
  781. width: 100%;
  782. color: #fff;
  783. font-size: 16px;
  784. text-align: center;
  785. line-height: 50px;
  786. cursor: pointer;
  787. }
  788. .e_add_list_detail {
  789. position: absolute;
  790. bottom: 0;
  791. height: 130px;
  792. background: rgb(120, 120, 254);
  793. width: 100%;
  794. color: #fff;
  795. font-size: 16px;
  796. display: flex;
  797. align-items: center;
  798. justify-content: center;
  799. }
  800. .e_add_list_detail textarea {
  801. height: 90%;
  802. width: 95%;
  803. border: none;
  804. resize: none;
  805. outline: none;
  806. padding: 5px;
  807. box-sizing: border-box;
  808. }
  809. .e_add_list_pbox {
  810. width: 100%;
  811. }
  812. .e_add_list_pbox_title {
  813. height: 50px;
  814. background: #fff;
  815. display: flex;
  816. align-items: center;
  817. width: 100%;
  818. box-sizing: border-box;
  819. padding: 0 20px;
  820. flex-direction: row;
  821. flex-wrap: wrap;
  822. }
  823. .mbCss {
  824. width: 100%;
  825. display: flex;
  826. flex-direction: row;
  827. flex-wrap: nowrap;
  828. align-content: center;
  829. align-items: flex-start;
  830. justify-content: flex-start;
  831. }
  832. .pjCss {
  833. /* width: 42%; */
  834. width: calc(100%);
  835. display: flex;
  836. flex-direction: column;
  837. flex-wrap: nowrap;
  838. align-items: flex-start;
  839. }
  840. .e_box {
  841. /* display: flex; */
  842. flex-wrap: wrap;
  843. max-height: 500px;
  844. align-items: flex-start;
  845. overflow: auto;
  846. width: 100%;
  847. }
  848. .e_card {
  849. border: 1px solid #ccc;
  850. background: #fff;
  851. margin-right: 20px;
  852. width: 270px;
  853. display: flex;
  854. flex-direction: column;
  855. align-items: center;
  856. border-radius: 5px;
  857. margin-top: 10px;
  858. text-align: center;
  859. }
  860. .e_card_picture {
  861. margin: 10px 0;
  862. }
  863. .e_card_picture>img {
  864. width: 50px;
  865. }
  866. .e_card_name {
  867. width: 100%;
  868. padding: 0 10px;
  869. box-sizing: border-box;
  870. margin-bottom: 10px;
  871. overflow: hidden;
  872. text-overflow: ellipsis;
  873. white-space: nowrap;
  874. }
  875. .e_card_time {
  876. width: 100%;
  877. padding: 0 10px;
  878. box-sizing: border-box;
  879. font-size: 15px;
  880. color: #c3c3c3;
  881. margin-bottom: 10px;
  882. }
  883. .e_card_btn {
  884. height: 40px;
  885. display: flex;
  886. align-items: center;
  887. width: 100%;
  888. background: rgb(244, 244, 244);
  889. }
  890. .e_card_btn:hover {
  891. background: rgb(221 221 221);
  892. }
  893. .e_card_btn span {
  894. flex: 1 1 auto;
  895. text-align: center;
  896. cursor: pointer;
  897. }
  898. .addEva {
  899. border: 1px solid #ccc;
  900. background: #fff;
  901. margin-right: 20px;
  902. width: 270px;
  903. height: 149px;
  904. display: flex;
  905. flex-direction: column;
  906. align-items: center;
  907. border-radius: 5px;
  908. margin-top: 10px;
  909. text-align: center;
  910. cursor: pointer;
  911. justify-content: center;
  912. }
  913. .addEva>img {
  914. width: 50px;
  915. object-fit: cover;
  916. }
  917. .ruleBtn {
  918. width: fit-content;
  919. height: 36px;
  920. line-height: 36px;
  921. cursor: pointer;
  922. color: #0061FF;
  923. }
  924. .op_task_box,
  925. .op_tool_box,
  926. .outline_detail {
  927. position: relative;
  928. }
  929. .op_task_box:hover .op_box,
  930. .op_tool_box:hover .op_box,
  931. .outline_detail:hover .op_box {
  932. display: flex
  933. }
  934. .op_box {
  935. position: absolute;
  936. bottom: 10px;
  937. display: none;
  938. align-items: center;
  939. justify-content: space-between;
  940. width: calc(100% - 20px);
  941. left: 50%;
  942. transform: translateX(-50%);
  943. }
  944. .op_box .op_remark {
  945. color: #8E8E8E;
  946. font-size: 14px;
  947. }
  948. .binfo_input {
  949. width: 100%;
  950. margin: 0;
  951. padding: 12px 14px;
  952. display: block;
  953. min-width: 0;
  954. outline: none;
  955. box-sizing: border-box;
  956. background: none;
  957. border: none;
  958. border-radius: 4px;
  959. background: #fff;
  960. font-size: 16px;
  961. resize: none;
  962. font-family: "Microsoft YaHei";
  963. min-height: 48px;
  964. /* border: 1px solid #3682fc00; */
  965. border: 1.5px solid #cad1dc;
  966. }
  967. .binfo_textarea {
  968. border: 1.5px solid #cad1dc;
  969. font-size: 16px;
  970. resize: none;
  971. /* background: #f6f6f6; */
  972. font-family: "Microsoft YaHei";
  973. }
  974. .binfo_input:focus-visible {
  975. border: 1.5px solid #3681fc !important;
  976. }
  977. .rateSwitch>>>.el-switch__label.is-active {
  978. color: #0061FF;
  979. }
  980. .rateSwitch>>>.el-switch__label--right {
  981. display: flex;
  982. align-items: center;
  983. }
  984. .rateSwitch>>>.el-switch__label--right::before {
  985. content: "";
  986. width: 14px;
  987. height: 14px;
  988. min-width: 14px;
  989. min-height: 14px;
  990. background-size: 100% 100%;
  991. display: block;
  992. margin-right: 7px;
  993. background-image: url(../../../assets/icon/new/u_op2.png);
  994. }
  995. .rateSwitch>>>.el-switch__label--right.is-active::before {
  996. background-image: url(../../../assets/icon/new/u_op.png);
  997. }
  998. .stopBtn {
  999. z-index: 999999;
  1000. position: absolute;
  1001. left: 50%;
  1002. top: calc(50% + 70px);
  1003. transform: translateX(-50%);
  1004. }
  1005. .show_taskD {
  1006. min-width: fit-content;
  1007. margin-left: 10px;
  1008. display: flex;
  1009. align-items: center;
  1010. font-size: 14px;
  1011. cursor: pointer;
  1012. color: #0061FF;
  1013. }
  1014. .show_taskD>img {
  1015. width: 15px;
  1016. margin-right: 5px;
  1017. transition: 0.2s all;
  1018. transform: rotate(-90deg);
  1019. }
  1020. .show_taskD.show>img {
  1021. transform: rotate(0deg);
  1022. }
  1023. </style>