标准版政企呼叫中心业务系统

aiDialog.vue 45KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  1. <template>
  2. <div>
  3. <div class="aiWrap"
  4. id="gundong"
  5. :style="{ 'background': 'url(' + base64data.aiBG2 + ') right -36px/400px 300px no-repeat' }">
  6. <!-- 新会话开始 -->
  7. <div v-show="dialogState !== '会话中'" class="ai_girl"
  8. :style="{ 'background': 'url(' + base64data.aiBG3 + ') -16px -36px/400px 300px no-repeat'}">
  9. <div class="ai_content">
  10. <div class="ai_des">
  11. 我是你的智能助手,可以帮你撰写营销文案、查询数据和功能,助力你更高效的完成工作。
  12. </div>
  13. <div class="ai_tips">
  14. 💡你可能想知道
  15. </div>
  16. <div class="ai_text">
  17. <div class="ai_item" @click="chatModalHandle(item.content)" v-for="(item,index) in conModelData" :key="index">
  18. <span class="ai_label">{{item.icon}}{{item.title}}</span>
  19. <span class="ai_value">{{item.content}}</span>
  20. </div>
  21. </div>
  22. </div>
  23. </div>
  24. <!-- 新会话结束 -->
  25. <!-- 会话中 -->
  26. <div class="ai-conversation" v-show="dialogState == '会话中' ">
  27. <div v-for="(item, index) in chatData" :key="index">
  28. <div class="conversation_item" v-if="item.direction ===1 ">
  29. <div class="item_user">
  30. <div class="aiHtml">{{item.page_content}}</div>
  31. </div>
  32. </div>
  33. <div class="conversation_item" v-if="item.direction === 2 ">
  34. <div class="item_ai" v-loading="item.loadingFlag">
  35. <!-- v-for="(item,index) in productDetails.content && productDetails.content.split('\n')" :key="index" -->
  36. <!-- productDetails.content.split('\n') pre-wrap -->
  37. <!-- v-text="item.page_content" -->
  38. <!-- v-for="(itemChild,indexChild) in item.page_content && item.page_content.split('\n')" -->
  39. <div class="aiHtml" >
  40. {{item.page_content}}
  41. </div>
  42. <div class="tools-wrap">
  43. <div class="item-ai-tools">
  44. <div class="tools-left">
  45. <!-- <div class="tool">
  46. <svg width="16" height="16" viewBox="0 0 16 16" fill="none"
  47. xmlns="http://www.w3.org/2000/svg" class="sc-ai-conversation">
  48. <g id="Frame 427321419" class="sc-ai-conversation">
  49. <rect id="Rectangle 34624950" x="2.50018" y="4.3335" width="9.16667"
  50. height="9.16667" rx="1.83333" stroke="#86909C"
  51. stroke-width="1.2" class="sc-ai-conversation"></rect>
  52. <path id="Subtract" fill-rule="evenodd" clip-rule="evenodd"
  53. d="M6.16649 1.8999C4.82259 1.8999 3.73315 2.98935 3.73315 4.33324V4.43394C3.92124 4.36879 4.12323 4.3334 4.33348 4.3334H4.93315V4.33324C4.93315 3.65209 5.48534 3.0999 6.16649 3.0999H11.6665C12.3476 3.0999 12.8998 3.65209 12.8998 4.33324V9.83323C12.8998 10.5143 12.3478 11.0664 11.6668 11.0666V11.6667C11.6668 11.8768 11.6315 12.0786 11.5664 12.2666H11.6665C13.0104 12.2666 14.0998 11.1771 14.0998 9.83323V4.33324C14.0998 2.98934 13.0104 1.8999 11.6665 1.8999H6.16649Z"
  54. fill="#86909C" class="sc-ai-conversation"></path>
  55. </g>
  56. </svg>
  57. <div class="text">复制</div>
  58. </div> -->
  59. <!-- <div class="tool">
  60. <svg width="16" height="16" viewBox="0 0 16 16" fill="none"
  61. xmlns="http://www.w3.org/2000/svg" class="sc-ai-conversation">
  62. <g id="Frame 427321538" class="sc-ai-conversation">
  63. <path id="Ellipse 2705"
  64. d="M3.48167 10.6094C4.92242 13.1048 8.11334 13.9598 10.6088 12.5191C12.1804 11.6117 13.1014 10.0101 13.208 8.32526M12.5185 5.39195C11.0777 2.8965 7.88683 2.04149 5.39138 3.48224C3.81975 4.38962 2.89879 5.99121 2.79222 7.67605"
  65. stroke="#86909C" stroke-width="1.2" stroke-linecap="round"
  66. stroke-linejoin="round" class="sc-ai-conversation"></path>
  67. <path id="Rectangle 34625018"
  68. d="M10.437 5.36768L12.7034 5.36768L12.7034 3.1013"
  69. stroke="#86909C" stroke-width="1.2" stroke-linecap="round"
  70. stroke-linejoin="round" class="sc-ai-conversation"></path>
  71. <path id="Rectangle 34625019"
  72. d="M5.51387 10.3096L3.2475 10.3096L3.2475 12.5759"
  73. stroke="#86909C" stroke-width="1.2" stroke-linecap="round"
  74. stroke-linejoin="round" class="sc-ai-conversation"></path>
  75. </g>
  76. </svg>
  77. <div class="text">重新生成</div>
  78. </div> -->
  79. </div>
  80. <div class="tools-right">
  81. <!-- <div class="pointer">
  82. <svg width="16" height="16" viewBox="0 0 16 16" fill="none"
  83. xmlns="http://www.w3.org/2000/svg" class="sc-ai-conversation">
  84. <g id="Frame 427321417" class="sc-ai-conversation">
  85. <path id="Rectangle 34624947"
  86. d="M5 6H4.5C3.39543 6 2.5 6.89543 2.5 8V11.5C2.5 12.6046 3.39543 13.5 4.5 13.5H5M5 6L5.11992 5.96672C5.79688 5.77882 6.32561 5.2495 6.51275 4.57233L6.96307 2.94285C7.20278 2.07547 8.28898 1.78898 8.9253 2.4253V2.4253C9.28996 2.78996 9.4765 3.29611 9.43569 3.81021L9.34753 4.92087C9.30136 5.50252 9.76091 6 10.3444 6H11.5604C12.8225 6 13.7691 7.15465 13.5216 8.39223L12.8216 11.8922C12.6346 12.8271 11.8138 13.5 10.8604 13.5H5M5 6V13.5"
  87. stroke="#86909C" stroke-width="1.2" class="sc-ai-conversation">
  88. </path>
  89. </g>
  90. </svg>
  91. </div> -->
  92. <!-- <div class="pointer">
  93. <svg width="16" height="16" viewBox="0 0 16 16" fill="none"
  94. xmlns="http://www.w3.org/2000/svg" class="sc-ai-conversation">
  95. <g id="Frame 427321417" class="sc-ai-conversation">
  96. <path id="Rectangle 34624947"
  97. d="M5 6H4.5C3.39543 6 2.5 6.89543 2.5 8V11.5C2.5 12.6046 3.39543 13.5 4.5 13.5H5M5 6L5.11992 5.96672C5.79688 5.77882 6.32561 5.2495 6.51275 4.57233L6.96307 2.94285C7.20278 2.07547 8.28898 1.78898 8.9253 2.4253V2.4253C9.28996 2.78996 9.4765 3.29611 9.43569 3.81021L9.34753 4.92087C9.30136 5.50252 9.76091 6 10.3444 6H11.5604C12.8225 6 13.7691 7.15465 13.5216 8.39223L12.8216 11.8922C12.6346 12.8271 11.8138 13.5 10.8604 13.5H5M5 6V13.5"
  98. stroke="#86909C" stroke-width="1.2" class="sc-ai-conversation">
  99. </path>
  100. </g>
  101. </svg>
  102. </div> -->
  103. </div>
  104. </div>
  105. </div>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. <!-- 会话中结束 -->
  111. </div>
  112. <!-- 提示指令内容 -->
  113. <div class="tip_bg" v-show="tipFlag " @click="tipBgHandle"></div>
  114. <div class="tip_dialog" v-show="tipFlag ">
  115. <div class="bottomItem">
  116. <!-- <div class="ai_bttton_wrap">
  117. <button class="primary" v-if="tipState === '内容创作' " @click="tipHandle('内容创作')">
  118. <img class="btn_icon" :src="base64data.aiBG11">
  119. <span style="padding-left: 15px;">内容创作</span>
  120. </button>
  121. <button class="default" v-if="tipState !== '内容创作' " @click="tipHandle('内容创作')">
  122. <img class="btn_icon" :src="base64data.aiBG12">
  123. <span style="padding-left: 15px;">内容创作</span>
  124. </button>
  125. </div> -->
  126. <div class="ai_bttton_wrap">
  127. <button class="primary" v-if="tipState === '问题咨询' " @click="tipHandle('问题咨询')">
  128. <img class="btn_icon" :src="base64data.aiBG14">
  129. <span style="padding-left: 15px;">问题咨询</span>
  130. </button>
  131. <button class="default" v-if="tipState !== '问题咨询' " @click="tipHandle('问题咨询')">
  132. <img class="btn_icon" :src="base64data.aiBG13">
  133. <span style="padding-left: 15px;">问题咨询</span>
  134. </button>
  135. </div>
  136. <div class="ai_bttton_wrap">
  137. <button class="primary" v-if="tipState === '数据查询' " @click="tipHandle('数据查询')">
  138. <img class="btn_icon" :src="base64data.aiBG16">
  139. <span style="padding-left: 15px;">数据查询</span>
  140. </button>
  141. <button class="default" v-if="tipState !== '数据查询' " @click="tipHandle('数据查询')">
  142. <img class="btn_icon" :src="base64data.aiBG15">
  143. <span style="padding-left: 15px;">数据查询</span>
  144. </button>
  145. </div>
  146. </div>
  147. <div class="ai_content_scroll">
  148. <div class="scroll_ele">
  149. <div class="ai_item" @click="modelItemHandle(item.content)" v-for="(item,index) in modelData" :key="index">
  150. <div class="ai_label">{{item.title}}</div>
  151. <div class="ai_value">{{item.content}}</div>
  152. </div>
  153. </div>
  154. </div>
  155. </div>
  156. <!-- 提示指令内容结束 -->
  157. <!-- 回话底部按钮 -->
  158. <div class="sc-ai-dialog">
  159. <div class="bottomItem">
  160. <!-- <div class="ai_bttton_wrap">
  161. <button class="primary" @click="dialogHandle('提示指令')">
  162. <img class="btn_icon" :src="base64data.aiBG4">
  163. <span style="padding-left: 15px;">提示指令</span>
  164. </button>
  165. </div> -->
  166. <div class="ai_bttton_wrap">
  167. <button class="default" @click="dialogHandle('新建会话')">
  168. <img class="btn_icon" :src="base64data.aiBG5">
  169. <span style="padding-left: 15px;">新建会话</span>
  170. </button>
  171. </div>
  172. <!-- <div class="ai_bttton_wrap">
  173. <button class="default" @click="dialogHandle('历史记录')">
  174. <img class="btn_icon" :src="base64data.aiBG6">
  175. <span style="padding-left: 15px;">历史记录</span>
  176. </button>
  177. </div> -->
  178. </div>
  179. <div class="textareaBox">
  180. <div class="textarea_wrap">
  181. <textarea v-model="postChatText" @keydown.enter="enterHnadle" placeholder="输入你想了解的内容,Shift + Enter 换行" rows="1"></textarea>
  182. <button class="send-btn-disabled" @click="enterHnadle">
  183. <img :src="base64data.aiBG7">
  184. </button>
  185. </div>
  186. </div>
  187. <div class="ai-tips">内容由 AI 生成,请结合实际情况进行甄别</div>
  188. </div>
  189. <!-- 回话底部按钮结束 -->
  190. <el-drawer direction="btt" size="90%" :style="{ 'background-image': 'url(' + base64data.aiBG10 + ')'}"
  191. :append-to-body="false" v-model="drawer">
  192. <template #header="{ close, titleId, titleClass }">
  193. <h4 :id="titleId" :class="titleClass">历史记录</h4>
  194. <img class="ai_delete pointer" :src="base64data.aiBG8" alt="">
  195. </template>
  196. <div class="ai_history_list">
  197. <div v-for="o in 10" :key="o">
  198. <div class="title">2024-10-16</div>
  199. <div class="item-module">
  200. <div class="itemBg">
  201. <!-- @mouseover="showButton" @mouseleave="hideButton" -->
  202. <div class="item" @mouseover="hisItemOver" @mouseleave="hisItemLeave">
  203. <div class="item-content">
  204. 你是个专业文本润色专家,注重细节,提升文章质量,现在将下面的文本优化一下:
  205. </div>
  206. </div>
  207. <div class="item_close" v-show="hisItemFlag">
  208. <img class="item_close_icon" :src="base64data.aiBG9" alt="">
  209. </div>
  210. </div>
  211. </div>
  212. </div>
  213. </div>
  214. </el-drawer>
  215. </div>
  216. </template>
  217. <script setup>
  218. import { onMounted, ref, watch, defineProps } from 'vue'
  219. import axios from 'axios';
  220. import aiIcon from '@/assets/images/aiIcon.png' // 默认头像
  221. import { getToken } from '@/utils/auth'
  222. import { base64data } from '@/utils/baseUrlData'
  223. const { proxy } = getCurrentInstance();
  224. const drawer = ref(false)
  225. const props = defineProps({
  226. text: {
  227. type: String,
  228. default: ''
  229. },
  230. });
  231. onMounted(() => {
  232. console.log('onMounted-ai')
  233. // getSearchDocs()
  234. modelData.value = quesModelData
  235. if (props.text) {
  236. postChatText.value = props.text;
  237. enterHnadle();
  238. }
  239. })
  240. watch(props , (newVal, oldVal) => {
  241. console.log('watch-ai', newVal, oldVal)
  242. if (newVal.text) {
  243. postChatText.value = newVal.text;
  244. enterHnadle();
  245. }
  246. })
  247. const dialogState = ref('新建会话')
  248. const tipFlag = ref(false)
  249. // dialogState === '历史记录'
  250. function dialogHandle(name) {
  251. console.log(name)
  252. if (name == '新建会话') {
  253. if (dialogState.value == '新建会话') {
  254. proxy.$modal.msgWarning('当前已是最新会话');
  255. }
  256. postChatText.value = ''
  257. chatData.value = []
  258. dialogState.value = name
  259. } else if (name === '历史记录') {
  260. drawer.value = true
  261. } else if (name === '提示指令'){
  262. tipFlag.value = true
  263. } else{
  264. dialogState.value = name
  265. }
  266. }
  267. function chatModalHandle(value) {
  268. console.log('chatModalHandle')
  269. // dialogState.value = '会话中'
  270. postChatText.value = value
  271. }
  272. function tipBgHandle() {
  273. tipFlag.value = false
  274. }
  275. const modelData = ref([])
  276. const tipState = ref('问题咨询')
  277. function tipHandle(name) {
  278. tipState.value = name
  279. if (name === '问题咨询') {
  280. modelData.value = quesModelData
  281. } else if (name === '数据查询') {
  282. modelData.value = baseModelData
  283. }
  284. }
  285. function modelItemHandle(value) {
  286. postChatText.value = value
  287. }
  288. const postChatText = ref()
  289. function enterHnadle() {
  290. if (postChatText.value) {
  291. dialogState.value = '会话中'
  292. tipFlag.value = false
  293. sendChatText(1, postChatText.value)
  294. if (tipState.value === '问题咨询') {
  295. getSearchDocs()
  296. } else if (tipState.value === '数据查询') {
  297. getSearchDb()
  298. }
  299. postChatText.value = ''
  300. }
  301. }
  302. const hisItemFlag = ref(false)
  303. function hisItemOver() {
  304. hisItemFlag.value = true
  305. }
  306. function hisItemLeave() {
  307. hisItemFlag.value = false
  308. }
  309. // 滚动核心代码
  310. function roll() {
  311. nextTick(() => {
  312. var msg = document.getElementById('gundong'); // 获取对象
  313. if (msg) {
  314. msg.scrollTop = msg.scrollHeight; // 滚动高度
  315. }
  316. });
  317. }
  318. const chatData = ref([])
  319. function sendChatText(direction, dataValue) {
  320. const obj = {
  321. direction,
  322. page_content: dataValue
  323. }
  324. chatData.value.push(obj)
  325. setTimeout(() => {
  326. roll();
  327. }, 200);
  328. }
  329. const getChatResultText = ref('')
  330. function getSearchDb() {
  331. console.log(postChatText.value)
  332. const obj = {
  333. direction:2,
  334. loadingFlag:true,
  335. page_content: ''
  336. }
  337. chatData.value.push(obj)
  338. axios({
  339. method: 'post',
  340. url: 'http://192.168.1.89:7861/db_base/search_db',
  341. headers: {
  342. "Content-Type": 'application/json'
  343. },
  344. data: postChatText.value
  345. }).then(function (response) {
  346. console.log(response.data)
  347. if (response.data) {
  348. const resultText = response.data.analysis
  349. chatData.value[chatData.value.length-1].loadingFlag = false
  350. chatData.value[chatData.value.length-1].page_content = resultText
  351. setTimeout(() => {
  352. roll();
  353. }, 200);
  354. }
  355. }).catch(function (error) {
  356. })
  357. // axios.post('http://192.168.1.89:7861/db_base/search_db', {postChatText.value},
  358. // {
  359. // headers: {
  360. // 'Content-Type':'application/json;charset=utf-8',
  361. // // responseType: 'stream'
  362. // // 'Authorization': 'Bearer ' + getToken()
  363. // },
  364. // }
  365. // ).then(function (response) {
  366. // console.log(response)
  367. // }).catch(function (error) {
  368. // console.log(error);
  369. // });
  370. }
  371. async function getSearchDocs() {
  372. let params = {}
  373. const obj = {
  374. direction:2,
  375. loadingFlag:true,
  376. page_content: getChatResultText.value
  377. }
  378. chatData.value.push(obj)
  379. setTimeout(() => {
  380. roll();
  381. }, 200);
  382. try {
  383. params = {
  384. model: 'deepseek-r1:32b',
  385. messages: [{
  386. role: 'system',
  387. content: `你是一位专业的心理咨询师,擅长帮助来访者探索情绪、压力、人际关系等问题。请根据以下用户输入,提供专业、温暖且有针对性的心理咨询建议。如果用户的问题涉及具体心理困扰,请尝试引导用户深入思考,并提供适当的应对策略或情绪调节方法。
  388. 用户输入:{用户输入信息}
  389. 请根据以下步骤进行回复:
  390. 1. **共情与理解**:首先对用户的情绪或困扰表示理解,建立信任感。
  391. 2. **问题分析**:分析用户问题的可能根源或核心矛盾。
  392. 3. **建议与引导**:提供具体的建议或引导用户思考解决方案。
  393. 4. **总结与支持**:总结关键点,并鼓励用户尝试行动或进一步探索。
  394. 注意:保持语气温和、专业,避免使用过于绝对的判断或建议,内容尽量言简意赅。`
  395. }, {
  396. role: 'user',
  397. content: postChatText.value,
  398. }],
  399. stop: ['stop'],
  400. stream: true,
  401. }
  402. // 发送请求
  403. // let response = await fetch("http://192.168.1.89:7861/chat/kb_chat",
  404. const url = import.meta.env.VITE_APP_AI_API || 'https://open.bigmodel.cn/api/paas/v4/chat/completions'
  405. let response = await fetch(url,
  406. {
  407. method: "post",
  408. responseType: "stream",
  409. headers: {
  410. "Content-Type": "application/json",
  411. "Authorization": `Bearer ${import.meta.env.VITE_APP_AI_API_KEY}`
  412. },
  413. body: JSON.stringify(params),
  414. }
  415. );
  416. // // 发送请求
  417. // let response = await fetch("https://open.bigmodel.cn/api/paas/v4/chat/completions",
  418. // // let response = await fetch("http://192.168.1.89:7861/chat/kb_chat",
  419. // {
  420. // method: "post",
  421. // responseType: "stream",
  422. // headers: {
  423. // "Content-Type": "application/json",
  424. // "Authorization": 'Bearer 1711c0bfa059f253fce0921015a44fc8.VZVQz66PrwJ2NqLP',
  425. // },
  426. // body: JSON.stringify(params),
  427. // }
  428. // );
  429. // ok字段判断是否成功获取到数据流
  430. if (!response.ok) {
  431. throw new Error("Network response was not ok");
  432. }
  433. // 用来获取一个可读的流的读取器(Reader)以流的方式处理响应体数据
  434. const reader = response.body.getReader();
  435. // 将流中的字节数据解码为文本字符串
  436. const textDecoder = new TextDecoder();
  437. let result = true;
  438. let sqlValue = ''
  439. while (result) {
  440. // done表示流是否已经完成读取 value包含读取到的数据块
  441. const { done, value } = await reader.read();
  442. if (done) {
  443. result = false;
  444. break;
  445. }
  446. // 拿到的value就是后端分段返回的数据,大多是以data:开头的字符串
  447. // 需要通过decode方法处理数据块,例如转换为文本或进行其他操作
  448. const chunkText = textDecoder.decode(value).split("\n").forEach((val) => {
  449. if (!val) return;
  450. try {
  451. // 后端返回的流式数据一般都是以data:开头的字符,排除掉data:后就是需要的数据
  452. // 具体返回结构可以跟后端约定
  453. let text = val?.replace("data:", "") || ""
  454. const resultData = JSON.parse(text)
  455. let resultText = resultData.choices[0].delta.content
  456. // console.log(resultData.choices[0].delta.content, "输出分段返回的数据")
  457. chatData.value[chatData.value.length -1].page_content += resultText || ''
  458. chatData.value[chatData.value.length-1].loadingFlag = false
  459. setTimeout(() => {
  460. roll();
  461. }, 200);
  462. } catch (err) {
  463. // console.log(err)
  464. }
  465. });
  466. }
  467. console.log(chatData.value, '输出所有返回数据')
  468. // console.log(getChatResultText.value, '输出所有返回数据')
  469. } catch (err) {
  470. console.log(err)
  471. }
  472. }
  473. const conModelData = [
  474. // {
  475. // icon:'✍️',
  476. // title:'标题大师',
  477. // content:'请帮我拟定几个合适的标题,我的主题或内容是:'
  478. // },
  479. // {
  480. // icon:'💬 ',
  481. // title:'疾病咨询',
  482. // content:'请帮我查询一下,心脏病'
  483. // },
  484. // {
  485. // icon:'🔍',
  486. // title:'功能查询',
  487. // content:'怎么添加员工?'
  488. // },
  489. // {
  490. // icon:'📈 ',
  491. // title:'工单查询',
  492. // content:'帮我查询所有产品线下2024-10-01 到 2024-10-31的工单数据'
  493. // },
  494. ]
  495. const quesModelData = [
  496. {
  497. title:'标题大师',
  498. content:'请帮我拟定几个合适的标题,我的主题或内容是:'
  499. },
  500. {
  501. title:'疾病查询',
  502. content:'请帮我查询一下,心脏病'
  503. },
  504. {
  505. title:'故障措施',
  506. content:'请帮我查询一下,冬季供水防冻的措施'
  507. },
  508. ]
  509. const baseModelData = [
  510. {
  511. title:'工单查询',
  512. content:'帮我查询工单数据,手机号为:'
  513. },
  514. {
  515. title:'用户查询',
  516. content:'帮我查询用户数据,用户手机号为:'
  517. },
  518. {
  519. title:'患者查询',
  520. content:'帮我查询患者数据,手机号为:'
  521. },
  522. {
  523. title:'计划查询',
  524. content:'帮我查询计划数据,关键字:'
  525. },
  526. {
  527. title:'问卷查询',
  528. content:'帮我查询问卷数据,关键字:'
  529. },
  530. ]
  531. </script>
  532. <style scoped lang="scss">
  533. :deep(.el-overlay) {
  534. position: absolute;
  535. }
  536. :deep(.el-drawer) {
  537. position: absolute;
  538. width: 100%;
  539. border-radius: 8px 8px 0px 0px;
  540. background-color: rgb(248, 251, 255);
  541. box-shadow: rgba(18, 110, 254, 0.1) 0px 2px 16px 0px;
  542. margin-top: 60px;
  543. background-repeat: no-repeat;
  544. background-position: center top;
  545. background-size: 100%;
  546. }
  547. :deep(.el-drawer__header) {
  548. margin-bottom: 0px;
  549. }
  550. .aiWrap {
  551. height: 550px;
  552. overflow: auto;
  553. position: relative;
  554. padding-right: 15px;
  555. .ai_girl {
  556. width: 100%;
  557. padding-top: 136px;
  558. .ai_content {
  559. box-sizing: border-box;
  560. padding: 8px 12px;
  561. background: rgba(255, 255, 255, 0.8);
  562. border-radius: 2px 16px 16px;
  563. .ai_des {
  564. font-family: "PingFang SC", "PingFang SC";
  565. font-weight: 400;
  566. font-size: 14px;
  567. color: rgb(29, 33, 41);
  568. padding-bottom: 8px;
  569. margin-bottom: 8px;
  570. line-height: 22px;
  571. border-bottom: 1px dashed rgb(240, 240, 240);
  572. white-space: normal;
  573. }
  574. .ai_tips {
  575. font-family: "PingFang SC", "PingFang SC";
  576. font-weight: 400;
  577. font-size: 12px;
  578. color: rgb(134, 144, 156);
  579. }
  580. .ai_text {
  581. list-style: none;
  582. padding: 0px;
  583. margin: 8px 0px;
  584. .ai_item:hover {
  585. border-radius: 8px;
  586. background-clip: padding-box, border-box;
  587. background-origin: padding-box, border-box;
  588. /* background-image:
  589. -webkit-gradient(linear, left top, right top, from(#fff), to(#fff)),
  590. -webkit-gradient(linear, left top, right top, from(#3D8EFF), to(#7835FF)); */
  591. background-image: linear-gradient(89deg, rgba(61, 142, 255, 0.16) 5.48%, rgba(120, 53, 255, 0.16) 105.77%);
  592. display: -ms-flexbox;
  593. }
  594. .ai_item {
  595. height: 36px;
  596. padding: 0px 8px;
  597. background: linear-gradient(89deg, rgba(61, 142, 255, 0.06) 5.48%, rgba(120, 53, 255, 0.06) 105.77%);
  598. border-radius: 8px;
  599. display: flex;
  600. align-items: center;
  601. justify-content: flex-start;
  602. cursor: pointer;
  603. margin: 8px 0px;
  604. .ai_label {
  605. font-family: "PingFang SC", "PingFang SC";
  606. font-weight: 500;
  607. font-size: 14px;
  608. color: rgb(29, 33, 41);
  609. line-height: 22px;
  610. text-align: left;
  611. flex-shrink: 0;
  612. }
  613. .ai_value {
  614. font-family: "PingFang SC", "PingFang SC";
  615. font-weight: 400;
  616. font-size: 14px;
  617. color: rgb(78, 89, 105);
  618. margin-left: 8px;
  619. overflow: hidden;
  620. text-overflow: ellipsis;
  621. white-space: nowrap;
  622. }
  623. }
  624. }
  625. }
  626. }
  627. .ai-conversation {
  628. .conversation_item {
  629. display: flex;
  630. .item_user {
  631. display: inline-block;
  632. margin-left: auto;
  633. width: auto;
  634. max-width: 640px;
  635. background: linear-gradient(89deg, #3D8EFF 0%, #7835FF 100%);
  636. border-radius: 16px 2px 16px 16px;
  637. margin-bottom: 24px;
  638. overflow: visible;
  639. white-space: normal !important;
  640. word-break: break-all !important;
  641. .aiHtml {
  642. white-space: pre-wrap;
  643. font-size: 14px;
  644. color: #FFFFFF;
  645. line-height: 22px;
  646. padding: 8px 12px;
  647. overflow: visible;
  648. white-space: normal !important;
  649. word-break: break-all !important;
  650. position: relative;
  651. }
  652. }
  653. .item_ai {
  654. margin-right: auto;
  655. width: atuo;
  656. max-width: 640px;
  657. background: #ffffff;
  658. border-radius: 2px 16px 16px 16px;
  659. margin-bottom: 24px;
  660. .aiHtml {
  661. white-space: pre-wrap;
  662. font-size: 14px;
  663. color: #1D2129;
  664. line-height: 22px;
  665. padding: 8px 12px;
  666. overflow: hidden;
  667. /* white-space: normal !important;
  668. word-break: break-all !important; */
  669. }
  670. .tools-wrap {
  671. position: relative;
  672. .item-ai-tools {
  673. display: flex;
  674. -ms-flex-align: center;
  675. align-items: center;
  676. -ms-flex-pack: justify;
  677. justify-content: space-between;
  678. height: 20px;
  679. margin-bottom: 8px;
  680. font-family: PingFang SC, PingFang SC;
  681. font-weight: 400;
  682. font-size: 12px;
  683. color: #86909C;
  684. padding: 0 12px;
  685. .tools-left {
  686. display: flex;
  687. -ms-flex-align: center;
  688. align-items: center;
  689. -ms-flex-pack: center;
  690. justify-content: center;
  691. .tool {
  692. display: flex;
  693. padding: 0 4px;
  694. height: 20px;
  695. }
  696. }
  697. .tools-right {
  698. margin-left: 12px;
  699. display: flex;
  700. .pointer {
  701. position: relative;
  702. width: 20px;
  703. height: 20px;
  704. border-radius: 4px;
  705. }
  706. }
  707. }
  708. }
  709. }
  710. }
  711. }
  712. }
  713. .tip_bg {
  714. width: 100%;
  715. height: 600px;
  716. top: 0;
  717. position: absolute;
  718. z-index: 1;
  719. }
  720. .tip_dialog {
  721. position: absolute;
  722. bottom: 69px;
  723. left: 16px;
  724. min-height: 400px;
  725. width: calc(100% - 32px);
  726. box-sizing: border-box;
  727. padding: 12px 8px 8px;
  728. background: linear-gradient(89deg, rgba(61, 142, 255, 0.4), rgba(120, 53, 255, 0.4)), rgb(255, 255, 255);
  729. box-shadow: rgba(18, 110, 254, 0.2) 0px 2px 16px 0px;
  730. border-radius: 8px;
  731. z-index: 2;
  732. .bottomItem {
  733. display: -ms-flexbox;
  734. display: flex;
  735. -ms-flex-align: center;
  736. align-items: center;
  737. gap: 8px;
  738. -ms-flex-wrap: wrap;
  739. flex-wrap: wrap;
  740. margin-bottom: 8px;
  741. .ai_bttton_wrap {
  742. display: -ms-flexbox;
  743. display: flex;
  744. -ms-flex-align: center;
  745. align-items: center;
  746. gap: 8px;
  747. .primary {
  748. background: linear-gradient(89deg, #3D8EFF 0%, #7835FF 100%);
  749. color: #fff;
  750. position: relative;
  751. .btn_icon {
  752. position: absolute;
  753. top: 6px;
  754. left: 5px;
  755. width: 16px;
  756. height: 16px;
  757. margin-right: 2px;
  758. }
  759. }
  760. .default {
  761. position: relative;
  762. .btn_icon {
  763. position: absolute;
  764. top: 6px;
  765. left: 5px;
  766. width: 16px;
  767. height: 16px;
  768. margin-right: 2px;
  769. }
  770. }
  771. button {
  772. margin: 0;
  773. padding: 0;
  774. border: 0;
  775. outline: 0;
  776. background: none;
  777. cursor: pointer;
  778. padding: 5px 10px;
  779. background: rgba(255, 255, 255, 0.6);
  780. font-family: PingFang SC, PingFang SC;
  781. font-weight: 500;
  782. color: #000;
  783. border-radius: 8px;
  784. }
  785. }
  786. }
  787. .ai_content_scroll {
  788. margin-top: 8px;
  789. padding-right: 10px;
  790. box-sizing: border-box;
  791. overflow: auto;
  792. width: 100%;
  793. max-height: 340px;
  794. .scroll_ele {
  795. list-style: none;
  796. padding: 0px;
  797. margin: 8px 0px;
  798. .ai_item {
  799. box-sizing: border-box;
  800. height: 62px;
  801. padding: 10px 12px;
  802. background: rgba(255, 255, 255, 0.7);
  803. border-radius: 8px;
  804. border: 1.5px solid transparent;
  805. cursor: pointer;
  806. margin: 8px 0px;
  807. .ai_label {
  808. font-family: "PingFang SC", "PingFang SC";
  809. font-weight: 500;
  810. font-size: 14px;
  811. color: rgb(29, 33, 41);
  812. line-height: 22px;
  813. text-align: left;
  814. }
  815. .ai_value {
  816. font-family: "PingFang SC", "PingFang SC";
  817. font-weight: 400;
  818. font-size: 12px;
  819. color: rgb(134, 144, 156);
  820. line-height: 20px;
  821. text-align: left;
  822. overflow: hidden;
  823. text-overflow: ellipsis;
  824. white-space: nowrap;
  825. }
  826. }
  827. .ai_item:hover {
  828. border: 1.5px solid transparent;
  829. background-clip: padding-box, border-box;
  830. background-origin: padding-box, border-box;
  831. background-image: -webkit-gradient(linear, left top, right top, from(#fff), to(#fff)), -webkit-gradient(linear, left top, right top, from(#3D8EFF), to(#7835FF));
  832. background-image: linear-gradient(to right, #fff, #fff), linear-gradient(90deg, #3D8EFF, #7835FF);
  833. display: -ms-flexbox;
  834. }
  835. }
  836. }
  837. }
  838. .sc-ai-dialog {
  839. position: absolute;
  840. bottom: 24px;
  841. bottom: 0px;
  842. left: 16px;
  843. right: 16px;
  844. .bottomItem {
  845. display: -ms-flexbox;
  846. display: flex;
  847. -ms-flex-align: center;
  848. align-items: center;
  849. gap: 8px;
  850. -ms-flex-wrap: wrap;
  851. flex-wrap: wrap;
  852. margin-bottom: 8px;
  853. .ai_bttton_wrap {
  854. display: -ms-flexbox;
  855. display: flex;
  856. -ms-flex-align: center;
  857. align-items: center;
  858. gap: 8px;
  859. .primary {
  860. background: linear-gradient(89deg, #3D8EFF 0%, #7835FF 100%);
  861. color: #fff;
  862. position: relative;
  863. .btn_icon {
  864. position: absolute;
  865. top: 6px;
  866. left: 5px;
  867. width: 16px;
  868. height: 16px;
  869. margin-right: 2px;
  870. }
  871. }
  872. .default {
  873. position: relative;
  874. .btn_icon {
  875. position: absolute;
  876. top: 6px;
  877. left: 5px;
  878. width: 16px;
  879. height: 16px;
  880. margin-right: 2px;
  881. }
  882. }
  883. button {
  884. margin: 0;
  885. padding: 0;
  886. border: 0;
  887. outline: 0;
  888. background: none;
  889. cursor: pointer;
  890. padding: 5px 10px;
  891. background: rgba(255, 255, 255, 0.6);
  892. font-family: PingFang SC, PingFang SC;
  893. font-weight: 500;
  894. color: #000;
  895. border-radius: 8px;
  896. }
  897. }
  898. }
  899. .textareaBox {
  900. .textarea_wrap {
  901. padding: 4.5px;
  902. border: 1.5px solid transparent;
  903. border-radius: 12px;
  904. background-clip: padding-box, border-box;
  905. background-origin: padding-box, border-box;
  906. background-image: -webkit-gradient(linear, left top, right top, from(#fff), to(#fff)), -webkit-gradient(linear, left top, right top, from(#3D8EFF), to(#7835FF));
  907. background-image: linear-gradient(to right, #fff, #fff), linear-gradient(90deg, #3D8EFF, #7835FF);
  908. display: -ms-flexbox;
  909. display: flex;
  910. -ms-flex-align: center;
  911. align-items: center;
  912. -ms-flex-pack: justify;
  913. justify-content: space-between;
  914. textarea {
  915. margin: 0;
  916. padding: 0;
  917. border: 0;
  918. outline: 0;
  919. font-size: 14px;
  920. font-family: PingFang SC, PingFang SC;
  921. font-weight: 400;
  922. color: #1D2129;
  923. background: none;
  924. resize: none;
  925. width: 100%;
  926. -webkit-box-sizing: border-box;
  927. box-sizing: border-box;
  928. line-height: 1.5;
  929. -webkit-transition: height 0.3s;
  930. transition: height 0.3s;
  931. }
  932. .send-btn-disabled {
  933. /* pointer-events: none; */
  934. /* cursor: default; */
  935. opacity: 0.5;
  936. /* pointer-events: auto !important;
  937. cursor: not-allowed !important; */
  938. }
  939. button {
  940. -ms-flex-item-align: end;
  941. align-self: flex-end;
  942. width: 40px;
  943. height: 28px;
  944. background: linear-gradient(89deg, #3DADFF 0%, #7835FF 100%);
  945. border-radius: 8px 8px 8px 8px;
  946. border: none;
  947. cursor: pointer;
  948. img {
  949. margin-top: 4px;
  950. width: 16px;
  951. height: 18px;
  952. }
  953. }
  954. }
  955. }
  956. .ai-tips {
  957. height: 24px;
  958. width: 100%;
  959. font-size: 12px;
  960. color: #A9AEB8;
  961. line-height: 24px;
  962. text-align: center;
  963. }
  964. }
  965. .ai_history_list {
  966. display: flex;
  967. flex-direction: column;
  968. padding-left: 16px;
  969. padding-right: 16px;
  970. margin-top: 16px;
  971. width: 100%;
  972. height: calc(100% - 70px);
  973. box-sizing: border-box;
  974. overflow: auto;
  975. .title {
  976. font-size: 12px;
  977. color: rgb(134, 144, 156);
  978. line-height: 20px;
  979. }
  980. .item-module {
  981. margin-bottom: 24px;
  982. .itemBg {
  983. position: relative;
  984. cursor: pointer;
  985. border-radius: 8px;
  986. .item {
  987. margin-top: 7px;
  988. background: linear-gradient(89deg, rgba(61, 142, 255, 0.06) 5.48%, rgba(120, 53, 255, 0.06) 105.77%);
  989. border-radius: 8px;
  990. .item-content {
  991. padding: 12px;
  992. font-size: 14px;
  993. color: rgb(29, 33, 41);
  994. line-height: 22px;
  995. line-break: anywhere;
  996. white-space: normal !important;
  997. word-break: break-all !important;
  998. }
  999. }
  1000. .item:hover {
  1001. background: linear-gradient(89deg, rgba(61, 142, 255, 0.16) 5.48%, rgba(120, 53, 255, 0.16) 105.77%);
  1002. border-radius: 8px;
  1003. }
  1004. .item_close {
  1005. position: absolute;
  1006. right: 0px;
  1007. top: 0px;
  1008. width: 16px;
  1009. height: 16px;
  1010. background: rgba(0, 0, 0, 0.4);
  1011. border-radius: 0px 8px;
  1012. /* display: none; */
  1013. cursor: pointer;
  1014. z-index: 1008;
  1015. .item_close_icon {
  1016. display: flex;
  1017. margin: 2px;
  1018. width: 12px;
  1019. height: 12px;
  1020. }
  1021. }
  1022. }
  1023. }
  1024. }
  1025. </style>