aiBox.vue 26 KB

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