aiBox.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. <template>
  2. <div class="ai_body">
  3. <div class="ai_body_dialog" v-loading="loading" ref="chatDialog">
  4. <div
  5. class="dialog_content"
  6. v-for="(item, index) in array"
  7. :key="item.uid"
  8. >
  9. <div v-if="item.content">
  10. <div class="content content2" v-html="item.content"></div>
  11. <div class="role">
  12. <img src="../../../assets/icon/new/role2.png" />
  13. </div>
  14. </div>
  15. <div style="margin-top:10px ;">
  16. <div class="role">
  17. <img src="../../../assets/icon/new/role1.png" />
  18. </div>
  19. <div
  20. class="content"
  21. v-loading="item.loading"
  22. v-html="item.aiContent"
  23. ></div>
  24. </div>
  25. <!-- <div class="role">
  26. <img src="../../../assets/icon/new/role1.png"/>
  27. <img src="../../../assets/icon/new/role2.png"/>
  28. </div>
  29. <div class="content content2" :class="{ content2: item.role == 2 }">
  30. {{ item.text }}
  31. </div>
  32. <div class="role">
  33. <img src="../../../assets/icon/new/role1.png"/>
  34. </div>
  35. <div class="content">
  36. {{ item.text }}
  37. </div> -->
  38. </div>
  39. </div>
  40. <div class="ai_body_select">
  41. <div class="checkBox" v-if="checkBool">
  42. <div class="task">
  43. <div class="title">选择需要优化的任务:</div>
  44. <div class="content">
  45. <div class="span" @click="addAllTask()">
  46. <div class="check">
  47. <img
  48. :src="checkImg"
  49. alt=""
  50. v-if="checkArray.length !== course.length"
  51. />
  52. <img :src="checkIsImg" alt="" v-else />
  53. </div>
  54. <span>全选</span>
  55. </div>
  56. <div
  57. class="span"
  58. v-for="(item, index) in course"
  59. :key="index"
  60. @click="addTask(index)"
  61. >
  62. <div class="check">
  63. <img
  64. :src="checkImg"
  65. alt=""
  66. v-if="checkArray.indexOf(index) === -1"
  67. />
  68. <img :src="checkIsImg" alt="" v-else />
  69. </div>
  70. <span>任务{{ index + 1 }}</span>
  71. </div>
  72. </div>
  73. </div>
  74. <div class="part">
  75. <div class="title">选择优化的部分:</div>
  76. <div class="content">
  77. <div
  78. class="span"
  79. v-for="(item, index) in partArray"
  80. :key="index"
  81. :class="{ active: part == item.name }"
  82. @click="checkPart(item.name)"
  83. >
  84. {{ item.name }}
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. <span
  90. class="check"
  91. :class="{ isCheck: checkBool }"
  92. v-if="!checkArray.length && !part"
  93. @click="checkBool = !checkBool"
  94. >选择优化内容</span
  95. >
  96. <span
  97. class="check"
  98. :class="{ isCheck: checkBool }"
  99. @click="checkBool = !checkBool"
  100. v-else
  101. >
  102. <el-tooltip :content="taskName" placement="top" effect="dark">
  103. <!-- content to trigger tooltip here -->
  104. <span>{{ taskName }}</span>
  105. </el-tooltip>
  106. </span>
  107. </div>
  108. <div class="ai_body_input">
  109. <textarea
  110. rows="3"
  111. @keyup.enter="addContent"
  112. class="binfo_input binfo_textarea"
  113. cols
  114. v-model.trim="courseText"
  115. placeholder="在此输入您想了解的内容"
  116. ></textarea>
  117. <div
  118. class="c_pub_button_confirm"
  119. v-if="!loading && courseText"
  120. @click="addContent"
  121. >
  122. 发送
  123. </div>
  124. <div class="c_pub_button_confirm" @click="promptTit" v-else>发送</div>
  125. </div>
  126. </div>
  127. </template>
  128. <script>
  129. import checkImg from "../../../assets/icon/sourceFile/check.png";
  130. import checkIsImg from "../../../assets/icon/sourceFile/check_is.png";
  131. import { v4 as uuidv4 } from "uuid";
  132. import MarkdownIt from "markdown-it";
  133. export default {
  134. props: {
  135. unitJson: {
  136. type: Array
  137. },
  138. courseId:{
  139. type:String,
  140. default:""
  141. },
  142. },
  143. data() {
  144. return {
  145. array: [],
  146. courseText: "",
  147. checkImg: checkImg,
  148. checkIsImg: checkIsImg,
  149. userid: this.$route.query.userid,
  150. checkArray: [],
  151. course: [{ title: "任务1" }, { title: "任务2" }, { title: "任务3" }],
  152. partArray: [
  153. { name: "全部内容" },
  154. { name: "任务设计" },
  155. { name: "评价设计" }
  156. ],
  157. part: "全部内容",
  158. checkBool: false,
  159. loading: false
  160. };
  161. },
  162. watch: {
  163. unitJson: {
  164. immediate: true,
  165. deep: true,
  166. handler(newValue, oldValue) {
  167. this.course = this.unitJson[0].chapterInfo[0].taskJson;
  168. }
  169. }
  170. },
  171. methods: {
  172. promptTit() {
  173. if (!this.loading && !this.courseText) {
  174. this.$message({
  175. message: "请输入您想要了解的内容",
  176. type: "warning"
  177. });
  178. } else {
  179. this.$message({
  180. message: "请回答完毕后再次发送",
  181. type: "warning"
  182. });
  183. }
  184. },
  185. addContent() {
  186. let message = this.courseText
  187. if (this.courseText) {
  188. let msg = `
  189. ATTENTION: Use '##' to SPLIT SECTIONS, not '#'.Output format carefully referenced "Format example".`
  190. if(this.checkArray.length){
  191. let task = []
  192. if(this.part == "全部内容"){
  193. // msg += `--------
  194. // ## 示例
  195. // [
  196. // {
  197. // detail: "面向学生的任务描述",
  198. // elist:[
  199. // {"value":"评价名字1","detail":"评价维度1", "score": 5},
  200. // {"value":"评价名字2","detail":"评价维度2", "score": 5},
  201. // {"value":"评价名字3","detail":"评价维度3", "score": 5}
  202. // ],
  203. // toolChoose: [
  204. // {
  205. // tool:"电子白板",
  206. // detail: "工具描述"
  207. // },
  208. // {
  209. // tool:"思维大图",
  210. // detail: "工具描述"
  211. // }
  212. // ]
  213. // },
  214. // {
  215. // detail: "面向学生的任务描述",
  216. // elist:[
  217. // {"value":"评价名字1","detail":"评价维度1", "score": 5},
  218. // {"value":"评价名字2","detail":"评价维度2", "score": 5},
  219. // {"value":"评价名字3","detail":"评价维度3", "score": 5}
  220. // ],
  221. // toolChoose: []
  222. // },
  223. // {
  224. // detail: "面向学生的任务描述",
  225. // elist:[
  226. // {"value":"评价名字1","detail":"评价维度1", "score": 5},
  227. // {"value":"评价名字2","detail":"评价维度2", "score": 5},
  228. // {"value":"评价名字3","detail":"评价维度3", "score": 5}
  229. // ],
  230. // toolChoose: [
  231. // {
  232. // tool:"文档",
  233. // detail: "工具描述"
  234. // }
  235. // ]
  236. // }
  237. // ]
  238. // --------
  239. // ## 输出格式与要求
  240. // [
  241. // {
  242. // detail: "面向学生的任务描述",
  243. // elist:[
  244. // {"value":"评价名字1","detail":"评价维度1","score":5},
  245. // {"value":"评价名字2","detail":"评价维度2","score":5},
  246. // {"value":"评价名字3","detail":"评价维度3","score":5}
  247. // ],//至少3条评价标准,这个评价是教师用来评价学生表现的,需要包含评价维度,以及该维度中教师期待学生的表现,句式为学生应该能....
  248. // toolChoose: [
  249. // {
  250. // tool: "工具", //电子白板,文档,思维导图,表格,作业提交中选择其中一个工具
  251. // detail: "工具描述"
  252. // }
  253. // ] //可0~2个工具
  254. // }
  255. // ]
  256. // `
  257. for(var i = 0; i < this.checkArray.length; i++){
  258. let _index = this.checkArray[i]
  259. task.push(this.course[_index])
  260. }
  261. }else if(this.part == "任务设计"){
  262. // msg += `
  263. // --------
  264. // ## 示例
  265. // [
  266. // {
  267. // detail: "面向学生的任务描述",
  268. // toolChoose: [
  269. // {
  270. // tool:"电子白板",
  271. // detail: "工具描述"
  272. // },
  273. // {
  274. // tool:"思维大图",
  275. // detail: "工具描述"
  276. // }
  277. // ]
  278. // },
  279. // {
  280. // detail: "面向学生的任务描述",
  281. // toolChoose: []
  282. // },
  283. // {
  284. // detail: "面向学生的任务描述",
  285. // toolChoose: [
  286. // {
  287. // tool:"文档",
  288. // detail: "工具描述"
  289. // }
  290. // ]
  291. // }
  292. // ]
  293. // --------
  294. // ## 输出格式与要求
  295. // [
  296. // {
  297. // detail: "面向学生的任务描述",
  298. // toolChoose: [
  299. // {
  300. // tool: "工具", //电子白板,文档,思维导图,表格,作业提交中选择其中一个工具
  301. // detail: "工具描述"
  302. // }
  303. // ] //可0~2个工具
  304. // }
  305. // ]
  306. // `
  307. for(var i = 0; i < this.checkArray.length; i++){
  308. let _index = this.checkArray[i]
  309. task.push(this.course[_index])
  310. }
  311. }else if(this.part == "评价设计"){
  312. // msg += `
  313. // --------
  314. // ## 示例
  315. // [
  316. // {
  317. // elist:[
  318. // {"value":"评价名字1","detail":"评价维度1", "score": 5},
  319. // {"value":"评价名字2","detail":"评价维度2", "score": 5},
  320. // {"value":"评价名字3","detail":"评价维度3", "score": 5}
  321. // ],
  322. // },
  323. // {
  324. // elist:[
  325. // {"value":"评价名字1","detail":"评价维度1", "score": 5},
  326. // {"value":"评价名字2","detail":"评价维度2", "score": 5},
  327. // {"value":"评价名字3","detail":"评价维度3", "score": 5}
  328. // ],
  329. // },
  330. // {
  331. // elist:[
  332. // {"value":"评价名字1","detail":"评价维度1", "score": 5},
  333. // {"value":"评价名字2","detail":"评价维度2", "score": 5},
  334. // {"value":"评价名字3","detail":"评价维度3", "score": 5}
  335. // ],
  336. // }
  337. // ]
  338. // --------
  339. // ## 输出格式与要求
  340. // [
  341. // {
  342. // elist:[
  343. // {"value":"评价名字1","detail":"评价维度1","score":5},
  344. // {"value":"评价名字2","detail":"评价维度2","score":5},
  345. // {"value":"评价名字3","detail":"评价维度3","score":5}
  346. // ],//至少3条评价标准,这个评价是教师用来评价学生表现的,需要包含评价维度,以及该维度中教师期待学生的表现,句式为学生应该能....
  347. // }
  348. // ]
  349. // `
  350. for(var i = 0; i < this.checkArray.length; i++){
  351. let _index = this.checkArray[i]
  352. task.push(this.course[_index].eList)
  353. }
  354. }
  355. msg += `
  356. --------
  357. ## 修改内容
  358. ${JSON.stringify(task)}
  359. `
  360. msg += `
  361. --------
  362. ## 要求
  363. ${this.courseText}
  364. `
  365. message = msg
  366. }
  367. let _uuid = uuidv4();
  368. this.array.push({
  369. role: "user",
  370. content: `${this.courseText}`,
  371. uid: _uuid,
  372. AI: "AI",
  373. aiContent: "",
  374. oldContent: "",
  375. isShowSynchronization: false,
  376. filename: "",
  377. index: this.array.length,
  378. is_mind_map: false,
  379. loading: true
  380. });
  381. this.$nextTick(() => {
  382. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  383. });
  384. let params = JSON.stringify({
  385. model: "gpt-3.5-turbo",
  386. temperature: 0,
  387. max_tokens: 4096,
  388. top_p: 1,
  389. frequency_penalty: 0,
  390. presence_penalty: 0,
  391. messages: [{ role: "user", content: message }],
  392. uid: _uuid,
  393. mind_map_question: ""
  394. });
  395. this.courseText = "";
  396. this.ajax
  397. .post("https://gpt4.cocorobo.cn/chat", params)
  398. .then(res => {
  399. if (res.data.FunctionResponse.result == "发送成功") {
  400. } else {
  401. this.$message.warning(res.data.FunctionResponse.result);
  402. }
  403. })
  404. .catch(e => {
  405. console.log(e);
  406. });
  407. this.getAiContent(_uuid);
  408. }
  409. },
  410. getAiContent(_uid) {
  411. let _source = new EventSource(`https://gpt4.cocorobo.cn/stream/${_uid}`); //http://gpt4.cocorobo.cn:8011/stream/ https://gpt4.cocorobo.cn/stream/
  412. let _allText = "";
  413. let _mdText = "";
  414. const md = new MarkdownIt();
  415. _source.onmessage = _e => {
  416. if (_e.data.replace("'", "").replace("'", "") == "[DONE]") {
  417. //对话已经完成
  418. _mdText = _mdText.replace("_", "");
  419. _source.close();
  420. this.$nextTick(() => {
  421. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  422. });
  423. this.array.find(i => i.uid == _uid).aiContent = _mdText;
  424. this.array.find(i => i.uid == _uid).isalltext = true;
  425. this.array.find(i => i.uid == _uid).isShowSynchronization = true;
  426. this.array.find(i => i.uid == _uid).loading = false;
  427. // 这里保存对话
  428. this.insertChat(_uid);
  429. return;
  430. } else {
  431. //对话还在继续
  432. let _text = "";
  433. _text = _e.data.replaceAll("'", "");
  434. if (_allText == "") {
  435. _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
  436. } else {
  437. _allText += _text;
  438. }
  439. _mdText = _allText + "_";
  440. _mdText = _mdText.replace(/\\n/g, "\n");
  441. _mdText = _mdText.replace(/\\/g, "");
  442. if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
  443. //转化返回的回复流数据
  444. _mdText = md.render(_mdText);
  445. this.array.find(i => i.uid == _uid).aiContent = _mdText;
  446. this.array.find(i => i.uid == _uid).loading = false;
  447. this.$nextTick(() => {
  448. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  449. });
  450. // 处理流数据
  451. }
  452. };
  453. },
  454. //保存消息
  455. insertChat(_uid) {
  456. let _data = this.array.find(i => i.uid == _uid);
  457. if (!_data) return;
  458. let params = {
  459. userId: this.userid,
  460. userName: "qgt",
  461. groupId: "602def61-005d-11ee-91d8-005056b8q12w",
  462. answer: _data.aiContent,
  463. problem: _data.content,
  464. file_id: _data.fileid ? _data.fileid : "",
  465. alltext: _data.aiContent,
  466. type: "chat",
  467. filename: _data.filename,
  468. session_name: `${this.courseId}-addCourse` //这是对话记录位置
  469. };
  470. this.ajax
  471. .post("https://gpt4.cocorobo.cn/insert_chat", params)
  472. .then(res => {});
  473. },
  474. // 获取对应的聊天记录
  475. getChatList() {
  476. return new Promise((resolve, reject) => {
  477. if (this.loading) return this.$message.info("请稍等...");
  478. this.array = [];
  479. this.loading = true;
  480. let params = {
  481. userid: this.userid,
  482. groupid: "602def61-005d-11ee-91d8-005056b8q12w",
  483. // session_name:``
  484. session_name: `${this.courseId}-addCourse`
  485. };
  486. this.ajax
  487. .post("https://gpt4.cocorobo.cn/get_agent_park_chat", params)
  488. .then(res => {
  489. let _data = JSON.parse(res.data.FunctionResponse);
  490. if (_data.length > 0) {
  491. let _chatList = [];
  492. for (let i = 0; i < _data.length; i++) {
  493. _chatList.push({
  494. loading: false,
  495. role: "user",
  496. content: _data[i].problem,
  497. uid: _data[i].id,
  498. AI: "AI",
  499. aiContent: _data[i].answer,
  500. oldContent: _data[i].answer,
  501. isShowSynchronization: false,
  502. filename: _data[i].filename,
  503. index: i,
  504. is_mind_map: false,
  505. fileid: _data[i].fileid
  506. });
  507. }
  508. this.array = _chatList;
  509. this.loading = false;
  510. } else {
  511. //没有对话记录
  512. this.loading = false;
  513. }
  514. resolve();
  515. })
  516. .catch(err => {
  517. console.log(err);
  518. this.$message.error("获取对话记录失败");
  519. this.loading = false;
  520. resolve();
  521. });
  522. });
  523. },
  524. addTask(index) {
  525. if (this.checkArray.indexOf(index) !== -1) {
  526. this.checkArray.splice(this.checkArray.indexOf(index), 1);
  527. } else {
  528. this.checkArray.push(index);
  529. }
  530. console.log(index);
  531. },
  532. addAllTask() {
  533. if (this.checkArray.length === this.course.length) {
  534. this.checkArray = [];
  535. } else {
  536. this.checkArray = [];
  537. this.course.forEach((item, index) => {
  538. this.checkArray.push(index);
  539. });
  540. }
  541. },
  542. checkPart(name) {
  543. this.part = name;
  544. }
  545. },
  546. computed: {
  547. courseTextLength() {
  548. return this.courseText.length;
  549. },
  550. taskName() {
  551. let task = "";
  552. if (this.checkArray.length) {
  553. task = "任务";
  554. this.checkArray = this.checkArray.sort((a, b) => a - b);
  555. let a = JSON.parse(JSON.stringify(this.checkArray));
  556. for (let index = 0; index < a.length; index++) {
  557. a[index]++;
  558. }
  559. task += a.join("/");
  560. }
  561. return task + " " + this.part;
  562. }
  563. },
  564. mounted() {
  565. this.getChatList().then(_ => {
  566. this.$nextTick(() => {
  567. console.log(this.$refs.chatDialog.scrollHeight)
  568. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  569. });
  570. });
  571. }
  572. };
  573. </script>
  574. <style scoped>
  575. .ai_body {
  576. height: 100%;
  577. width: calc(100% - 20px);
  578. margin: 0 auto;
  579. }
  580. .binfo_input {
  581. width: 100%;
  582. margin: 0;
  583. padding: 12px 14px;
  584. display: block;
  585. min-width: 0;
  586. outline: none;
  587. box-sizing: border-box;
  588. background: none;
  589. border: none;
  590. border-radius: 4px;
  591. background: #fff;
  592. font-size: 14px;
  593. resize: none;
  594. font-family: "Microsoft YaHei";
  595. min-height: 48px;
  596. /* border: 1px solid #3682fc00; */
  597. border: 1.5px solid #cad1dc;
  598. }
  599. .binfo_textarea {
  600. border: 1.5px solid #cad1dc;
  601. font-size: 14px;
  602. resize: none;
  603. /* background: #f6f6f6; */
  604. font-family: "Microsoft YaHei";
  605. }
  606. .binfo_textarea::-webkit-scrollbar {
  607. /*滚动条整体样式*/
  608. width: 6px;
  609. /*高宽分别对应横竖滚动条的尺寸*/
  610. height: 6px;
  611. }
  612. /*定义滚动条轨道 内阴影+圆角*/
  613. .binfo_textarea::-webkit-scrollbar-track {
  614. border-radius: 10px;
  615. background-color: rgba(0, 0, 0, 0.1);
  616. }
  617. /*定义滑块 内阴影+圆角*/
  618. .binfo_textarea::-webkit-scrollbar-thumb {
  619. border-radius: 10px;
  620. -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
  621. background-color: rgba(0, 0, 0, 0.1);
  622. }
  623. .binfo_input:focus-visible {
  624. border: 1.5px solid #3681fc !important;
  625. }
  626. .ai_body_input {
  627. /* position: relative; */
  628. display: flex;
  629. flex-direction: column;
  630. justify-content: center;
  631. align-items: end;
  632. }
  633. .c_pub_button_confirm {
  634. /* position: absolute;
  635. bottom: 13px;
  636. right: 13px; */
  637. margin-top: 10px;
  638. width: 80px;
  639. display: flex;
  640. justify-content: center;
  641. }
  642. .ai_body_dialog {
  643. padding: 10px 0;
  644. box-sizing: border-box;
  645. height: calc(100% - 180px);
  646. overflow: auto;
  647. margin-bottom: 10px;
  648. }
  649. .dialog_content {
  650. width: 100%;
  651. display: flex;
  652. flex-direction: column;
  653. }
  654. .dialog_content > div {
  655. display: flex;
  656. align-items: flex-start;
  657. }
  658. .dialog_content + .dialog_content {
  659. margin: 15px 0;
  660. }
  661. .dialog_content > div .right {
  662. flex-direction: row-reverse;
  663. }
  664. .dialog_content > div .right .role {
  665. margin-right: 0;
  666. margin-left: 10px;
  667. }
  668. .dialog_content > div .role {
  669. min-width: 30px;
  670. width: 30px;
  671. height: 30px;
  672. margin-right: 10px;
  673. border-radius: 50%;
  674. }
  675. .dialog_content > div .role > img {
  676. height: 100%;
  677. width: 100%;
  678. }
  679. .dialog_content > div .content {
  680. padding: 10px 5px;
  681. border-radius: 5px;
  682. width: 100%;
  683. word-break: break-word;
  684. box-sizing: border-box;
  685. /* white-space: pre-line; */
  686. max-width: 100%;
  687. background: #f7f7f7;
  688. overflow: hidden;
  689. margin: 0 10px;
  690. }
  691. .dialog_content > div .content2 {
  692. background: #3681fc;
  693. color: #fff;
  694. }
  695. .ai_body_select {
  696. position: relative;
  697. }
  698. .ai_body_select > .check {
  699. background: #e7e7e7;
  700. display: flex;
  701. width: fit-content;
  702. padding: 0 10px;
  703. height: 30px;
  704. border-radius: 21px;
  705. font-size: 14px;
  706. align-items: center;
  707. justify-content: center;
  708. color: #0061ff;
  709. font-weight: 700;
  710. margin: 10px 0;
  711. cursor: pointer;
  712. }
  713. .ai_body_select > .check::before {
  714. content: "";
  715. width: 15px;
  716. height: 15px;
  717. display: block;
  718. background-image: url("../../../assets/icon/course/aiPart.png");
  719. background-size: 100% 100%;
  720. margin-right: 5px;
  721. }
  722. .ai_body_select > .check::after {
  723. content: "";
  724. width: 15px;
  725. height: 15px;
  726. display: block;
  727. background-image: url("../../../assets/icon/course/aiPart_arrow.png");
  728. background-size: 100% 100%;
  729. margin-right: 5px;
  730. }
  731. .ai_body_select > .isCheck {
  732. background: #0061ff;
  733. display: flex;
  734. width: fit-content;
  735. padding: 0 10px;
  736. height: 30px;
  737. border-radius: 21px;
  738. font-size: 14px;
  739. align-items: center;
  740. justify-content: center;
  741. color: #fff;
  742. font-weight: 700;
  743. margin: 10px 0;
  744. cursor: pointer;
  745. max-width: 100%;
  746. box-sizing: border-box;
  747. }
  748. .ai_body_select > .isCheck > span {
  749. width: calc(100% - 40px);
  750. display: block;
  751. overflow: hidden;
  752. white-space: nowrap;
  753. text-overflow: ellipsis;
  754. }
  755. .ai_body_select > .isCheck::before {
  756. content: "";
  757. width: 15px;
  758. height: 15px;
  759. display: block;
  760. background-image: url("../../../assets/icon/course/aiPart_active.png");
  761. background-size: 100% 100%;
  762. margin-right: 5px;
  763. }
  764. .ai_body_select > .isCheck::after {
  765. content: "";
  766. width: 15px;
  767. height: 15px;
  768. display: block;
  769. background-image: url("../../../assets/icon/course/aiPart_arrow_active.png");
  770. background-size: 100% 100%;
  771. margin-right: 5px;
  772. }
  773. .ai_body_select > .checkBox {
  774. position: absolute;
  775. bottom: 40px;
  776. border: 1px solid #e0eafb;
  777. width: 100%;
  778. height: 300px;
  779. background: #fff;
  780. border-radius: 5px;
  781. padding: 10px;
  782. box-sizing: border-box;
  783. }
  784. .ai_body_select > .checkBox > .task > .title,
  785. .ai_body_select > .checkBox > .part > .title {
  786. font-size: 14px;
  787. font-weight: 700;
  788. margin-bottom: 5px;
  789. }
  790. .ai_body_select > .checkBox > .task {
  791. height: calc(100% - 60px);
  792. }
  793. .ai_body_select > .checkBox > .part {
  794. }
  795. .ai_body_select > .checkBox > .task > .content {
  796. height: calc(100% - 40px);
  797. overflow: auto;
  798. }
  799. .ai_body_select > .checkBox > .task > .content > .span + .span {
  800. margin-top: 5px;
  801. }
  802. .ai_body_select > .checkBox > .task > .content > .span {
  803. display: flex;
  804. align-items: center;
  805. font-size: 14px;
  806. cursor: pointer;
  807. }
  808. .ai_body_select > .checkBox > .task > .content > .span > .check {
  809. width: 13px;
  810. height: 13px;
  811. display: flex;
  812. align-items: center;
  813. margin-right: 5px;
  814. }
  815. .ai_body_select > .checkBox > .task > .content > .span > .check > img {
  816. width: 100%;
  817. height: 100%;
  818. }
  819. .ai_body_select > .checkBox > .part > .content {
  820. display: flex;
  821. align-items: center;
  822. font-size: 14px;
  823. justify-content: space-between;
  824. }
  825. .ai_body_select > .checkBox > .part > .content > .span {
  826. padding: 3px 6px;
  827. border: 1px solid #e0eafb;
  828. border-radius: 40px;
  829. cursor: pointer;
  830. }
  831. .ai_body_select > .checkBox > .part > .content > .span.active {
  832. color: #0061ff;
  833. border-color: #0061ff;
  834. }
  835. </style>