New file |
| | |
| | | <script setup> |
| | | import { getCurrentInstance, ref, watch, nextTick } from 'vue'; |
| | | import { useRouter } from "vue-router"; |
| | | import { get, post, postForm } from '@/utils/request.js' |
| | | import { message, Modal } from 'ant-design-vue'; |
| | | import { logout } from '@/config.js'; |
| | | import { formatMessage } from '@/utils/localeUtils.js'; |
| | | import useTableSearch from '@/utils/tableUtils.jsx'; |
| | | const context = getCurrentInstance()?.appContext.config.globalProperties; |
| | | |
| | | const open = ref(false) |
| | | const showWidth = ref("70%") |
| | | const chatContainer = ref(null); |
| | | const aiLoading = ref(false) |
| | | const messageValue = ref(null) |
| | | const messageList = ref([ |
| | | { |
| | | 'author': 'AI', |
| | | 'message': '欢迎使用中扬AI大模型智能助手', |
| | | 'type': 'str' |
| | | } |
| | | ]) |
| | | |
| | | const handleOk = () => { |
| | | |
| | | } |
| | | |
| | | const handleCancel = () => { |
| | | |
| | | } |
| | | |
| | | const openModal = () => { |
| | | open.value = true |
| | | } |
| | | |
| | | const handleSubmit = () => { |
| | | let message = messageValue.value; |
| | | let tmp = { |
| | | 'author': 'Me', |
| | | 'message': message, |
| | | 'type': 'str' |
| | | } |
| | | |
| | | messageList.value.push(tmp) |
| | | messageValue.value = '' |
| | | aiLoading.value = true |
| | | |
| | | get("http://192.168.4.61:5000/chat?message=" + message, {}).then(resp => { |
| | | let result = resp.data; |
| | | if (result.code == 200) { |
| | | let aiTmp = { |
| | | 'author': 'AI', |
| | | 'message': result.data, |
| | | 'img': result.img, |
| | | 'type': result.type |
| | | } |
| | | messageList.value.push(aiTmp) |
| | | aiLoading.value = false |
| | | } else { |
| | | let aiTmp = { |
| | | 'author': 'AI', |
| | | 'message': '抱歉,我暂时不能回答这个问题', |
| | | 'img': '', |
| | | 'type': 'str' |
| | | } |
| | | messageList.value.push(aiTmp) |
| | | aiLoading.value = false |
| | | } |
| | | |
| | | scrollToBottom() |
| | | }).catch(resp => { |
| | | let aiTmp = { |
| | | 'author': 'AI', |
| | | 'message': '抱歉,我暂时不能回答这个问题', |
| | | 'img': '', |
| | | 'type': 'str' |
| | | } |
| | | messageList.value.push(aiTmp) |
| | | aiLoading.value = false |
| | | |
| | | scrollToBottom() |
| | | }) |
| | | } |
| | | |
| | | const scrollToBottom = () => { |
| | | if (chatContainer.value) { |
| | | nextTick(() => { |
| | | setTimeout(() => { |
| | | chatContainer.value.scrollTop = chatContainer.value.scrollHeight; |
| | | }, 100); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | |
| | | </script> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'aiComponent' |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div> |
| | | <a-modal v-model:open="open" :width="showWidth" @ok="handleOk" @cancel="handleCancel"> |
| | | <div class="box" ref="chatContainer"> |
| | | <a-comment v-for="(item, index) in messageList" :key="index"> |
| | | <template #author><a>{{ item.author }}</a></template> |
| | | <template #avatar> |
| | | <a-avatar src="/public/img/logo.png" :alt="item.author" /> |
| | | </template> |
| | | <template #content> |
| | | <div v-if="item.type == 'str'"> |
| | | {{ item.message }} |
| | | </div> |
| | | <div v-else-if="item.type == 'html'" v-html="item.message"></div> |
| | | <div v-else-if="item.type == 'img'"> |
| | | <img :src="'data:image/png;base64,' + item.img" /> |
| | | </div> |
| | | </template> |
| | | </a-comment> |
| | | |
| | | <a-comment v-if="aiLoading"> |
| | | <template #author><a>AI</a></template> |
| | | <template #content> |
| | | <a-spin tip="Loading..."> |
| | | <a-alert message="AI is Loading..."></a-alert> |
| | | </a-spin> |
| | | </template> |
| | | </a-comment> |
| | | </div> |
| | | |
| | | <a-comment> |
| | | <template #content> |
| | | <a-form-item> |
| | | <a-textarea v-model:value="messageValue" :rows="4" /> |
| | | </a-form-item> |
| | | <a-form-item> |
| | | <a-button html-type="submit" type="primary" @click="handleSubmit"> |
| | | 发送 |
| | | </a-button> |
| | | </a-form-item> |
| | | </template> |
| | | </a-comment> |
| | | </a-modal> |
| | | |
| | | <a-float-button type="primary" :style="{ |
| | | right: '24px', |
| | | }" @click="openModal"> |
| | | <template #icon> |
| | | AI |
| | | </template> |
| | | </a-float-button> |
| | | </div> |
| | | </template> |
| | | |
| | | <style> |
| | | .box { |
| | | height: 768px; |
| | | overflow-y: auto; |
| | | } |
| | | </style> |