feat: 对话框

This commit is contained in:
wangdan-fit2cloud 2023-11-28 17:39:35 +08:00
parent 4c3dbbf6af
commit f669ac2b35
4 changed files with 88 additions and 30 deletions

View File

@ -7,4 +7,9 @@ interface ApplicationFormType {
example?: string[]
dataset_id_list: string[]
}
export type { ApplicationFormType }
interface chatType {
id: string
problem_text: string
answer_text: string
}
export type { ApplicationFormType, chatType }

View File

@ -1,15 +1,12 @@
<template>
<div class="ai-dialog p-24">
<el-scrollbar>
<div class="ai-dialog__content">
<el-scrollbar ref="scrollDiv">
<div ref="dialogScrollbar" class="ai-dialog__content">
<div class="item-content mb-16">
<div class="avatar">
<AppAvatar class="avatar-gradient">
<img src="@/assets/icon_robot.svg" style="width: 54%" alt="" />
</AppAvatar>
<!-- <AppAvatar>
<img src="@/assets/user-icon.svg" style="width: 54%" alt="" />
</AppAvatar> -->
</div>
<div class="content">
@ -36,28 +33,35 @@
</el-card>
</div>
</div>
<div class="item-content mb-16">
<div class="avatar">
<AppAvatar>
<img src="@/assets/user-icon.svg" style="width: 54%" alt="" />
</AppAvatar>
</div>
<div class="content">
<div class="text">
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
<template v-for="(item, index) in chatList" :key="index">
<!-- 问题 -->
<div class="item-content mb-16 lighter">
<div class="avatar">
<AppAvatar>
<img src="@/assets/user-icon.svg" style="width: 54%" alt="" />
</AppAvatar>
</div>
<div class="content">
<div class="text">
{{ item.problem_text }}
</div>
</div>
</div>
</div>
<div class="item-content mb-16">
<div class="avatar">
<AppAvatar class="avatar-gradient">
<img src="@/assets/icon_robot.svg" style="width: 54%" alt="" />
</AppAvatar>
<!-- 回答 -->
<div class="item-content mb-16 lighter">
<div class="avatar">
<AppAvatar class="avatar-gradient">
<img src="@/assets/icon_robot.svg" style="width: 54%" alt="" />
</AppAvatar>
</div>
<div class="content">
<div class="flex" v-if="!item.answer_text">
<el-card shadow="always" class="dialog-card"> {{ '回答中...' }} </el-card>
</div>
<el-card v-else shadow="always" class="dialog-card"> {{ item.answer_text }} </el-card>
</div>
</div>
<div class="content">
<el-card shadow="always" class="dialog-card"> XXXXXXXXX </el-card>
</div>
</div>
</template>
</div>
</el-scrollbar>
<div class="ai-dialog__operate p-24">
@ -67,13 +71,15 @@
type="textarea"
placeholder="请输入"
:autosize="{ minRows: 1, maxRows: 8 }"
@keydown.enter="sendChatHandle($event)"
:disabled="loading"
/>
<div class="operate" v-loading="loading">
<el-button
text
class="sent-button"
:disabled="!(inputValue && data?.name && data?.model_id)"
@click="chatMessage"
@click="sendChatHandle"
>
<img
v-show="!(inputValue && data?.name && data?.model_id)"
@ -85,7 +91,6 @@
src="@/assets/icon_send_colorful.svg"
alt=""
/>
<!-- <AppIcon iconName="app-send"></AppIcon> -->
</el-button>
</div>
</div>
@ -93,22 +98,40 @@
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ref, nextTick, onUpdated } from 'vue'
import applicationApi from '@/api/application'
import type { chatType } from '@/api/type/application'
import { randomId } from '@/utils/utils'
const props = defineProps({
data: {
type: Object,
default: () => {}
}
})
const scrollDiv = ref()
const dialogScrollbar = ref()
const loading = ref(false)
const inputValue = ref('')
const chartOpenId = ref('')
const chatList = ref<chatType[]>([])
function quickProblemHandel(val: string) {
inputValue.value = val
}
function sendChatHandle(event: any) {
if (!event.ctrlKey) {
// ctrl
event.preventDefault()
chatMessage()
} else {
// ctrl+
inputValue.value += '\n'
}
}
/**
* 对话
*/
@ -131,10 +154,18 @@ function getChartOpenId() {
}
function chatMessage() {
loading.value = true
if (!chartOpenId.value) {
getChartOpenId()
} else {
applicationApi.postChatMessage(chartOpenId.value, inputValue.value).then(async (response) => {
const randomNum = randomId()
chatList.value.push({
id: randomNum,
problem_text: inputValue.value,
answer_text: ''
})
inputValue.value = ''
const reader = response.body.getReader()
while (true) {
const { done, value } = await reader.read()
@ -144,11 +175,26 @@ function chatMessage() {
}
const decoder = new TextDecoder('utf-8')
const str = decoder.decode(value, { stream: true })
console.log('value', JSON.parse(str.replace('data:', '')))
// console.log(JSON?.parse(str.replace('data:', '')))
const content = JSON?.parse(str.replace('data:', ''))?.content
if (content) {
chatList.value[chatList.value.findIndex((v) => v.id === randomNum)].answer_text += content
}
}
})
}
}
//
function handleScrollBottom() {
nextTick(() => {
scrollDiv.value.setScrollTop(dialogScrollbar.value.scrollHeight)
})
}
onUpdated(() => {
handleScrollBottom()
})
</script>
<style lang="scss" scoped>
.ai-dialog {
@ -160,6 +206,7 @@ function chatMessage() {
position: relative;
padding-right: 20px;
padding-top: 0;
color: var(--app-text-color);
&__content {
width: 99%;
padding-bottom: 96px;

View File

@ -38,7 +38,6 @@ instance.interceptors.request.use(
//设置响应拦截器
instance.interceptors.response.use(
(response: any) => {
console.log('instance_response', response)
if (response.data) {
if (response.status !== 200 && !(response.data instanceof Blob)) {
MsgError(response.data.message)

View File

@ -19,6 +19,13 @@ export function filesize(size: number) {
return (size / Math.pow(num, 4)).toFixed(2) + 'T' //T
}
/*
id
*/
export const randomId = function () {
return Math.floor(Math.random() * 10000) + ''
}
/*
*/