feat: 对话上传文件功能前端样式更新

This commit is contained in:
wangdan-fit2cloud 2024-11-18 18:08:12 +08:00
parent d958db0538
commit 2f03409c9f
2 changed files with 194 additions and 68 deletions

View File

@ -1,7 +1,62 @@
<template> <template>
<div class="ai-chat__operate p-16-24"> <div class="ai-chat__operate p-16-24">
<slot name="operateBefore" /> <slot name="operateBefore" />
<div class="operate-textarea flex"> <div class="operate-textarea">
<el-scrollbar max-height="136">
<div
class="p-8-12"
v-loading="localLoading"
v-if="uploadDocumentList.length || uploadImageList.length"
>
<el-space wrap>
<!-- <template v-for="(item, index) in uploadDocumentList" :key="index">
<el-card shadow="never" style="--el-card-padding: 8px" class="file cursor">
<div
class="flex align-center"
@mouseenter.stop="mouseenter(item)"
@mouseleave.stop="mouseleave()"
>
<div
@click="deleteFile(index, 'document')"
class="delete-icon color-secondary"
v-if="showDelete === item.url"
>
<el-icon><CircleCloseFilled /></el-icon>
</div>
<img :src="getImgUrl(item && item?.name)" alt="" width="24" />
<div class="ml-4 ellipsis" :title="item && item?.name">
{{ item && item?.name }}
</div>
</div>
</el-card>
</template> -->
<template v-for="(item, index) in uploadImageList" :key="index">
<div
class="file cursor border border-r-4"
v-if="item.url"
@mouseenter.stop="mouseenter(item)"
@mouseleave.stop="mouseleave()"
>
<div
@click="deleteFile(index, 'image')"
class="delete-icon color-secondary"
v-if="showDelete === item.url"
>
<el-icon><CircleCloseFilled /></el-icon>
</div>
<el-image
:src="item.url"
alt=""
fit="cover"
style="width: 40px; height: 40px; display: block"
class="border-r-4"
/>
</div>
</template>
</el-space>
</div>
</el-scrollbar>
<div class="flex">
<el-input <el-input
ref="quickInputRef" ref="quickInputRef"
v-model="inputValue" v-model="inputValue"
@ -20,12 +75,14 @@
<div class="operate flex align-center"> <div class="operate flex align-center">
<span v-if="props.applicationDetails.file_upload_enable" class="flex align-center"> <span v-if="props.applicationDetails.file_upload_enable" class="flex align-center">
<!-- accept="image/jpeg, image/png, image/gif"--> <!-- accept="image/jpeg, image/png, image/gif"-->
<el-upload <el-upload
action="#" action="#"
:auto-upload="false" :auto-upload="false"
:show-file-list="false" :show-file-list="false"
:accept="[...imageExtensions, ...documentExtensions].map((ext) => '.' + ext).join(',')" :accept="
[...imageExtensions, ...documentExtensions].map((ext) => '.' + ext).join(',')
"
:on-change="(file: any, fileList: any) => uploadFile(file, fileList)" :on-change="(file: any, fileList: any) => uploadFile(file, fileList)"
> >
<el-button text> <el-button text>
@ -63,11 +120,8 @@
</el-button> </el-button>
</div> </div>
</div> </div>
<div </div>
class="text-center" <div class="text-center" v-if="applicationDetails.disclaimer" style="margin-top: 8px">
v-if="applicationDetails.disclaimer"
style="margin-top: 8px"
>
<el-text type="info" v-if="applicationDetails.disclaimer" style="font-size: 12px"> <el-text type="info" v-if="applicationDetails.disclaimer" style="font-size: 12px">
<auto-tooltip :content="applicationDetails.disclaimer_value"> <auto-tooltip :content="applicationDetails.disclaimer_value">
{{ applicationDetails.disclaimer_value }} {{ applicationDetails.disclaimer_value }}
@ -83,7 +137,9 @@ import applicationApi from '@/api/application'
import { MsgAlert } from '@/utils/message' import { MsgAlert } from '@/utils/message'
import { type chatType } from '@/api/type/application' import { type chatType } from '@/api/type/application'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { getImgUrl } from '@/utils/utils'
import 'recorder-core/src/engine/mp3' import 'recorder-core/src/engine/mp3'
import 'recorder-core/src/engine/mp3-engine' import 'recorder-core/src/engine/mp3-engine'
import { MsgWarning } from '@/utils/message' import { MsgWarning } from '@/utils/message'
const route = useRoute() const route = useRoute()
@ -130,7 +186,6 @@ const localLoading = computed({
} }
}) })
const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp'] const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp']
const documentExtensions = ['pdf', 'docx', 'txt', 'xls', 'xlsx', 'md', 'html', 'csv'] const documentExtensions = ['pdf', 'docx', 'txt', 'xls', 'xlsx', 'md', 'html', 'csv']
const videoExtensions = ['mp4', 'avi', 'mov', 'mkv', 'flv'] const videoExtensions = ['mp4', 'avi', 'mov', 'mkv', 'flv']
@ -209,6 +264,8 @@ const inputValue = ref<string>('')
const uploadImageList = ref<Array<any>>([]) const uploadImageList = ref<Array<any>>([])
const uploadDocumentList = ref<Array<any>>([]) const uploadDocumentList = ref<Array<any>>([])
const mediaRecorderStatus = ref(true) const mediaRecorderStatus = ref(true)
const showDelete = ref('')
// //
const mediaRecorder = ref<any>(null) const mediaRecorder = ref<any>(null)
const isDisabledChart = computed( const isDisabledChart = computed(
@ -346,6 +403,21 @@ function sendChatHandle(event: any) {
inputValue.value += '\n' inputValue.value += '\n'
} }
} }
function deleteFile(index: number, val: string) {
if (val === 'image') {
uploadImageList.value.splice(index, 1)
} else if (val === 'document') {
uploadDocumentList.value.splice(index, 1)
}
}
function mouseenter(row: any) {
showDelete.value = row.url
}
function mouseleave() {
showDelete.value = ''
}
onMounted(() => { onMounted(() => {
setTimeout(() => { setTimeout(() => {
if (quickInputRef.value && mode === 'embed') { if (quickInputRef.value && mode === 'embed') {
@ -356,4 +428,14 @@ onMounted(() => {
</script> </script>
<style lang="scss" scope> <style lang="scss" scope>
@import '../../index.scss'; @import '../../index.scss';
.file {
position: relative;
overflow: inherit;
.delete-icon {
position: absolute;
right: -5px;
top: -5px;
z-index: 1;
}
}
</style> </style>

View File

@ -15,6 +15,39 @@
</div> </div>
<div class="content"> <div class="content">
<div class="text break-all pre-wrap"> <div class="text break-all pre-wrap">
<div class="mb-8" v-if="document_list.length">
<el-space wrap>
<template v-for="(item, index) in document_list" :key="index">
<el-card shadow="never" style="--el-card-padding: 8px" class="file cursor">
<div class="flex align-center">
<img :src="getImgUrl(item && item?.name)" alt="" width="24" />
<div class="ml-4 ellipsis" :title="item && item?.name">
{{ item && item?.name }}
</div>
</div>
</el-card>
</template>
</el-space>
</div>
<div class="mb-8" v-if="image_list.length">
<el-space wrap>
<template v-for="(item, index) in image_list" :key="index">
<div class="file cursor border border-r-4" v-if="item.url">
<el-image
:src="item.url"
:zoom-rate="1.2"
:max-scale="7"
:min-scale="0.2"
:preview-src-list="getAttrsArray(image_list, 'url')"
alt=""
fit="cover"
style="width: 170px; height: 170px; display: block"
class="border-r-4"
/>
</div>
</template>
</el-space>
</div>
{{ chatRecord.problem_text }} {{ chatRecord.problem_text }}
</div> </div>
</div> </div>
@ -22,13 +55,25 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { type chatType } from '@/api/type/application' import { type chatType } from '@/api/type/application'
import { onMounted } from 'vue' import { getImgUrl, getAttrsArray } from '@/utils/utils'
import { onMounted, computed } from 'vue'
const props = defineProps<{ const props = defineProps<{
application: any application: any
chatRecord: chatType chatRecord: chatType
}>() }>()
const document_list = computed(() => {
return []
})
const image_list = computed(() => {
if (props.chatRecord.execution_details?.length > 0) {
return props.chatRecord.execution_details[0].image_list
} else {
return []
}
})
onMounted(() => { onMounted(() => {
console.log(props.chatRecord.execution_details)
if (props.chatRecord.execution_details?.length > 0) { if (props.chatRecord.execution_details?.length > 0) {
props.chatRecord.execution_details[0].image_list?.forEach((image: any) => { props.chatRecord.execution_details[0].image_list?.forEach((image: any) => {
console.log('image', image.name, image.url) console.log('image', image.name, image.url)
@ -36,5 +81,4 @@ onMounted(() => {
} }
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>