markScore.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. <template>
  2. <div>
  3. <div v-loading="loading" style="cursor: pointer;" @click.stop="markScoreDigBtn">
  4. <div class="scoreTit">
  5. <div>任务得分</div>
  6. <div>{{ totalScore ? totalScore : 0 }}分</div>
  7. </div>
  8. <div class="allD">
  9. <div class="scoreStarBack2">
  10. <div
  11. v-for="(e, index) in scoTitList"
  12. :key="index"
  13. style="height: 30px;"
  14. >
  15. <img
  16. class="rootImg"
  17. v-if="e.isai == 1 || !e.isai"
  18. src="../../../assets/icon/newIcons/blueRoot.png"
  19. alt=""
  20. />
  21. </div>
  22. </div>
  23. <div class="scoreStar">
  24. <div v-for="(e, index) in scoTitList" :key="index">
  25. <div class="scoreStarBack">
  26. <el-tooltip
  27. class="item"
  28. effect="dark"
  29. :content="e.detail"
  30. placement="top"
  31. >
  32. <div class="briefTit">
  33. {{ e.detail }}
  34. </div>
  35. </el-tooltip>
  36. <el-rate
  37. disabled
  38. disabled-void-color="#ccc"
  39. v-model="e.cog"
  40. ></el-rate>
  41. </div>
  42. </div>
  43. </div>
  44. </div>
  45. <div class="AreaCss">
  46. {{ textarea }}
  47. <!-- <el-input
  48. type="textarea"
  49. disabled
  50. placeholder="您可在此输入评语"
  51. v-model="textarea"
  52. style="padding-bottom: 10px;"
  53. >
  54. </el-input> -->
  55. </div>
  56. <!-- <div style="width:100%;display:flex;justify-content: flex-end;">
  57. <el-button size="mini" @click="reset">重置</el-button>
  58. <el-button type="primary" size="mini" @click="submit">确认</el-button>
  59. <el-button type="primary" size="mini" @click="AIsubmit"
  60. >AI评分</el-button
  61. >
  62. </div> -->
  63. </div>
  64. </div>
  65. </template>
  66. <script>
  67. import { v4 as uuidv4 } from "uuid";
  68. export default {
  69. name: "PblStudentTableMarkScore",
  70. props: [
  71. "scoTit",
  72. "scoCon",
  73. "task",
  74. "stage",
  75. "loading",
  76. "wIndex",
  77. "toolIndex",
  78. ],
  79. data() {
  80. return {
  81. homeworkVal: [],
  82. scoTitList: [],
  83. markScoPopover: false,
  84. id: this.$route.query.courseId,
  85. stUid: this.scoCon.userid,
  86. userid: this.$route.query.userid,
  87. total: 0
  88. };
  89. },
  90. computed: {
  91. totalScore() {
  92. let a = 0;
  93. let isPing = 0;
  94. this.scoTitList.forEach(e => {
  95. if (e.cog || e.cog == "0") {
  96. a += e.cog * 1;
  97. } else {
  98. isPing += 1;
  99. }
  100. });
  101. let data = 0;
  102. if (isPing == this.scoTit.length) {
  103. this.$emit("updateDocSco", {
  104. val: this.toolIndex,
  105. val2: this.wIndex,
  106. val3: null
  107. });
  108. } else {
  109. data = (a / this.scoTit.length).toFixed(1);
  110. this.$emit("updateDocSco", {
  111. val: this.toolIndex,
  112. val2: this.wIndex,
  113. val3: data
  114. });
  115. }
  116. return data;
  117. }
  118. },
  119. mounted() {
  120. this.scoTitList = JSON.parse(JSON.stringify(this.scoTit));
  121. this.getData();
  122. },
  123. methods: {
  124. // // 获取文档id
  125. createFileid(url) {
  126. let _this = this;
  127. return new Promise((resolve, reject) => {
  128. try {
  129. _this.ajax
  130. .put("https://gpt4.cocorobo.cn/upload_file_knowledge", {
  131. url: url
  132. })
  133. .then(res => {
  134. let _data = res.data.FunctionResponse;
  135. if (_data.result && _data.result.id) {
  136. resolve(_data.result.id);
  137. } else {
  138. resolve(1);
  139. }
  140. })
  141. .catch(function(error) {
  142. resolve(1);
  143. });
  144. } catch (e) {
  145. resolve(1);
  146. }
  147. });
  148. },
  149. // 获取单个数据
  150. getData() {
  151. // this.fileId =[]
  152. // console.log(' this.scoCon', this.scoCon);
  153. let params = {
  154. uid: this.scoCon.userid,
  155. cid: this.id
  156. };
  157. this.ajax
  158. .get(this.$store.state.api + "selectWorksEvaScore", params)
  159. .then(res => {
  160. // console.log("res", res.data);
  161. if (res.data[0].length > 0) {
  162. var data2 = [];
  163. res.data[0].forEach((val, index) => {
  164. if (val.task == this.task) {
  165. data2 = res.data[0][index];
  166. this.homeworkVal = res.data[0][index];
  167. }
  168. });
  169. // console.log('data2',data2);
  170. if (data2.length == 0) {
  171. this.scoTitList = JSON.parse(JSON.stringify(this.scoTit));
  172. } else {
  173. let data = JSON.parse(data2.rate);
  174. this.scoTitList.forEach((e, index) => {
  175. e.cog = null;
  176. for (const key in data) {
  177. // if (e.value.endsWith('。')) {
  178. // e.value = e.value.slice(0, -1); // 如果字符串以句号结尾,则去除最后一个字符
  179. // }
  180. let result = e.detail.match(/[\u4e00-\u9fa5a-zA-Z]+/g).join("");
  181. let key2 = key.match(/[\u4e00-\u9fa5a-zA-Z]+/g).join("");
  182. if (result.indexOf(key2) != -1) {
  183. e.cog = data[key];
  184. }
  185. if ("content" == key) {
  186. this.textarea = data[key];
  187. }
  188. }
  189. });
  190. this.scoTitList = JSON.parse(JSON.stringify(this.scoTitList));
  191. // console.log(this.scoTitList);
  192. }
  193. } else {
  194. this.scoTitList = JSON.parse(JSON.stringify(this.scoTit));
  195. }
  196. })
  197. .catch(err => {
  198. console.error(err);
  199. });
  200. },
  201. markScoreDigBtn() {
  202. // console.log('11112222');
  203. this.$emit("markScoreDig", {
  204. val: this.stUid,
  205. val2: this.toolIndex,
  206. tit: this.scoTit,
  207. uname:this.scoCon.sName
  208. });
  209. },
  210. // 重置
  211. reset() {
  212. this.scoTitList.forEach(e => {
  213. e.cog = 0;
  214. // console.log(e.cog);
  215. });
  216. },
  217. // 老师提交评分
  218. submit() {
  219. let data = this.scoTitList.map(e => {
  220. return e.detail + ":" + e.cog;
  221. });
  222. // console.log("data", data);
  223. const processedData = {};
  224. data.forEach(item => {
  225. const [key, value] = item.split(":");
  226. processedData[key] = Number(value) ? Number(value) : 0;
  227. });
  228. processedData.content = this.textarea;
  229. // console.log(processedData);
  230. let params = {
  231. cid: this.id,
  232. s: this.stage,
  233. t: this.task,
  234. rate: JSON.stringify(processedData),
  235. uid: this.stUid
  236. };
  237. // return console.log(params);
  238. this.ajax
  239. .get(this.$store.state.api + "updateWorksEva", params)
  240. .then(res => {
  241. this.$message({
  242. message: "评价成功",
  243. type: "success"
  244. });
  245. this.$emit("refreshOther", this.toolIndex);
  246. })
  247. .catch(err => {
  248. this.$message.error("评价失败");
  249. console.error(err);
  250. });
  251. },
  252. // ai评分
  253. AIsubmit() {
  254. let tit = this.scoTit;
  255. tit.forEach((e, index) => {
  256. if (!e.isai) {
  257. e.isai = 1;
  258. }
  259. });
  260. let con = JSON.parse(this.scoCon.works);
  261. this.$emit("updateLoading", {
  262. val: this.toolIndex,
  263. val2: this.wIndex,
  264. val3: true
  265. });
  266. let _text = "";
  267. for (let i = 0; i < tit.length; i++) {
  268. if (tit[i].isai == 1) {
  269. _text += `评价名称:${tit[i].value} 评价描述:${tit[i].detail} \n`;
  270. }
  271. }
  272. let laws = "";
  273. for (let i = 0; i < tit.length; i++) {
  274. if (tit[i].isai == 1) {
  275. laws += `评价维度:${tit[i].value} 评价细则:${tit[i].rule} \n`;
  276. }
  277. }
  278. // console.log(_text);
  279. let msg = `NOTICE
  280. Role: 你是一个专业的项目式学习导师,你要对学生的评价高度负责。你要根据“六级评价细则”给学生作品评分,并生成需要的JSON数据。
  281. Language: Please use the same language as the user requirement, if the user speaks Chinese, the specific text of your answer should also be in Chinese.
  282. ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
  283. Instruction: Based on the context, follow "Format example", write content.
  284. #Context
  285. ##要求
  286. 根据<评价细则>和<作业内容>的相关性评价作业,判根据细则评价作业,判断该作业属于六级中的哪个等级。如果作业内容与评价细则无关,则直接评为0星。
  287. ##评分资料
  288. 评价细则:${laws}
  289. 作业内容:${con.text}
  290. # Format example
  291. [{'评价名称':'评价等级0-5(数字)'},{'评价名称':'评价等级0-5(数字)'},{'评价名称':'评价等级0-5(数字)'},{'评价名称':'评价等级0-5(数字)'}]
  292. `;
  293. // console.log(msg);
  294. this.aiGet2(msg);
  295. },
  296. // ai打分
  297. aiGet2(messages, callback) {
  298. // console.log(this.toolIndex, this.wIndex);
  299. let _this = this;
  300. let params = {
  301. assistant_id: "6063369f-289a-11ef-8bf4-12e77c4cb76b",
  302. message: [
  303. {
  304. type: "text",
  305. text: messages.replaceAll("\n", " ").replaceAll("*", "")
  306. }
  307. ],
  308. session_name: uuidv4(),
  309. userId: this.userid,
  310. file_ids: [],
  311. model: "gpt-4o-2024-08-06"
  312. };
  313. this.ajax
  314. .post("https://gpt4.cocorobo.cn/ai_agent_park_chat", params)
  315. .then(response => {
  316. let data = response.data.FunctionResponse;
  317. // console.log("data", data);
  318. if (data.message) {
  319. let dArray = {};
  320. try {
  321. dArray = JSON.parse(
  322. data.message.replaceAll("```json", "").replaceAll("```", "")
  323. );
  324. } catch (error) {
  325. console.log("error_________________" + error);
  326. try {
  327. let regex = new RegExp("(?<=```json)([\\s\\S]*?)(?=```)");
  328. let match = data.message.match(regex);
  329. dArray = JSON.parse(
  330. match[0]
  331. .replace(/\n/g, "")
  332. .replace(/\s{2,}/g, "")
  333. .replace(/\'/g, '"')
  334. );
  335. } catch (error) {
  336. try {
  337. dArray = JSON.parse(
  338. data.message
  339. .replaceAll("```json", "")
  340. .replaceAll("# Solution", "")
  341. .replaceAll("```", "")
  342. .replace(/\n/g, "")
  343. .replace(/\s{2,}/g, "")
  344. .replace(/\'/g, '"')
  345. );
  346. } catch (error) {
  347. console.log("error_________________" + error);
  348. }
  349. console.log("error_________________" + error);
  350. }
  351. }
  352. // console.log("dArray3", dArray);
  353. // _this.submit2(dArray);
  354. // 提交评分
  355. // if (!dArray) {
  356. // _this.$emit("updateLoading", {val:_this.task,val2:_this.wIndex,val3:false});
  357. // }
  358. let processedData = {};
  359. // return console.log(dArray);
  360. dArray.forEach(function(item) {
  361. let key = Object.keys(item)[0];
  362. let value = item[key];
  363. processedData[key] = value;
  364. });
  365. for (const key in processedData) {
  366. if (!Number.isFinite(processedData[key] * 1)) {
  367. processedData[key] = 0;
  368. }
  369. }
  370. processedData.content = this.textarea;
  371. let params = {
  372. cid: _this.id,
  373. s: _this.stage,
  374. t: _this.task,
  375. rate: JSON.stringify(processedData),
  376. uid: _this.stUid
  377. };
  378. // console.log(params);
  379. _this.ajax
  380. .get(_this.$store.state.api + "updateWorksEva", params)
  381. .then(res => {
  382. _this.$message({
  383. message: "评价成功",
  384. type: "success"
  385. });
  386. // console.log(_this.wIndex, _this.task);
  387. _this.$emit("updateLoading", {
  388. val: _this.toolIndex,
  389. val2: _this.wIndex,
  390. val3: false
  391. });
  392. _this.$emit("refreshOther", _this.toolIndex);
  393. _this.getData();
  394. // _this.markScoPopover = false;
  395. // _this.$emit("update:loading", false);
  396. })
  397. .catch(err => {
  398. _this.$message.error("评价失败");
  399. _this.$emit("updateLoading", {
  400. val: _this.toolIndex,
  401. val2: _this.wIndex,
  402. val3: false
  403. });
  404. console.error(err);
  405. });
  406. }
  407. this.$forceUpdate();
  408. callback ? callback() : "";
  409. })
  410. .catch(error => {
  411. // _this.markScoPopover = false;
  412. // _this.$emit("update:loading", false);
  413. _this.$emit("updateLoading", {
  414. val: _this.toolIndex,
  415. val2: _this.wIndex,
  416. val3: false
  417. });
  418. _this.$message.error("评价失败");
  419. // _this.loading = false
  420. console.log(error);
  421. });
  422. },
  423. // ai循环评分
  424. async aiupdetaSco(messages, uid, stage, task,_fileid, callback) {
  425. let _this = this;
  426. let params = {
  427. assistant_id: "6063369f-289a-11ef-8bf4-12e77c4cb76b",
  428. message: [
  429. {
  430. type: "text",
  431. text: messages.replaceAll("\n", " ").replaceAll("*", "")
  432. }
  433. ],
  434. session_name: uuidv4(),
  435. userId: this.userid,
  436. file_ids: _fileid ? [_fileid] : [],
  437. model: "gpt-4o-2024-08-06"
  438. };
  439. return new Promise(resolve => {
  440. this.ajax
  441. .post("https://gpt4.cocorobo.cn/ai_agent_park_chat", params)
  442. .then(response => {
  443. let data = response.data.FunctionResponse;
  444. // console.log(data);
  445. if (data.message) {
  446. let dArray = {};
  447. try {
  448. dArray = JSON.parse(
  449. data.message.replaceAll("```json", "").replaceAll("```", "")
  450. );
  451. } catch (error) {
  452. console.log("error_________________" + error);
  453. try {
  454. let regex = new RegExp("(?<=```json)([\\s\\S]*?)(?=```)");
  455. let match = data.message.match(regex);
  456. // console.log("dArray2", match);
  457. dArray = JSON.parse(
  458. match[0]
  459. .replace(/\n/g, "")
  460. .replace(/\s{2,}/g, "")
  461. .replace(/\'/g, '"')
  462. );
  463. // dArray = data.choices[0].message.content
  464. } catch (error) {
  465. try {
  466. dArray = JSON.parse(
  467. data.message
  468. .replaceAll("```json", "")
  469. .replaceAll("# Solution", "")
  470. .replaceAll("```", "")
  471. .replace(/\n/g, "")
  472. .replace(/\s{2,}/g, "")
  473. .replace(/\'/g, '"')
  474. );
  475. } catch (error) {
  476. console.log("error_________________" + error);
  477. }
  478. console.log("error_________________" + error);
  479. }
  480. }
  481. let processedData = {};
  482. dArray.forEach(function(item) {
  483. let key = Object.keys(item)[0];
  484. let value = item[key];
  485. processedData[key] = value;
  486. });
  487. let IsAIsuccess = 0
  488. for (const tKey in this.scoTitList) {
  489. for (const key in processedData) {
  490. let result = this.scoTitList[tKey].detail.match(/[\u4e00-\u9fa5a-zA-Z]+/g).join("");
  491. let key2 = key.match(/[\u4e00-\u9fa5a-zA-Z]+/g).join("");
  492. if (key != "评语") {
  493. if (result.indexOf(key2) != -1) {
  494. IsAIsuccess++
  495. }
  496. continue;
  497. }
  498. }
  499. continue;
  500. }
  501. if (IsAIsuccess != this.scoTitList.length) {
  502. _this.$message.error("评价失败");
  503. resolve(1);
  504. return
  505. }
  506. for (const key in processedData) {
  507. // if (!Number.isFinite(processedData[key] * 1)) {
  508. // processedData[key] = 0;
  509. // }
  510. if (key == "评语") {
  511. processedData.content = processedData[key];
  512. }
  513. }
  514. delete processedData["评语"];
  515. // processedData.content = this.textarea;
  516. let params = {
  517. cid: _this.id,
  518. s: stage,
  519. t: task,
  520. rate: JSON.stringify(processedData),
  521. uid: uid
  522. };
  523. // console.log("params", params);
  524. _this.ajax
  525. .get(_this.$store.state.api + "updateWorksEva", params)
  526. .then(res => {
  527. resolve(1);
  528. _this.$message({
  529. message: "评价成功",
  530. type: "success"
  531. });
  532. })
  533. .catch(err => {
  534. resolve(1);
  535. _this.$message.error("评价失败");
  536. console.error(err);
  537. });
  538. }
  539. callback ? callback() : "";
  540. })
  541. .catch(error => {
  542. resolve(1);
  543. _this.$message.error("评价失败");
  544. // _this.loading = false
  545. console.log(error);
  546. });
  547. });
  548. },
  549. }
  550. };
  551. </script>
  552. <style scoped>
  553. .scoreTit {
  554. font-size: 16px;
  555. font-weight: 600;
  556. display: flex;
  557. justify-content: space-between;
  558. box-sizing: border-box;
  559. }
  560. .allD {
  561. margin: 5px 0;
  562. display: flex;
  563. width: 100%;
  564. overflow: auto;
  565. max-height: 100px;
  566. min-height: 60px;
  567. }
  568. .scoreStar {
  569. background-color: #f3f7fd;
  570. padding: 10px;
  571. height: 100%;
  572. flex: 1;
  573. }
  574. .scoreStar > div:last-child > .scoreStarBack {
  575. margin-bottom: 0;
  576. }
  577. .scoreStarBack {
  578. flex: 1;
  579. display: flex;
  580. justify-content: space-between;
  581. margin-bottom: 10px;
  582. }
  583. .rootImg {
  584. padding-top: 1px;
  585. box-sizing: border-box;
  586. display: block;
  587. }
  588. .scoreStarBack2 {
  589. padding: 10px 0;
  590. margin-right: 2px;
  591. }
  592. .AreaCss {
  593. margin-bottom: 5px;
  594. -webkit-line-clamp: 2;
  595. display: -webkit-box;
  596. -webkit-box-orient: vertical;
  597. overflow: hidden;
  598. text-overflow: ellipsis;
  599. /* margin-left: 20px; */
  600. }
  601. .AreaCss >>> .el-textarea__inner {
  602. min-height: 60px;
  603. max-height: 150px;
  604. padding-bottom: 20px;
  605. }
  606. .briefTit {
  607. width: 150px;
  608. text-overflow: ellipsis;
  609. overflow: hidden;
  610. white-space: nowrap;
  611. }
  612. </style>