aiBoxRight.vue 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141
  1. <template>
  2. <div class="ai_body" v-loading="loading">
  3. <div class="ai_body_dialog" ref="chatDialog">
  4. <div class="dialog_content" v-for="item in array" :key="item.uid">
  5. <div v-if="item.content" style="margin-left: auto;">
  6. <div class="content content2" v-html="item.content"></div>
  7. <div class="role">
  8. <img src="../../../../assets/icon/new/role2.png" />
  9. </div>
  10. </div>
  11. <div
  12. style="margin-top:20px;margin-bottom:20px ; margin-right: auto;"
  13. v-if="item.aiContent || item.loading"
  14. >
  15. <div class="role">
  16. <img
  17. :src="
  18. item.fileid
  19. ? item.fileid
  20. : require('../../../../assets/icon/new/role1.png')
  21. "
  22. />
  23. </div>
  24. <div
  25. element-loading-background="#f6f9ff"
  26. :style="{
  27. minHeight: item.loading ? '50px' : 'unset',
  28. minWidth: item.loading ? '50px' : 'unset'
  29. }"
  30. class="content"
  31. v-loading="item.loading"
  32. >
  33. <span class="vditor-reset" v-html="item.aiContent"></span>
  34. <span class="createTime" v-text="item.createtime"></span>
  35. </div>
  36. <div
  37. class="ai_btn_box"
  38. v-if="!pan(item.aiContent).length && !item.loading"
  39. >
  40. <img
  41. src="../../../../assets/icon/course/pasete.png"
  42. @click="onCopy(item.aiContent)"
  43. />
  44. </div>
  45. </div>
  46. </div>
  47. </div>
  48. <div class="ai_body_select" v-if="false">
  49. <div class="checkBox" v-if="checkBool">
  50. <div class="task">
  51. <div class="title">选择需要优化的任务:</div>
  52. <div class="content">
  53. <div class="span" @click="addAllTask()">
  54. <div class="check">
  55. <img
  56. :src="checkImg"
  57. alt=""
  58. v-if="checkArray.length !== course.length"
  59. />
  60. <img :src="checkIsImg" alt="" v-else />
  61. </div>
  62. <span>全选</span>
  63. </div>
  64. <div
  65. class="span"
  66. v-for="(item, index) in course"
  67. :key="index"
  68. @click="addTask(index)"
  69. >
  70. <div class="check">
  71. <img
  72. :src="checkImg"
  73. alt=""
  74. v-if="checkArray.indexOf(index) === -1"
  75. />
  76. <img :src="checkIsImg" alt="" v-else />
  77. </div>
  78. <span>任务{{ index + 1 }}</span>
  79. </div>
  80. </div>
  81. </div>
  82. <div class="part">
  83. <div class="title">选择优化的部分:</div>
  84. <div class="content">
  85. <div
  86. class="span"
  87. v-for="(item, index) in partArray"
  88. :key="index"
  89. :class="{ active: part == item.name }"
  90. @click="checkPart(item.name)"
  91. >
  92. {{ item.name }}
  93. </div>
  94. </div>
  95. </div>
  96. </div>
  97. <span
  98. class="check"
  99. :class="{ isCheck: checkBool }"
  100. v-if="!checkArray.length && !part"
  101. @click="checkBool = !checkBool"
  102. >选择优化内容</span
  103. >
  104. <span
  105. class="check"
  106. :class="{ isCheck: checkBool }"
  107. @click="checkBool = !checkBool"
  108. v-else
  109. >
  110. <el-tooltip :content="taskName" placement="top" effect="dark">
  111. <!-- content to trigger tooltip here -->
  112. <span>{{ taskName }}</span>
  113. </el-tooltip>
  114. </span>
  115. </div>
  116. <div class="ai_body_input">
  117. <div class="ai_b_i_btnArea">
  118. <span class="clear" @click.stop="clear()">
  119. <svg
  120. width="20"
  121. height="20"
  122. viewBox="0 0 20 20"
  123. fill="none"
  124. xmlns="http://www.w3.org/2000/svg"
  125. >
  126. <path
  127. fill-rule="evenodd"
  128. clip-rule="evenodd"
  129. d="M2.5 3.125C2.5 2.77982 2.77982 2.5 3.125 2.5H16.875C17.2202 2.5 17.5 2.77982 17.5 3.125V8.02715C17.5 8.37233 17.2202 8.65215 16.875 8.65215C16.5298 8.65215 16.25 8.37233 16.25 8.02715V3.75H3.75V16.25H8.125C8.47018 16.25 8.75 16.5298 8.75 16.875C8.75 17.2202 8.47018 17.5 8.125 17.5H3.125C2.77982 17.5 2.5 17.2202 2.5 16.875V3.125Z"
  130. />
  131. <path
  132. fill-rule="evenodd"
  133. clip-rule="evenodd"
  134. d="M5.625 6.1521C5.625 5.80692 5.90482 5.5271 6.25 5.5271H13.125C13.4702 5.5271 13.75 5.80692 13.75 6.1521C13.75 6.49728 13.4702 6.7771 13.125 6.7771H6.25C5.90482 6.7771 5.625 6.49728 5.625 6.1521Z"
  135. />
  136. <path
  137. fill-rule="evenodd"
  138. clip-rule="evenodd"
  139. d="M5.625 9.2771C5.625 8.93192 5.90482 8.6521 6.25 8.6521H9.37496C9.72014 8.6521 9.99996 8.93192 9.99996 9.2771C9.99996 9.62228 9.72014 9.9021 9.37496 9.9021H6.25C5.90482 9.9021 5.625 9.62228 5.625 9.2771Z"
  140. />
  141. <path
  142. fill-rule="evenodd"
  143. clip-rule="evenodd"
  144. d="M12.465 11.507L15.9141 14.9048C16.1279 14.5365 16.25 14.1088 16.25 13.6521C16.25 12.2714 15.1307 11.1521 13.75 11.1521C13.2799 11.1521 12.8406 11.2815 12.465 11.507ZM15.0374 15.7957L11.5873 12.397C11.3726 12.7659 11.25 13.1944 11.25 13.6521C11.25 15.0328 12.3693 16.1521 13.75 16.1521C14.2211 16.1521 14.6613 16.0222 15.0374 15.7957ZM11.0797 11.0192C11.759 10.3303 12.7051 9.9021 13.75 9.9021C15.8211 9.9021 17.5 11.581 17.5 13.6521C17.5 14.6767 17.0882 15.6064 16.4226 16.2827C15.7431 16.9729 14.7961 17.4021 13.75 17.4021C11.6789 17.4021 10 15.7232 10 13.6521C10 12.6263 10.4127 11.6957 11.0797 11.0192Z"
  145. />
  146. </svg>
  147. <span>清屏</span>
  148. </span>
  149. <span
  150. class="clear"
  151. @click.stop="showjList = !showjList"
  152. v-if="jArray.length"
  153. >
  154. <span>查看</span>
  155. </span>
  156. <!-- <div style="margin-left: auto;">
  157. <el-switch v-model="continuous"></el-switch>
  158. <span @click.stop="continuous = !continuous">连续对话</span>
  159. </div> -->
  160. </div>
  161. <div
  162. class="ai_b_i_roleListBox"
  163. ref="roleListRef"
  164. v-if="showRoleList && choseRoleList.length > 0"
  165. >
  166. <div
  167. :class="[
  168. 'ai_b_i_rlb_item',
  169. index == choseRoleItem ? 'ai_b_i_rlb_itemActive' : ''
  170. ]"
  171. :ref="`roleItem${index}Ref`"
  172. v-for="(item, index) in choseRoleList"
  173. :key="item.id"
  174. @mouseover="choseRoleItem = index"
  175. @click.stop="choseRole(item)"
  176. >
  177. <div class="ai_b_i_rlb_itemTop">
  178. <img
  179. :src="
  180. item.headUrl
  181. ? item.headUrl
  182. : require('../../../../assets/icon/new/role1.png')
  183. "
  184. alt=""
  185. />
  186. <div class="ai_b_i_rlb_i_name">
  187. <span>{{ item.assistantName }}</span>
  188. <span>作者:{{ item.username }}</span>
  189. </div>
  190. </div>
  191. <div class="ai_b_i_rlb_itemBottom">
  192. {{ item.prologue }}
  193. </div>
  194. </div>
  195. </div>
  196. <!-- <div class="ai_b_i_textListBox">
  197. <div class="ai_b_i_tlb_left"></div>
  198. <div class="ai_b_i_tlb_right"></div>
  199. </div> -->
  200. <!-- @input="inputChange" -->
  201. <textarea
  202. @input="inputChange"
  203. class="ai_body_input_textarea"
  204. @keydown="textareaKeydown"
  205. :disabled="isVoice"
  206. ref="textareaRef"
  207. v-model.trim="courseText"
  208. :placeholder="isVoice ? isTalk?'':'点击按钮开始录音' : '在此输入您想了解的内容'"
  209. ></textarea>
  210. <span
  211. class="c_voiceBtn"
  212. v-if="!courseText && !isVoice"
  213. @click.stop="changeVoice(true)"
  214. >
  215. <svg
  216. width="22"
  217. height="22"
  218. viewBox="0 0 22 22"
  219. fill="none"
  220. xmlns="http://www.w3.org/2000/svg"
  221. >
  222. <path
  223. fill-rule="evenodd"
  224. clip-rule="evenodd"
  225. d="M11.4583 14.0308C13.8381 14.0308 15.7551 12.0651 15.7551 9.62496V6.23588C15.7551 3.79574 13.8381 1.83008 11.4583 1.83008C9.07845 1.83008 7.16138 3.79574 7.16138 6.23588V9.62496C7.16138 12.0651 9.07845 14.0308 11.4583 14.0308ZM8.4835 6.23588C8.4835 4.54134 9.80561 3.18571 11.4583 3.18571C13.1109 3.18571 14.433 4.54134 14.433 6.23588V9.62496C14.433 11.3195 13.1109 12.6751 11.4583 12.6751C9.80561 12.6751 8.4835 11.3195 8.4835 9.62496V6.23588ZM18.3333 10.6405C18.3333 10.2677 18.0358 9.96264 17.6722 9.96264C17.3417 9.96264 17.0442 10.2338 17.0111 10.5727C16.5484 13.3178 14.2347 15.3852 11.4583 15.3852C8.68181 15.3852 6.36811 13.3178 5.90537 10.5727C5.87231 10.2338 5.57484 9.96264 5.24431 9.96264C4.88073 9.96264 4.58325 10.2677 4.58325 10.6405V10.7421C5.1121 13.9279 7.65717 16.4019 10.7972 16.7069V19.635H7.93254C7.54315 19.635 7.22748 19.9587 7.22748 20.358C7.22748 20.7572 7.54315 21.0809 7.93254 21.0809H14.9832C15.3726 21.0809 15.6883 20.7572 15.6883 20.358C15.6883 19.9587 15.3726 19.635 14.9832 19.635H12.1193V16.7069C15.2593 16.4019 17.8044 13.9279 18.3002 10.776C18.3002 10.7591 18.3085 10.7337 18.3167 10.7082L18.3167 10.7082L18.3167 10.7082C18.325 10.6828 18.3333 10.6574 18.3333 10.6405Z"
  226. fill="black"
  227. fill-opacity="0.9"
  228. />
  229. </svg>
  230. </span>
  231. <span
  232. class="c_voiceBtn"
  233. style="right: 70px;"
  234. v-if="!courseText && isVoice && !isTalk"
  235. @click.stop="changeVoice(false)"
  236. >
  237. <svg
  238. width="22"
  239. height="22"
  240. viewBox="0 0 22 22"
  241. fill="none"
  242. xmlns="http://www.w3.org/2000/svg"
  243. >
  244. <path
  245. fill-rule="evenodd"
  246. clip-rule="evenodd"
  247. d="M2.75 3.4375C2.75 3.0578 3.0578 2.75 3.4375 2.75H18.5625C18.9422 2.75 19.25 3.0578 19.25 3.4375V18.5625C19.25 18.9422 18.9422 19.25 18.5625 19.25H3.4375C3.0578 19.25 2.75 18.9422 2.75 18.5625V3.4375ZM4.125 4.125V17.875H17.875V4.125H4.125Z"
  248. fill="black"
  249. fill-opacity="0.9"
  250. />
  251. <path
  252. fill-rule="evenodd"
  253. clip-rule="evenodd"
  254. d="M6.875 6.875C6.875 6.4953 7.1828 6.1875 7.5625 6.1875H14.4375C14.8172 6.1875 15.125 6.4953 15.125 6.875V8.25C15.125 8.6297 14.8172 8.9375 14.4375 8.9375C14.0578 8.9375 13.75 8.6297 13.75 8.25V7.5625H11.6875V14.4375H12.375C12.7547 14.4375 13.0625 14.7453 13.0625 15.125C13.0625 15.5047 12.7547 15.8125 12.375 15.8125H9.625C9.2453 15.8125 8.9375 15.5047 8.9375 15.125C8.9375 14.7453 9.2453 14.4375 9.625 14.4375H10.3125V7.5625H8.25V8.25C8.25 8.6297 7.9422 8.9375 7.5625 8.9375C7.1828 8.9375 6.875 8.6297 6.875 8.25V6.875Z"
  255. fill="black"
  256. fill-opacity="0.9"
  257. />
  258. </svg>
  259. </span>
  260. <div
  261. :class="[
  262. 'c_pub_button_confirm',
  263. courseText ? '' : 'c_pub_button_confirmDisabled'
  264. ]"
  265. v-if="!faloading && !isVoice"
  266. @click="addContent"
  267. >
  268. 发送
  269. </div>
  270. <div
  271. :class="['c_pub_button_confirmVoice']"
  272. v-if="!faloading && isVoice && !isTalk"
  273. @click="startVoice"
  274. >
  275. <svg
  276. width="22"
  277. height="22"
  278. viewBox="0 0 22 22"
  279. fill="none"
  280. xmlns="http://www.w3.org/2000/svg"
  281. >
  282. <path
  283. fill-rule="evenodd"
  284. clip-rule="evenodd"
  285. d="M11.4583 14.0308C13.8381 14.0308 15.7551 12.0651 15.7551 9.62496V6.23588C15.7551 3.79574 13.8381 1.83008 11.4583 1.83008C9.07845 1.83008 7.16138 3.79574 7.16138 6.23588V9.62496C7.16138 12.0651 9.07845 14.0308 11.4583 14.0308ZM8.4835 6.23588C8.4835 4.54134 9.80561 3.18571 11.4583 3.18571C13.1109 3.18571 14.433 4.54134 14.433 6.23588V9.62496C14.433 11.3195 13.1109 12.6751 11.4583 12.6751C9.80561 12.6751 8.4835 11.3195 8.4835 9.62496V6.23588ZM18.3333 10.6405C18.3333 10.2677 18.0358 9.96264 17.6722 9.96264C17.3417 9.96264 17.0442 10.2338 17.0111 10.5727C16.5484 13.3178 14.2347 15.3852 11.4583 15.3852C8.68181 15.3852 6.36811 13.3178 5.90537 10.5727C5.87231 10.2338 5.57484 9.96264 5.24431 9.96264C4.88073 9.96264 4.58325 10.2677 4.58325 10.6405V10.7421C5.1121 13.9279 7.65717 16.4019 10.7972 16.7069V19.635H7.93254C7.54315 19.635 7.22748 19.9587 7.22748 20.358C7.22748 20.7572 7.54315 21.0809 7.93254 21.0809H14.9832C15.3726 21.0809 15.6883 20.7572 15.6883 20.358C15.6883 19.9587 15.3726 19.635 14.9832 19.635H12.1193V16.7069C15.2593 16.4019 17.8044 13.9279 18.3002 10.776C18.3002 10.7591 18.3085 10.7337 18.3167 10.7082L18.3167 10.7082L18.3167 10.7082C18.325 10.6828 18.3333 10.6574 18.3333 10.6405Z"
  286. fill-opacity="0.9"
  287. />
  288. </svg>
  289. </div>
  290. <div
  291. :class="['c_pub_button_StopConfirmVoice']"
  292. v-if="!faloading && isVoice && isTalk"
  293. @click="stopVoice"
  294. >
  295. <svg
  296. width="22"
  297. height="22"
  298. viewBox="0 0 22 22"
  299. fill="none"
  300. xmlns="http://www.w3.org/2000/svg"
  301. >
  302. <path
  303. d="M11 19.25C6.4625 19.25 2.75 15.5375 2.75 11C2.75 6.4625 6.4625 2.75 11 2.75C15.5375 2.75 19.25 6.4625 19.25 11C19.25 15.5375 15.5375 19.25 11 19.25ZM11 17.1875C14.4031 17.1875 17.1875 14.4031 17.1875 11C17.1875 7.59687 14.4031 4.8125 11 4.8125C7.59687 4.8125 4.8125 7.59687 4.8125 11C4.8125 14.4031 7.59687 17.1875 11 17.1875Z"
  304. fill="#EE3E3E"
  305. />
  306. <path
  307. d="M12.75 8.25H9.25C8.69772 8.25 8.25 8.69772 8.25 9.25V12.75C8.25 13.3023 8.69772 13.75 9.25 13.75H12.75C13.3023 13.75 13.75 13.3023 13.75 12.75V9.25C13.75 8.69772 13.3023 8.25 12.75 8.25Z"
  308. fill="#EE3E3E"
  309. />
  310. </svg>
  311. </div>
  312. <div v-if="!faloading && isVoice"></div>
  313. <div class="c_pub_button_confirm" v-if="faloading" @click="stopSend">
  314. 终止
  315. </div>
  316. </div>
  317. <iframe
  318. allow="camera *; microphone *;display-capture;midi;encrypted-media;"
  319. src="https://beta.cloud.cocorobo.cn/browser/public/index.html"
  320. ref="iiframe"
  321. v-show="false"
  322. ></iframe>
  323. <!-- <div class="ai_body_input">
  324. <textarea
  325. style="padding-right: 85px;"
  326. rows="3"
  327. @keyup.enter="addContent"
  328. class="binfo_input binfo_textarea"
  329. cols
  330. v-model.trim="courseText"
  331. placeholder="在此输入您想了解的内容"
  332. ></textarea>
  333. <div
  334. class="c_pub_button_confirm"
  335. v-if="!loading && courseText"
  336. @click="addContent"
  337. >
  338. 发送
  339. </div>
  340. <div class="c_pub_button_confirm" @click="promptTit" v-else>发送</div>
  341. </div> -->
  342. </div>
  343. </template>
  344. <script>
  345. import checkImg from "../../../../assets/icon/sourceFile/check.png";
  346. import checkIsImg from "../../../../assets/icon/sourceFile/check_is.png";
  347. import { v4 as uuidv4 } from "uuid";
  348. import MarkdownIt from "markdown-it";
  349. import TurndownService from "turndown";
  350. const OpenCC = require("opencc-js");
  351. let converter = OpenCC.Converter({
  352. from: "cn",
  353. to: "hk"
  354. });
  355. export default {
  356. props: {
  357. courseId: {
  358. type: String,
  359. default: ""
  360. },
  361. worksArray: {
  362. type: Array,
  363. default: () => []
  364. }
  365. },
  366. data() {
  367. return {
  368. array: [],
  369. jArray: [],
  370. courseText: "",
  371. checkImg: checkImg,
  372. checkIsImg: checkIsImg,
  373. userid: this.$route.query.userid,
  374. oid: this.$route.query.oid,
  375. org: this.$route.query.org,
  376. checkArray: [],
  377. course: [{ title: "任务1" }, { title: "任务2" }, { title: "任务3" }],
  378. partArray: [
  379. { name: "全部内容" },
  380. { name: "任务设计" },
  381. { name: "评价设计" }
  382. ],
  383. part: "全部内容",
  384. checkBool: false,
  385. loading: false,
  386. textareaHeight: 50,
  387. publicRoleList: [],
  388. roleList: [],
  389. textList: [
  390. {
  391. title: "项目式学习",
  392. dataList: [
  393. "请给我一些学生开展项目式学习可以使用的主题或问题参考,请说出学生将要解决的问题,以及学生要经历怎样的学习活动。",
  394. "请将一个关于生态保护项目的项目式学习展开描述,你需要描述学生如何解决这个问题,你需要至少写出四个活动,这些活动需要按照前后逻辑关系排列。",
  395. "请对驱动问题为“如何为学校建造一个富有特色的花坛?”的项目式学习进行子问题拆解,至少拆解为5个子问题,并根据子问题对应写出各环节的主要活动。"
  396. ]
  397. },
  398. {
  399. title: "教学评价",
  400. dataList: [
  401. "如果需要给学生的社区服务进行评价,给出评价维度和至少3个等级的表现描述。",
  402. "为6年级学生设计一份关于梧桐山研究报告的评估任务表,并给出参考的报告流程,至少包含8个步骤,并包括地图、图片和至少300个词。",
  403. "创建一个给5年级学生使用的课堂小测试,包含5道多选题,评价学生对于太阳能这个概念的理解。你需要给出题目和正确答案。"
  404. ]
  405. },
  406. {
  407. title: "教学设计",
  408. dataList: [
  409. "如果需要5年级学生感受“移步换景”的景观写作手法,你有什么合适的阅读材料推荐?你需要给出材料名称,以及材料的哪部分内容。",
  410. "设计一个针对8年级学生且关于人类迁徙主题的地理课,并在课程中设计至少1项小组活动。",
  411. "设计一个针对5年级学生的课程,课程综合科学和信息技术领域,解决生物与环境领域的生活问题,你需要给出完整的课程框架和活动。",
  412. "如果3年级的学生不能理解光合作用的实现过程,需要你帮我设计一个支持他们理解的教学活动,需要包含活动的形式、实施材料和清单。",
  413. "请基于贝叶斯定理为8年级学生出三道题目。",
  414. "如果需要八年级学生了解尼罗河流域的文化发展史,你有哪些推荐的网站或参考书籍?"
  415. ]
  416. },
  417. {
  418. title: "班级管理",
  419. dataList: [
  420. "创建一组给一年级学生使用的班级口号,要求大家注意卫生、保护环境,口号需要对仗工整,符合一年级学生的理解水平。",
  421. " 设计一套用于6年级学生的班级管理规章制度,内容需要包括学习、纪律、卫生、思想品德方面。"
  422. ]
  423. },
  424. {
  425. title: "课堂组织",
  426. dataList: [
  427. "请为“制作垃圾分类宣传单”的小组活动设计小组分工表,每个小组的成员为4-6人。",
  428. "请给5年级“校园植物图鉴”社团课程设计一份小组合作公约,需包含小组成员信息、小组项目目标、填写日期,总长度不超过300字,并且提供至少3处学生自行填写的部分。",
  429. "请用苏格拉底提问的方式,引导5年级学生拆解驱动问题:如何解决教室黑板反光的问题?其中需包含对于反光原因的分析与实验探究。"
  430. ]
  431. },
  432. {
  433. title: "教师发展",
  434. dataList: [
  435. "教师需要理解项目式学习的理论基础和基础概念,你需要生成一份阅读清单,要求内容为中文书籍或文献。",
  436. "设计一个教师进行个人学期总结的框架,需要体现在教学、教研、个人学习方面的进步。"
  437. ]
  438. },
  439. {
  440. title: "代码分析",
  441. dataList: [
  442. "这段代码实现了什么效果?",
  443. "请描述这段代码。",
  444. "根据这段代码,给我一些修改意见。"
  445. ]
  446. }
  447. ],
  448. showTextList: false,
  449. showRoleList: false,
  450. choseRoleItem: 0,
  451. choseTextItem: 0,
  452. continuous: true,
  453. showjList: false,
  454. faloading: false,
  455. fasource: null,
  456. saveUid: "",
  457. isVoice: false,
  458. isTalk: false,
  459. languageSetting: 0,
  460. username: "",
  461. options2: {
  462. 1: "选择题",
  463. // 2: "问答题",
  464. 3: "问答题",
  465. 4: "添加文档",
  466. 5: "附件",
  467. 6: "课程",
  468. 7: "评分",
  469. 8: "日期",
  470. 9: "单选题",
  471. 10: "多选题",
  472. 11: "课程",
  473. },
  474. answerArray: [],
  475. fileId: []
  476. };
  477. },
  478. watch: {
  479. courseId: {
  480. immediate: true,
  481. deep: true,
  482. handler(newValue, oldValue) {
  483. if (newValue) {
  484. this.getChatList().then(_ => {
  485. this.$nextTick(() => {
  486. console.log(this.$refs.chatDialog.scrollHeight);
  487. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  488. });
  489. });
  490. }
  491. }
  492. },
  493. worksArray :{
  494. immediate: true,
  495. deep: true,
  496. handler(newValue, oldValue) {
  497. if (newValue.length) {
  498. console.log('newValue',newValue);
  499. this.$emit("clearFileData")
  500. this.fileId = [];
  501. newValue.forEach(el=>{
  502. this.setJson(el)
  503. })
  504. // console.log("👈👉",newValue)
  505. // this.setJson(newValue)
  506. }
  507. }
  508. }
  509. },
  510. methods: {
  511. // setJson(array){
  512. // const getAnswer = (j) => {
  513. // switch (j.type) {
  514. // case 1:
  515. // return j.json.array
  516. // .filter((_, idx) => j.json.answer2.includes(idx))
  517. // .map(item => `${item.img}${item.option}`)
  518. // .join(',');
  519. // case 3:
  520. // case 6:
  521. // case 7:
  522. // case 8:
  523. // case 11:
  524. // return j.json.answer2;
  525. // case 5:
  526. // if (!Array.isArray(j.json.file) || j.json.file.length === 0) {
  527. // return '无附件';
  528. // }
  529. // return j.json.file.map(file => `${file.name}(${file.url})`).join(',');
  530. // default:
  531. // return '';
  532. // }
  533. // };
  534. // this.answerArray = array.map(i => ({
  535. // "用户名": i.name,
  536. // "提交时间": i.time,
  537. // "表单内容": i.array.map((j, index) => ({
  538. // "序号": index + 1,
  539. // "题目": j.json.title,
  540. // "题目类型": this.options2[j.type],
  541. // "答案": getAnswer(j)
  542. // }))
  543. // }))
  544. // console.log(this.answerArray);
  545. // // 将JSON对象转换为字符串
  546. // const jsonString = JSON.stringify(this.answerArray, null, 2);
  547. // // 创建Blob对象
  548. // const blob = new Blob([jsonString], { type: "application/json" });
  549. // blob.lastModifiedDate = new Date();
  550. // blob.name = `表单数据.json`;
  551. // // 如果仍需要上传文件,可以保留这行
  552. // return this.uploadFile(blob);
  553. // },
  554. setJson(obj){
  555. let array = obj.worksArray
  556. let name = obj.name
  557. console.log(obj)
  558. console.log(array)
  559. const getAnswer = (j) => {
  560. if (j.type === 1) {
  561. return j.json.array
  562. .filter((_, idx) => j.json.answer2.includes(idx))
  563. .map(item => `${item.img}${item.option}`)
  564. .join(',');
  565. } else if (j.type === 3 || j.type === 6 || j.type === 7 || j.type === 8 || j.type === 11) {
  566. console.log(j.json);
  567. return typeof j.json.answer2 === 'string' ? j.json.answer2.replace(/\n/g, ' ') : j.json.answer2;
  568. } else if (j.type === 5) {
  569. if (!Array.isArray(j.json.file) || j.json.file.length === 0) {
  570. return '无附件';
  571. }
  572. return j.json.file.map(file => `${file.name}(${file.url})`).join(',');
  573. } else {
  574. return '';
  575. }
  576. };
  577. // 获取所有题目类型和题目
  578. const questions = array[0].array.map((j, index) => ({
  579. "序号": index + 1,
  580. "题目类型": this.options2[j.type],
  581. "题目": j.json.title
  582. }));
  583. console.log(questions)
  584. // 构建CSV内容
  585. let csvContent = "用户名 | 提交时间 | " + questions.map(q => `${q.序号}-${q.题目类型}-${q.题目}`).join(' | ') + "\n";
  586. // 添加每个用户的答案
  587. array.forEach(i => {
  588. let row = [i.name, i.time];
  589. i.array.forEach(j => {
  590. row.push(getAnswer(j));
  591. });
  592. csvContent += row.join(' | ') + "\n";
  593. });
  594. // 创建Blob对象
  595. const blob = new Blob([csvContent], { type: "text/plain;charset=utf-8" });
  596. blob.lastModifiedDate = new Date();
  597. blob.name = `${name}_表单数据.txt`;
  598. // 如果仍需要上传文件,可以保留这行
  599. return this.uploadFile({file:blob,name:name});
  600. },
  601. uploadFile({file,name}) {
  602. var credentials = {
  603. accessKeyId: "AKIATLPEDU37QV5CHLMH",
  604. secretAccessKey: "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"
  605. }; //秘钥形式的登录上传
  606. window.AWS.config.update(credentials);
  607. window.AWS.config.region = "cn-northwest-1"; //设置区域
  608. var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
  609. var _this = this;
  610. if (file) {
  611. // this.loading = true;
  612. var params = {
  613. Key:
  614. file.name.split(".")[0] +
  615. new Date().getTime() +
  616. "." +
  617. file.name.split(".")[file.name.split(".").length - 1],
  618. ContentType: file.type,
  619. Body: file,
  620. "Access-Control-Allow-Credentials": "*",
  621. ACL: "public-read"
  622. }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
  623. var options = {
  624. partSize: 2048 * 1024 * 1024,
  625. queueSize: 2,
  626. leavePartsOnError: true
  627. };
  628. bucket
  629. .upload(params, options)
  630. .on("httpUploadProgress", function(evt) {
  631. //这里可以写进度条
  632. _this.progressData.value = parseInt((evt.loaded * 100) / evt.total);
  633. // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
  634. })
  635. .send(function(err, data) {
  636. if (err) {
  637. _this.$message.error("上传失败");
  638. } else {
  639. console.log(data.Location);
  640. _this.ajax
  641. .put("https://gpt4.cocorobo.cn/upload_file_knowledge", {
  642. url: data.Location
  643. })
  644. .then(res => {
  645. let _data = res.data.FunctionResponse;
  646. if (_data.result && _data.result.id) {
  647. _this.fileId.push(_data.result.id);
  648. _this.$emit("pushFileData",{fileId:_data.result.id,name:name,url:data.Location})
  649. } else {
  650. console.error("获取fileId失败");
  651. }
  652. })
  653. .catch(e => {
  654. console.log(e);
  655. console.error("获取fileId失败");
  656. });
  657. // }
  658. // console.log(data.Location)
  659. }
  660. });
  661. }
  662. },
  663. getLang() {
  664. let lang = "";
  665. if (this.languageSetting == 0) {
  666. lang = "Chinese.";
  667. } else if (this.languageSetting == 1) {
  668. lang = "Traditional Chinese.";
  669. } else if (this.languageSetting == 2) {
  670. lang = "English.";
  671. }
  672. return lang;
  673. },
  674. promptTit() {
  675. if (!this.loading && !this.courseText) {
  676. this.$message({
  677. message: "请输入您想要了解的内容",
  678. type: "warning"
  679. });
  680. } else {
  681. this.$message({
  682. message: "请回答完毕后再次发送",
  683. type: "warning"
  684. });
  685. }
  686. },
  687. addContent() {
  688. if (this.courseText.trim().length == 0)
  689. return this.$message.error("请输入内容");
  690. let message = this.courseText;
  691. if (this.courseText) {
  692. let msg = ``;
  693. if (this.answerArray.length) {
  694. // msg += `
  695. // ## 表单资料
  696. // ${JSON.stringify(this.answerArray)}
  697. // `;
  698. // msg += `
  699. // ## 要求
  700. // 根据<参考资料>中的内容实现以下要求:${this.courseText}
  701. // `;
  702. msg += `## 要求
  703. 根据上传文件中的内容实现以下要求:${this.courseText}`;
  704. message = msg;
  705. }
  706. // 这里处理@的角色
  707. let _atRoleList = [];
  708. let _roleList = [...this.roleList, ...this.publicRoleList];
  709. _roleList.forEach(i => {
  710. if (message.indexOf(`@${i.assistantName}`) != -1) {
  711. _atRoleList.push(i);
  712. }
  713. });
  714. this.faloading = true;
  715. if (_atRoleList.length > 0) {
  716. //有@角色
  717. let _replaceText = `Role: 你是数据检索大师,可以利用file_search的方式完整的去分析文件内容 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.\n${message}`;
  718. let _htmlText = message;
  719. _atRoleList.forEach(_i => {
  720. _replaceText = _replaceText.replaceAll(`@${_i.assistantName}`, ``);
  721. _htmlText = _htmlText.replaceAll(
  722. `@${_i.assistantName}`,
  723. `<span class='aite-name'>@${_i.assistantName}</span>`
  724. );
  725. });
  726. _atRoleList.forEach((_item, _index) => {
  727. const _uid = uuidv4();
  728. if (_index == 0) {
  729. this.array.push({
  730. loading: true,
  731. role: "user",
  732. content: _htmlText,
  733. uid: _uid,
  734. AI: "AI",
  735. aiContent: "",
  736. oldContent: "",
  737. isShowSynchronization: false,
  738. filename: _item.assistantName,
  739. index: this.array.length,
  740. is_mind_map: false,
  741. fileid: _item.headUrl,
  742. createtime: new Date().toLocaleString().replaceAll("/", "-")
  743. });
  744. } else {
  745. this.array.push({
  746. loading: true,
  747. role: "user",
  748. content: "",
  749. uid: _uid,
  750. AI: "AI",
  751. aiContent: "",
  752. oldContent: "",
  753. isShowSynchronization: false,
  754. filename: _item.assistantName,
  755. index: this.array.length,
  756. is_mind_map: false,
  757. fileid: _item.headUrl,
  758. createtime: new Date().toLocaleString().replaceAll("/", "-")
  759. });
  760. }
  761. this.$nextTick(() => {
  762. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  763. });
  764. let params = {
  765. assistant_id: _item.assistant_id,
  766. userId: this.userid,
  767. message: _replaceText,
  768. session_name: `${this.courseId}-${this.userid}-test`,
  769. uid: _uid,
  770. file_ids: this.fileId ? this.fileId : [],
  771. // model: "gpt-4o-mini"
  772. model: "qwen-plus"
  773. };
  774. this.ajax
  775. .post("https://gpt4.cocorobo.cn/ai_agent_park_chat_new", params)
  776. .then(res => {
  777. if (
  778. converter(res.data.FunctionResponse.result) ==
  779. converter("发送成功")
  780. ) {
  781. } else {
  782. this.$message.warning(res.data.FunctionResponse.result);
  783. }
  784. })
  785. .catch(err => {
  786. console.log(err);
  787. });
  788. this.getAtAuContent(_uid);
  789. this.saveUid = _uid;
  790. });
  791. this.courseText = "";
  792. } else {
  793. let _uuid = uuidv4();
  794. this.array.push({
  795. role: "user",
  796. content: `${this.courseText}`,
  797. uid: _uuid,
  798. AI: "AI",
  799. aiContent: "",
  800. oldContent: "",
  801. isShowSynchronization: false,
  802. filename: "",
  803. index: this.array.length,
  804. is_mind_map: false,
  805. createtime: new Date().toLocaleString().replaceAll("/", "-"),
  806. loading: true
  807. });
  808. // let history = [];
  809. // if (this.continuous) {
  810. // this.array.forEach((i, index) => {
  811. // if (i.content) history.push({ role: "user", content: index == this.array.length - 1 ? message : i.content });
  812. // if (i.aiContent)
  813. // history.push({ role: "assistant", content: i.aiContent });
  814. // });
  815. // } else {
  816. // history.push({ role: "user", content: message });
  817. // }
  818. // history = history.filter(
  819. // i =>
  820. // i.content !=
  821. // "您好,我是您的助手小可"
  822. // );
  823. // history = history.map(i => ({
  824. // role: i.role,
  825. // content: `${i.content}`
  826. // }));
  827. // this.$nextTick(() => {
  828. // this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  829. // });
  830. // let params = JSON.stringify({
  831. // // model: "gpt-3.5-turbo",
  832. // // model: "gpt-4o-mini",
  833. // model: "qwen-plus",
  834. // temperature: 0,
  835. // max_tokens: 4096,
  836. // top_p: 1,
  837. // frequency_penalty: 0,
  838. // presence_penalty: 0,
  839. // messages: history,
  840. // uid: _uuid,
  841. // mind_map_question: ""
  842. // });
  843. // this.courseText = "";
  844. // this.ajax
  845. // .post("https://gpt4.cocorobo.cn/chat", params)
  846. // .then(res => {
  847. // if (
  848. // converter(res.data.FunctionResponse.result) ==
  849. // converter("发送成功")
  850. // ) {
  851. // } else {
  852. // this.$message.warning(res.data.FunctionResponse.result);
  853. // }
  854. // })
  855. // .catch(e => {
  856. // console.log(e);
  857. // });
  858. // this.getAiContent(_uuid);\
  859. let params = {
  860. assistant_id: 'cd72354e-7be5-11ef-a263-12e77c4cb76b',
  861. userId: this.userid,
  862. message: `Role: 你是数据检索大师,可以利用file_search的方式完整的去分析文件内容 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.\n${message}`,
  863. session_name: `${this.courseId}-${this.userid}-test`,
  864. uid: _uuid,
  865. file_ids: this.fileId ? this.fileId : [],
  866. model: "gpt-4o-mini"
  867. };
  868. this.$nextTick(() => {
  869. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  870. });
  871. this.courseText = "";
  872. this.ajax
  873. .post("https://gpt4.cocorobo.cn/ai_agent_park_chat_new", params)
  874. .then(res => {
  875. if (
  876. converter(res.data.FunctionResponse.result) ==
  877. converter("发送成功")
  878. ) {
  879. } else {
  880. this.$message.warning(res.data.FunctionResponse.result);
  881. }
  882. })
  883. .catch(err => {
  884. console.log(err);
  885. });
  886. this.getAtAuContent(_uuid);
  887. this.saveUid = _uuid;
  888. }
  889. }
  890. },
  891. getAiContent(_uid) {
  892. this.fasource = new EventSource(
  893. `https://gpt4.cocorobo.cn/stream/${_uid}`
  894. ); //http://gpt4.cocorobo.cn:8011/stream/ https://gpt4.cocorobo.cn/stream/
  895. let _allText = "";
  896. let _mdText = "";
  897. const md = new MarkdownIt();
  898. this.fasource.onmessage = _e => {
  899. if (_e.data.replace("'", "").replace("'", "") == "[DONE]") {
  900. //对话已经完成
  901. _mdText = _mdText.replace("_", "");
  902. this.fasource.close();
  903. this.fasource = null;
  904. this.$nextTick(() => {
  905. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  906. });
  907. this.array.find(i => i.uid == _uid).aiContent = _mdText;
  908. this.array.find(i => i.uid == _uid).isalltext = true;
  909. this.array.find(i => i.uid == _uid).isShowSynchronization = true;
  910. this.array.find(i => i.uid == _uid).loading = false;
  911. // 这里保存对话
  912. if (this.courseId) {
  913. this.insertChat(_uid);
  914. }
  915. return;
  916. } else {
  917. //对话还在继续
  918. let _text = "";
  919. _text = _e.data.replaceAll("'", "");
  920. if (_allText == "") {
  921. _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
  922. } else {
  923. _allText += _text;
  924. }
  925. _mdText = _allText + "_";
  926. _mdText = _mdText.replace(/\\n/g, "\n");
  927. _mdText = _mdText.replace(/\\/g, "");
  928. if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
  929. //转化返回的回复流数据
  930. _mdText = md.render(_mdText);
  931. this.array.find(i => i.uid == _uid).aiContent = _mdText;
  932. this.array.find(i => i.uid == _uid).loading = false;
  933. this.$nextTick(() => {
  934. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  935. });
  936. // 处理流数据
  937. }
  938. };
  939. },
  940. getAtAuContent(_uid) {
  941. this.fasource = new EventSource(
  942. `https://gpt4.cocorobo.cn/question/${_uid}`
  943. ); //http://gpt4.cocorobo.cn:8011/question/ https://gpt4.cocorobo.cn/question/
  944. let _allText = "";
  945. let _mdText = "";
  946. const md = new MarkdownIt();
  947. this.fasource.onmessage = _e => {
  948. let _eData = JSON.parse(_e.data);
  949. if (_eData.content.replace("'", "").replace("'", "") == "[DONE]") {
  950. let _result = [];
  951. if ("result" in _eData) {
  952. _result = _eData.result;
  953. for (let i = 0; i < _result.length; i++) {
  954. _mdText = _mdText.replace(_result[i].text, _result[i].fileName);
  955. }
  956. }
  957. _mdText = _mdText.replace("_", "");
  958. this.array.find(i => i.uid == _uid).aiContent = _mdText;
  959. this.array.find(i => i.uid == _uid).isalltext = true;
  960. this.array.find(i => i.uid == _uid).isShowSynchronization = true;
  961. this.array.find(i => i.uid == _uid).loading = false;
  962. this.$nextTick(() => {
  963. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  964. });
  965. this.fasource.close();
  966. this.fasource = null;
  967. if (this.courseId) {
  968. this.insertChat(_uid);
  969. }
  970. } else {
  971. let _text = _eData.content.replace("'", "").replace("'", "");
  972. if (_allText == "") {
  973. _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
  974. } else {
  975. _allText += _text;
  976. }
  977. _mdText = _allText + "_";
  978. _mdText = _mdText.replace(/\\n/g, "\n");
  979. _mdText = _mdText.replace(/\\/g, "");
  980. if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
  981. //转化返回的回复流数据
  982. _mdText = md.render(_mdText);
  983. this.array.find(i => i.uid == _uid).aiContent = _mdText;
  984. this.array.find(i => i.uid == _uid).loading = false;
  985. this.$nextTick(() => {
  986. this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  987. });
  988. // 处理流数据
  989. }
  990. };
  991. },
  992. async getUserName() {
  993. let params = { uid: this.userid };
  994. try {
  995. let res = await this.ajax.get(this.$store.state.api + "getUser", params);
  996. this.username = res.data[0][0].name;
  997. } catch (err) {
  998. console.error(err);
  999. }
  1000. },
  1001. //保存消息
  1002. async insertChat(_uid) {
  1003. let _data = this.array.find(i => i.uid == _uid);
  1004. this.saveUid = ''
  1005. this.faloading = false
  1006. if(!this.username){
  1007. await this.getUserName()
  1008. }
  1009. if (!_data) return;
  1010. let params = {
  1011. userId: this.userid,
  1012. userName: this.username,
  1013. groupId: "602def61-005d-11ee-91d8-005056b8q12w",
  1014. answer: _data.aiContent,
  1015. problem: _data.content,
  1016. file_id: _data.fileid ? _data.fileid : "",
  1017. alltext: _data.aiContent,
  1018. type: "chat",
  1019. filename: _data.filename,
  1020. session_name: `${this.courseId}-${this.userid}-test` //这是对话记录位置
  1021. };
  1022. this.ajax
  1023. .post("https://gpt4.cocorobo.cn/insert_chat", params)
  1024. .then(res => {});
  1025. },
  1026. // 获取对应的聊天记录
  1027. getChatList() {
  1028. return new Promise((resolve, reject) => {
  1029. if (this.loading) return;
  1030. this.array = [];
  1031. this.loading = true;
  1032. let params = {
  1033. userid: this.userid,
  1034. groupid: "602def61-005d-11ee-91d8-005056b8q12w",
  1035. // session_name:``
  1036. session_name: `${this.courseId}-${this.userid}-test`
  1037. };
  1038. this.ajax
  1039. .post("https://gpt4.cocorobo.cn/get_agent_park_chat", params)
  1040. .then(res => {
  1041. let _data = JSON.parse(res.data.FunctionResponse);
  1042. if (_data.length > 0) {
  1043. let _chatList = [];
  1044. for (let i = 0; i < _data.length; i++) {
  1045. _chatList.push({
  1046. loading: false,
  1047. role: "user",
  1048. content: _data[i].problem,
  1049. uid: _data[i].id,
  1050. AI: "AI",
  1051. aiContent: _data[i].answer,
  1052. oldContent: _data[i].answer,
  1053. isShowSynchronization: false,
  1054. filename: _data[i].filename,
  1055. index: i,
  1056. is_mind_map: false,
  1057. fileid: _data[i].fileid,
  1058. createtime: _data[i].createtime
  1059. });
  1060. }
  1061. this.array = _chatList;
  1062. this.loading = false;
  1063. } else {
  1064. let _uid = uuidv4();
  1065. let _chatList = [];
  1066. _chatList.push({
  1067. loading: false,
  1068. role: "",
  1069. content: "",
  1070. uid: _uid,
  1071. AI: "AI",
  1072. aiContent:
  1073. "您好,我是您的助手小可",
  1074. oldContent:
  1075. "您好,我是您的助手小可",
  1076. isShowSynchronization: false,
  1077. filename: "",
  1078. index: 0,
  1079. is_mind_map: false,
  1080. fileid: ""
  1081. });
  1082. this.array = _chatList;
  1083. if (this.courseId) {
  1084. this.insertChat(_uid);
  1085. }
  1086. //没有对话记录
  1087. this.loading = false;
  1088. }
  1089. resolve();
  1090. })
  1091. .catch(err => {
  1092. console.log(err);
  1093. this.$message.error("获取对话记录失败");
  1094. this.loading = false;
  1095. resolve();
  1096. });
  1097. });
  1098. },
  1099. addTask(index) {
  1100. if (this.checkArray.indexOf(index) !== -1) {
  1101. this.checkArray.splice(this.checkArray.indexOf(index), 1);
  1102. } else {
  1103. this.checkArray.push(index);
  1104. }
  1105. console.log(index);
  1106. },
  1107. addAllTask() {
  1108. if (this.checkArray.length === this.course.length) {
  1109. this.checkArray = [];
  1110. } else {
  1111. this.checkArray = [];
  1112. this.course.forEach((item, index) => {
  1113. this.checkArray.push(index);
  1114. });
  1115. }
  1116. },
  1117. checkPart(name) {
  1118. this.part = name;
  1119. },
  1120. inputChange() {
  1121. if (this.courseText.at(-1) == "@") {
  1122. // this.showRoleList = true;
  1123. }
  1124. if (this.courseText.at(-1) == "/") {
  1125. console.log("哇卡ka2");
  1126. }
  1127. this.$nextTick(() => {
  1128. this.$refs.textareaRef.style.height = "35px";
  1129. this.$refs.textareaRef.style.height =
  1130. this.$refs.textareaRef.scrollHeight + "px";
  1131. this.textareaHeight = this.$refs.textareaRef.style.height;
  1132. });
  1133. },
  1134. textareaKeydown(_e) {
  1135. if (this.showRoleList && this.choseRoleList.length > 0) {
  1136. console.log(_e.keyCode);
  1137. switch (_e.keyCode) {
  1138. case 38: //小键盘上
  1139. _e.preventDefault();
  1140. if (this.choseRoleItem == 0) return;
  1141. this.choseRoleItem--;
  1142. // 修改滚动条高度
  1143. this.$refs.roleListRef.scrollTo({
  1144. top:
  1145. this.$refs[`roleItem${this.choseRoleItem}Ref`][0].offsetTop -
  1146. 10,
  1147. behavior: "smooth"
  1148. });
  1149. // this.$refs.roleListRef.scrollTop = this.choseRoleItem * 107;
  1150. break;
  1151. case 40: //小键盘下
  1152. _e.preventDefault();
  1153. if (this.choseRoleItem == this.choseRoleList.length - 1) return;
  1154. this.choseRoleItem++;
  1155. this.$refs.roleListRef.scrollTo({
  1156. top:
  1157. this.$refs[`roleItem${this.choseRoleItem}Ref`][0].offsetTop -
  1158. 10,
  1159. behavior: "smooth"
  1160. });
  1161. // this.$refs.roleListRef.scrollTop = this.choseRoleItem * 107;
  1162. break;
  1163. case 13: //回车
  1164. _e.preventDefault();
  1165. this.choseRole(this.choseRoleList[this.choseRoleItem]);
  1166. break;
  1167. }
  1168. } else if (_e.key === "Enter") {
  1169. _e.preventDefault();
  1170. if (_e.shiftKey) {
  1171. this.courseText += "\n";
  1172. } else {
  1173. this.addContent();
  1174. }
  1175. }
  1176. },
  1177. clear() {
  1178. this.$confirm("确定清空聊天记录吗?", "提示", {
  1179. confirmButtonText: "确定",
  1180. cancelButtonText: "取消",
  1181. type: "warning"
  1182. })
  1183. .then(_ => {
  1184. this.loading = true;
  1185. let params = {
  1186. user_id: this.userid,
  1187. id: "602def61-005d-11ee-91d8-005056b8q12w",
  1188. session_name: `${this.courseId}-${this.userid}-test`
  1189. };
  1190. this.ajax
  1191. .post("https://gpt4.cocorobo.cn/delete_park_session", params)
  1192. .then(res => {
  1193. this.array = [];
  1194. this.$message.success("清除聊天记录成功");
  1195. this.loading = false;
  1196. })
  1197. .catch(err => {
  1198. this.loading = false;
  1199. this.$message.error("清除聊天记录失败");
  1200. });
  1201. })
  1202. .catch(_ => {});
  1203. },
  1204. getRoleList() {
  1205. this.roleList = [];
  1206. let params = {
  1207. userId: this.userid
  1208. };
  1209. this.ajax
  1210. .post("https://gpt4.cocorobo.cn/get_ai_agent_assistant_list", params)
  1211. .then(res => {
  1212. let _data = res.data.FunctionResponse.result;
  1213. if (_data) {
  1214. this.roleList = JSON.parse(_data);
  1215. }
  1216. })
  1217. .catch(e => {
  1218. console.log(e);
  1219. // this.$message.error("获取角色列表失败");
  1220. this.roleList = [];
  1221. });
  1222. },
  1223. getPublicRoleList() {
  1224. this.publicRoleList = [];
  1225. let params = {
  1226. userId: this.userid,
  1227. organizeid: this.oid
  1228. };
  1229. this.ajax
  1230. .post(
  1231. "https://gpt4.cocorobo.cn/get_ai_agent_assistant_share_list",
  1232. params
  1233. )
  1234. .then(res => {
  1235. let _data = res.data.FunctionResponse.result;
  1236. if (_data) {
  1237. this.publicRoleList = JSON.parse(_data);
  1238. }
  1239. })
  1240. .catch(e => {
  1241. this.publicRoleList = [];
  1242. console.log(e);
  1243. // console.log("获取公共角色失败", e);
  1244. });
  1245. },
  1246. choseRole(item) {
  1247. let _lastAtIndex = this.courseText.lastIndexOf("@");
  1248. this.courseText = `${this.courseText.slice(0, _lastAtIndex)}@${
  1249. item.assistantName
  1250. } `;
  1251. this.$refs.textareaRef.focus();
  1252. this.showRoleList = false;
  1253. },
  1254. onCopy(content) {
  1255. const turndownService = new TurndownService();
  1256. // 添加自定义规则来处理表格
  1257. turndownService.addRule("table", {
  1258. filter: "table",
  1259. replacement: (content, node) => {
  1260. const rows = node.querySelectorAll("tr");
  1261. let markdown = "";
  1262. rows.forEach(row => {
  1263. const cells = row.querySelectorAll("th, td");
  1264. const rowMarkdown = Array.from(cells)
  1265. .map(cell => cell.textContent)
  1266. .join(" | ");
  1267. markdown += `| ${rowMarkdown} |\n`;
  1268. if (cells && cells.length && cells[0].tagName == "TH") {
  1269. let a = Array.from(cells)
  1270. .map(cell => "")
  1271. .join(" --- |");
  1272. markdown += `| --- |${a}\n`;
  1273. }
  1274. });
  1275. // 添加分隔行
  1276. // markdown = markdown.replace(/^/, '| --- |\n');
  1277. return markdown;
  1278. }
  1279. });
  1280. // 创建临时textarea元素
  1281. const tempInput = document.createElement("textarea");
  1282. tempInput.value = turndownService.turndown(content); // 设置要复制的内容
  1283. // 隐藏元素
  1284. tempInput.style.position = "absolute";
  1285. tempInput.style.left = "-9999px";
  1286. // 将元素添加到DOM中
  1287. document.body.appendChild(tempInput);
  1288. // 选中元素内容
  1289. tempInput.select();
  1290. // 执行复制操作
  1291. document.execCommand("copy");
  1292. // 移除临时元素
  1293. document.body.removeChild(tempInput);
  1294. this.$message({
  1295. message: "复制成功",
  1296. type: "success"
  1297. });
  1298. },
  1299. stopSend() {
  1300. if (this.fasource) {
  1301. this.fasource.close();
  1302. if (this.array[this.array.length - 1].content == "wanSearch") {
  1303. this.array.pop();
  1304. }
  1305. this.array.find(i => i.uid == this.saveUid).loading = false;
  1306. this.faloading = false;
  1307. this.fasource = null;
  1308. this.insertChat(this.saveUid);
  1309. }
  1310. },
  1311. changeVoice(flag) {
  1312. this.isVoice = flag;
  1313. },
  1314. startVoice() {
  1315. let iiframe = this.$refs["iiframe"];
  1316. iiframe.contentWindow.window.document.getElementById(
  1317. "languageOptions"
  1318. ).selectedIndex = 2; //普通话
  1319. iiframe.contentWindow.testdoContinuousPronunciationAssessment();
  1320. this.isTalk = true;
  1321. iiframe.contentWindow.onRecognizedResult = e => {
  1322. let _msg = e.privText;
  1323. console.log(_msg);
  1324. if (_msg) this.courseText += _msg;
  1325. };
  1326. },
  1327. stopVoice(){
  1328. try {
  1329. if (!this.isTalk) return this.$message.info("请先开始录音");
  1330. let iiframe = this.$refs["iiframe"];
  1331. iiframe.contentWindow.window.document
  1332. .getElementById("scenarioStopButton")
  1333. .click();
  1334. iiframe.contentWindow.onSessionStopped = (s, e) => {
  1335. this.isTalk = false;
  1336. if (this.courseText) {
  1337. this.addContent();
  1338. }
  1339. };
  1340. } catch (error) {
  1341. console.log(error);
  1342. this.isTalk = false;
  1343. if (this.courseText) {
  1344. this.addContent();
  1345. }
  1346. }
  1347. }
  1348. },
  1349. computed: {
  1350. pan() {
  1351. return content => {
  1352. try {
  1353. return JSON.parse(content);
  1354. } catch (error) {
  1355. return [];
  1356. }
  1357. };
  1358. },
  1359. courseTextLength() {
  1360. return this.courseText.length;
  1361. },
  1362. taskName() {
  1363. let task = "";
  1364. if (this.checkArray.length) {
  1365. task = "任务";
  1366. this.checkArray = this.checkArray.sort((a, b) => a - b);
  1367. let a = JSON.parse(JSON.stringify(this.checkArray));
  1368. for (let index = 0; index < a.length; index++) {
  1369. a[index]++;
  1370. }
  1371. task += a.join("/");
  1372. }
  1373. return task + " " + this.part;
  1374. },
  1375. choseRoleList() {
  1376. let result = [...this.roleList, ...this.publicRoleList];
  1377. const _index = this.courseText.lastIndexOf("@");
  1378. if (_index !== -1) {
  1379. let roleName = this.courseText.substring(_index + 1);
  1380. result = result.filter(i => i.assistantName.indexOf(roleName) != -1);
  1381. } else {
  1382. return [];
  1383. }
  1384. this.choseRoleItem = 0;
  1385. return result;
  1386. }
  1387. },
  1388. mounted() {
  1389. // this.getChatList().then(_ => {
  1390. // this.$nextTick(() => {
  1391. // console.log(this.$refs.chatDialog.scrollHeight);
  1392. // this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
  1393. // });
  1394. // });
  1395. // if(this.worksArray.length){
  1396. // this.worksArray.forEach(el=>{
  1397. // this.setJson(el)
  1398. // })
  1399. // }
  1400. this.getRoleList();
  1401. this.getPublicRoleList();
  1402. }
  1403. };
  1404. </script>
  1405. <style scoped>
  1406. .ai_body {
  1407. /* height: calc(100% - 158px - 46px);
  1408. width: 500px; */
  1409. height: 100%;
  1410. width: 100%;
  1411. /* margin: 0 auto; */
  1412. display: flex;
  1413. flex-direction: column;
  1414. /* position: fixed; */
  1415. /* z-index: 999; */
  1416. background: #fff;
  1417. /* right: 30px; */
  1418. /* bottom: 10px; */
  1419. padding: 10px 20px;
  1420. box-sizing: border-box;
  1421. /* box-shadow: 0 0 5px 2px #00000045;
  1422. border-radius: 5px; */
  1423. }
  1424. .binfo_input {
  1425. width: 100%;
  1426. margin: 0;
  1427. padding: 12px 14px;
  1428. display: block;
  1429. min-width: 0;
  1430. outline: none;
  1431. box-sizing: border-box;
  1432. background: none;
  1433. border: none;
  1434. border-radius: 4px;
  1435. background: #fff;
  1436. font-size: 14px;
  1437. resize: none;
  1438. font-family: "Microsoft YaHei";
  1439. min-height: 48px;
  1440. /* border: 1px solid #3682fc00; */
  1441. border: 1.5px solid #cad1dc;
  1442. }
  1443. .binfo_textarea {
  1444. border: 1.5px solid #cad1dc;
  1445. font-size: 14px;
  1446. resize: none;
  1447. /* background: #f6f6f6; */
  1448. font-family: "Microsoft YaHei";
  1449. }
  1450. .binfo_textarea::-webkit-scrollbar {
  1451. /*滚动条整体样式*/
  1452. width: 6px;
  1453. /*高宽分别对应横竖滚动条的尺寸*/
  1454. height: 6px;
  1455. }
  1456. /*定义滚动条轨道 内阴影+圆角*/
  1457. .binfo_textarea::-webkit-scrollbar-track {
  1458. border-radius: 10px;
  1459. background-color: rgba(0, 0, 0, 0.1);
  1460. }
  1461. /*定义滑块 内阴影+圆角*/
  1462. .binfo_textarea::-webkit-scrollbar-thumb {
  1463. border-radius: 10px;
  1464. -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
  1465. background-color: rgba(0, 0, 0, 0.1);
  1466. }
  1467. .binfo_input:focus-visible {
  1468. border: 1.5px solid #3681fc !important;
  1469. }
  1470. .ai_body_input {
  1471. position: relative;
  1472. display: flex;
  1473. margin-top: auto;
  1474. width: 100%;
  1475. /* height: auto; */
  1476. /* max-height: 80vh; */
  1477. justify-content: space-between;
  1478. align-items: flex-end;
  1479. border-radius: 10px;
  1480. border: 1.5px solid #3681fc !important;
  1481. /* padding: 10px;
  1482. padding-top: 20px; */
  1483. /* overflow: auto; */
  1484. }
  1485. .ai_b_i_btnArea {
  1486. width: calc(100% - 10px);
  1487. position: absolute;
  1488. bottom: calc(100% + 5px);
  1489. height: 30px;
  1490. display: flex;
  1491. /* justify-content: space-between; */
  1492. }
  1493. .ai_b_i_btnArea > div {
  1494. display: flex;
  1495. align-items: center;
  1496. }
  1497. .ai_b_i_btnArea > div > span {
  1498. margin-left: 5px;
  1499. cursor: pointer;
  1500. }
  1501. .ai_b_i_btnArea > .clear + .clear {
  1502. margin-left: 10px;
  1503. }
  1504. .ai_b_i_btnArea > .clear {
  1505. box-sizing: border-box;
  1506. padding: 5px 10px;
  1507. box-sizing: border-box;
  1508. cursor: pointer;
  1509. border: solid 1px #3781fb;
  1510. border-radius: 15px;
  1511. display: flex;
  1512. font-size: 15px;
  1513. align-items: center;
  1514. justify-content: center;
  1515. background-color: #fff;
  1516. }
  1517. .ai_b_i_btnArea > .clear > svg {
  1518. width: 17px;
  1519. height: 17px;
  1520. margin-right: 5px;
  1521. fill: black;
  1522. }
  1523. .ai_b_i_btnArea > .clear:hover {
  1524. background-color: #ebf4fe;
  1525. color: #409eff;
  1526. }
  1527. .ai_b_i_btnArea > .clear:hover > svg {
  1528. fill: #409eff;
  1529. }
  1530. .ai_b_i_textListBox {
  1531. width: 100%;
  1532. height: 300px;
  1533. background-color: #fff;
  1534. position: absolute;
  1535. bottom: calc(100% + 5px);
  1536. box-sizing: border-box;
  1537. padding: 10px;
  1538. overflow: auto;
  1539. border-radius: 8px;
  1540. border: 1px solid #e7e7e7;
  1541. box-shadow: 0 4px 10px 0 rgba(29, 57, 131, 0.08),
  1542. 1px 1px 20px 4px rgba(29, 57, 131, 0.05);
  1543. display: flex;
  1544. }
  1545. .ai_b_i_tlb_left {
  1546. width: 60px;
  1547. height: 100%;
  1548. background-color: red;
  1549. }
  1550. .ai_b_i_tlb_right {
  1551. flex: 1;
  1552. height: 100%;
  1553. background-color: yellow;
  1554. }
  1555. .ai_b_i_roleListBox {
  1556. width: 100%;
  1557. height: 300px;
  1558. background-color: #fff;
  1559. position: absolute;
  1560. bottom: calc(100% + 5px);
  1561. box-sizing: border-box;
  1562. padding: 10px;
  1563. overflow: auto;
  1564. border-radius: 8px;
  1565. border: 1px solid #e7e7e7;
  1566. box-shadow: 0 4px 10px 0 rgba(29, 57, 131, 0.08),
  1567. 1px 1px 20px 4px rgba(29, 57, 131, 0.05);
  1568. }
  1569. .ai_b_i_rlb_item {
  1570. width: calc(100% - 20px);
  1571. height: auto;
  1572. padding: 10px;
  1573. background-color: #f3f7fd;
  1574. margin-bottom: 20px;
  1575. border-radius: 8px;
  1576. display: flex;
  1577. flex-direction: column;
  1578. justify-content: center;
  1579. transition: 0.3s;
  1580. cursor: pointer;
  1581. }
  1582. .ai_b_i_rlb_itemActive {
  1583. background-color: #d1d5db !important;
  1584. }
  1585. /* .ai_b_i_rlb_item:hover{
  1586. background-color: #d1d5db;
  1587. } */
  1588. .ai_b_i_rlb_itemTop {
  1589. display: flex;
  1590. }
  1591. .ai_b_i_rlb_itemTop > img {
  1592. width: 40px;
  1593. height: 40px;
  1594. margin-right: 10px;
  1595. border-radius: 100%;
  1596. overflow: hidden;
  1597. }
  1598. .ai_b_i_rlb_itemTop > div {
  1599. display: flex;
  1600. flex-direction: column;
  1601. }
  1602. .ai_b_i_rlb_itemTop > div > span {
  1603. font-size: 16px;
  1604. font-weight: bold;
  1605. }
  1606. .ai_b_i_rlb_itemTop > div > span:last-child {
  1607. font-size: 14px;
  1608. color: #999;
  1609. }
  1610. .ai_b_i_rlb_itemBottom {
  1611. margin-top: 10px;
  1612. display: flex;
  1613. }
  1614. .ai_b_i_rlb_itemBottom > span {
  1615. width: 60px;
  1616. height: 30px;
  1617. border-radius: 15px;
  1618. display: flex;
  1619. }
  1620. .ai_body_input_textarea {
  1621. flex: 1;
  1622. margin: 10px 5px 10px 5px;
  1623. min-height: 35px;
  1624. height: 35px;
  1625. max-height: 100px;
  1626. border: none;
  1627. outline: none;
  1628. resize: none;
  1629. font-size: 16px;
  1630. overflow: auto;
  1631. padding-right: 100px;
  1632. background-color: #fff !important;
  1633. }
  1634. .ai_body_input_textarea::-webkit-input-placeholder {
  1635. font-size: 16px;
  1636. /* 修改placeholder字体大小 */
  1637. color: grey;
  1638. /* 修改placeholder文字颜色 */
  1639. }
  1640. .ai_body_input_textarea::-moz-placeholder {
  1641. font-size: 16px;
  1642. /* 修改placeholder字体大小 */
  1643. color: grey;
  1644. /* 修改placeholder文字颜色 */
  1645. opacity: 1;
  1646. /* 修复Firefox的透明度问题 */
  1647. }
  1648. .ai_body_input_textarea::-moz-placeholder {
  1649. font-size: 16px;
  1650. /* 修改placeholder字体大小 */
  1651. color: grey;
  1652. /* 修改placeholder文字颜色 */
  1653. opacity: 1;
  1654. /* 修复Firefox的透明度问题 */
  1655. }
  1656. .ai_body_input_textarea::-ms-input-placeholder {
  1657. font-size: 16px;
  1658. /* 修改placeholder字体大小 */
  1659. color: grey;
  1660. /* 修改placeholder文字颜色 */
  1661. }
  1662. .ai_body_input_textarea::-webkit-scrollbar {
  1663. width: 6px;
  1664. }
  1665. .ai_body_input_textarea::-webkit-scrollbar-track {
  1666. background: #d8d9dc;
  1667. border-radius: 2px;
  1668. }
  1669. .ai_body_input_textarea::-webkit-scrollbar-thumb {
  1670. background: #c9c9c9;
  1671. border-radius: 10px;
  1672. }
  1673. .ai_body_input_textarea::-webkit-scrollbar-thumb:hover {
  1674. background: #c9c9c9;
  1675. }
  1676. .c_pub_button_confirm {
  1677. /* position: absolute;
  1678. bottom: 13px;
  1679. right: 13px; */
  1680. /* margin-top: 10px; */
  1681. width: 60px;
  1682. margin-right: 5px;
  1683. display: flex;
  1684. justify-content: center;
  1685. margin-bottom: 10px;
  1686. position: absolute;
  1687. right: 10px;
  1688. bottom: 0px;
  1689. white-space: nowrap;
  1690. border-radius: 10px;
  1691. }
  1692. .c_pub_button_confirmVoice {
  1693. width: 30px;
  1694. height: 36px;
  1695. min-width: auto;
  1696. margin-right: 5px;
  1697. display: flex;
  1698. justify-content: center;
  1699. align-items: center;
  1700. margin-bottom: 10px;
  1701. position: absolute;
  1702. right: 10px;
  1703. bottom: 0px;
  1704. white-space: nowrap;
  1705. border-radius: 10px;
  1706. background-color: #3681fc;
  1707. cursor: pointer;
  1708. padding: 0 10px;
  1709. }
  1710. .c_pub_button_confirmVoice > svg {
  1711. fill: #fff;
  1712. width: 25px;
  1713. height: 25px;
  1714. }
  1715. .c_pub_button_StopConfirmVoice {
  1716. width: 30px;
  1717. height: 36px;
  1718. min-width: auto;
  1719. margin-right: 5px;
  1720. display: flex;
  1721. justify-content: center;
  1722. align-items: center;
  1723. margin-bottom: 10px;
  1724. position: absolute;
  1725. right: 10px;
  1726. bottom: 0px;
  1727. white-space: nowrap;
  1728. border-radius: 10px;
  1729. background-color: #dde2e2;
  1730. cursor: pointer;
  1731. padding: 0 10px;
  1732. }
  1733. .c_pub_button_StopConfirmVoice > svg {
  1734. width: 25px;
  1735. height: 25px;
  1736. }
  1737. .c_voiceBtn {
  1738. width: 25px;
  1739. height: 25px;
  1740. position: absolute;
  1741. right: 85px;
  1742. bottom: 0px;
  1743. margin-bottom: 17px;
  1744. cursor: pointer;
  1745. }
  1746. .c_voiceBtn > svg {
  1747. width: 100%;
  1748. height: 100%;
  1749. }
  1750. .c_pub_button_confirmDisabled {
  1751. background-color: #aeccfe;
  1752. }
  1753. .ai_body_dialog {
  1754. padding: 10px 0;
  1755. box-sizing: border-box;
  1756. /* min-height: calc(20vh - 10px); */
  1757. /* height: calc(100%); */
  1758. overflow: auto;
  1759. margin-bottom: 10px;
  1760. }
  1761. .dialog_content {
  1762. width: 100%;
  1763. display: flex;
  1764. flex-direction: column;
  1765. }
  1766. .dialog_content > div {
  1767. display: flex;
  1768. align-items: flex-start;
  1769. width: 100%;
  1770. }
  1771. .dialog_content + .dialog_content {
  1772. margin: 15px 0;
  1773. }
  1774. .dialog_content > div .right {
  1775. flex-direction: row-reverse;
  1776. }
  1777. .dialog_content > div .right .role {
  1778. margin-right: 0;
  1779. margin-left: 10px;
  1780. }
  1781. .dialog_content > div .role {
  1782. min-width: 30px;
  1783. width: 30px;
  1784. height: 30px;
  1785. margin-right: 10px;
  1786. border-radius: 50%;
  1787. }
  1788. .dialog_content > div .role > img {
  1789. height: 100%;
  1790. width: 100%;
  1791. border-radius: 100%;
  1792. }
  1793. .dialog_content > div .content {
  1794. padding: 10px 10px;
  1795. border-radius: 2px 8px 8px 8px;
  1796. width: auto;
  1797. word-break: break-word;
  1798. box-sizing: border-box;
  1799. /* white-space: pre-line; */
  1800. max-width: calc(100% - 85px);
  1801. background: #f6f9ff;
  1802. /* overflow: hidden; */
  1803. margin: 0 10px;
  1804. position: relative;
  1805. }
  1806. .createTime {
  1807. width: 100%;
  1808. height: 20px;
  1809. position: absolute;
  1810. bottom: -25px;
  1811. left: 0;
  1812. font-size: 14px;
  1813. white-space: nowrap;
  1814. color: #919191;
  1815. }
  1816. .dialog_content > div .content2 {
  1817. background: #3681fc;
  1818. color: #fff;
  1819. border-radius: 8px 2px 8px 8px;
  1820. margin-left: auto;
  1821. }
  1822. .ai_body_select {
  1823. position: relative;
  1824. }
  1825. .ai_body_select > .check {
  1826. background: #e7e7e7;
  1827. display: flex;
  1828. width: fit-content;
  1829. padding: 0 10px;
  1830. height: 30px;
  1831. border-radius: 21px;
  1832. font-size: 14px;
  1833. align-items: center;
  1834. justify-content: center;
  1835. color: #0061ff;
  1836. font-weight: 700;
  1837. margin: 10px 0;
  1838. cursor: pointer;
  1839. }
  1840. .ai_body_select > .check::before {
  1841. content: "";
  1842. width: 15px;
  1843. height: 15px;
  1844. display: block;
  1845. background-image: url("../../../../assets/icon/course/aiPart.png");
  1846. background-size: 100% 100%;
  1847. margin-right: 5px;
  1848. }
  1849. .ai_body_select > .check::after {
  1850. content: "";
  1851. width: 15px;
  1852. height: 15px;
  1853. display: block;
  1854. background-image: url("../../../../assets/icon/course/aiPart_arrow.png");
  1855. background-size: 100% 100%;
  1856. margin-right: 5px;
  1857. }
  1858. .ai_body_select > .isCheck {
  1859. background: #0061ff;
  1860. display: flex;
  1861. width: fit-content;
  1862. padding: 0 10px;
  1863. height: 30px;
  1864. border-radius: 21px;
  1865. font-size: 14px;
  1866. align-items: center;
  1867. justify-content: center;
  1868. color: #fff;
  1869. font-weight: 700;
  1870. margin: 10px 0;
  1871. cursor: pointer;
  1872. max-width: 100%;
  1873. box-sizing: border-box;
  1874. }
  1875. .ai_body_select > .isCheck > span {
  1876. width: calc(100% - 40px);
  1877. display: block;
  1878. overflow: hidden;
  1879. white-space: nowrap;
  1880. text-overflow: ellipsis;
  1881. }
  1882. .ai_body_select > .isCheck::before {
  1883. content: "";
  1884. width: 15px;
  1885. height: 15px;
  1886. display: block;
  1887. background-image: url("../../../../assets/icon/course/aiPart_active.png");
  1888. background-size: 100% 100%;
  1889. margin-right: 5px;
  1890. }
  1891. .ai_body_select > .isCheck::after {
  1892. content: "";
  1893. width: 15px;
  1894. height: 15px;
  1895. display: block;
  1896. background-image: url("../../../../assets/icon/course/aiPart_arrow_active.png");
  1897. background-size: 100% 100%;
  1898. margin-right: 5px;
  1899. }
  1900. .ai_body_select > .checkBox {
  1901. position: absolute;
  1902. bottom: 40px;
  1903. border: 1px solid #e0eafb;
  1904. width: 100%;
  1905. height: 300px;
  1906. background: #fff;
  1907. border-radius: 5px;
  1908. padding: 10px;
  1909. box-sizing: border-box;
  1910. }
  1911. .ai_body_select > .checkBox > .task > .title,
  1912. .ai_body_select > .checkBox > .part > .title {
  1913. font-size: 14px;
  1914. font-weight: 700;
  1915. margin-bottom: 5px;
  1916. }
  1917. .ai_body_select > .checkBox > .task {
  1918. height: calc(100% - 60px);
  1919. }
  1920. .ai_body_select > .checkBox > .part {
  1921. }
  1922. .ai_body_select > .checkBox > .task > .content {
  1923. height: calc(100% - 40px);
  1924. overflow: auto;
  1925. }
  1926. .ai_body_select > .checkBox > .task > .content > .span + .span {
  1927. margin-top: 5px;
  1928. }
  1929. .ai_body_select > .checkBox > .task > .content > .span {
  1930. display: flex;
  1931. align-items: center;
  1932. font-size: 14px;
  1933. cursor: pointer;
  1934. }
  1935. .ai_body_select > .checkBox > .task > .content > .span > .check {
  1936. width: 13px;
  1937. height: 13px;
  1938. display: flex;
  1939. align-items: center;
  1940. margin-right: 5px;
  1941. }
  1942. .ai_body_select > .checkBox > .task > .content > .span > .check > img {
  1943. width: 100%;
  1944. height: 100%;
  1945. }
  1946. .ai_body_select > .checkBox > .part > .content {
  1947. display: flex;
  1948. align-items: center;
  1949. font-size: 14px;
  1950. justify-content: space-between;
  1951. }
  1952. .ai_body_select > .checkBox > .part > .content > .span {
  1953. padding: 3px 6px;
  1954. border: 1px solid #e0eafb;
  1955. border-radius: 40px;
  1956. cursor: pointer;
  1957. }
  1958. .ai_body_select > .checkBox > .part > .content > .span.active {
  1959. color: #0061ff;
  1960. border-color: #0061ff;
  1961. }
  1962. .ai_b_i_jListPanel {
  1963. width: 400px;
  1964. height: 100%;
  1965. top: 0;
  1966. right: 0;
  1967. position: fixed;
  1968. /* background-color: #000; */
  1969. z-index: 990;
  1970. }
  1971. .ai_b_i_jListBox {
  1972. width: 100%;
  1973. max-height: 300px;
  1974. background-color: #fff;
  1975. position: absolute;
  1976. bottom: calc(100% + 5px);
  1977. box-sizing: border-box;
  1978. padding: 10px;
  1979. overflow: auto;
  1980. border-radius: 8px;
  1981. border: 1px solid #e7e7e7;
  1982. box-shadow: 0 4px 10px 0 rgba(29, 57, 131, 0.08),
  1983. 1px 1px 20px 4px rgba(29, 57, 131, 0.05);
  1984. z-index: 999;
  1985. }
  1986. .jlist_box {
  1987. background: #f1f1f1;
  1988. border-radius: 5px;
  1989. margin-bottom: 10px;
  1990. padding: 8px 18px 8px 8px;
  1991. box-sizing: border-box;
  1992. width: 100%;
  1993. position: relative;
  1994. }
  1995. .jlist_box .cancel {
  1996. position: absolute;
  1997. top: 8px;
  1998. right: 5px;
  1999. cursor: pointer;
  2000. font-size: 14px;
  2001. }
  2002. .jlist_box > span {
  2003. display: -webkit-box;
  2004. -webkit-box-orient: vertical;
  2005. -webkit-line-clamp: 3;
  2006. text-overflow: ellipsis;
  2007. overflow: hidden;
  2008. word-break: break-all;
  2009. }
  2010. .ai_btn_box {
  2011. min-width: fit-content;
  2012. margin-top: auto;
  2013. }
  2014. .ai_btn_box > img {
  2015. cursor: pointer;
  2016. width: 15px;
  2017. }
  2018. </style>