11<template >
22 <div class =" ai-chat__operate p-16-24" >
33 <slot name =" operateBefore" />
4- <div class =" operate-textarea flex" >
5- <el-input
6- ref =" quickInputRef"
7- v-model =" inputValue"
8- :placeholder ="
9- startRecorderTime
10- ? '说话中...'
11- : recorderLoading
12- ? '转文字中...'
13- : '请输入问题,Ctrl+Enter 换行,Enter发送'
14- "
15- :autosize =" { minRows: 1, maxRows: isMobile ? 4 : 10 }"
16- type =" textarea"
17- :maxlength =" 100000"
18- @keydown.enter =" sendChatHandle($event)"
19- />
4+ <div class =" operate-textarea" >
5+ <el-scrollbar max-height =" 136" >
6+ <div
7+ class =" p-8-12"
8+ v-loading =" localLoading"
9+ v-if =" uploadDocumentList.length || uploadImageList.length"
10+ >
11+ <el-space wrap >
12+ <!-- <template v-for="(item, index) in uploadDocumentList" :key="index">
13+ <el-card shadow="never" style="-- el-card-padding: 8px" class="file cursor">
14+ <div
15+ class="flex align-center"
16+ @mouseenter.stop="mouseenter(item)"
17+ @mouseleave.stop="mouseleave()"
18+ >
19+ <div
20+ @click="deleteFile(index, 'document')"
21+ class="delete-icon color-secondary"
22+ v-if="showDelete === item.url"
23+ >
24+ <el-icon><CircleCloseFilled /></el-icon>
25+ </div>
26+ <img :src="getImgUrl(item && item?.name)" alt="" width="24" />
27+ <div class="ml-4 ellipsis" :title="item && item?.name">
28+ {{ item && item?.name }}
29+ </div>
30+ </div>
31+ </el-card>
32+ </template> -->
33+ <template v-for =" (item , index ) in uploadImageList " :key =" index " >
34+ <div
35+ class =" file cursor border border-r-4"
36+ v-if =" item.url"
37+ @mouseenter.stop =" mouseenter(item)"
38+ @mouseleave.stop =" mouseleave()"
39+ >
40+ <div
41+ @click =" deleteFile(index, 'image')"
42+ class =" delete-icon color-secondary"
43+ v-if =" showDelete === item.url"
44+ >
45+ <el-icon ><CircleCloseFilled /></el-icon >
46+ </div >
47+ <el-image
48+ :src =" item.url"
49+ alt =" "
50+ fit =" cover"
51+ style =" width : 40px ; height : 40px ; display : block "
52+ class =" border-r-4"
53+ />
54+ </div >
55+ </template >
56+ </el-space >
57+ </div >
58+ </el-scrollbar >
59+ <div class =" flex" >
60+ <el-input
61+ ref =" quickInputRef"
62+ v-model =" inputValue"
63+ :placeholder ="
64+ startRecorderTime
65+ ? '说话中...'
66+ : recorderLoading
67+ ? '转文字中...'
68+ : '请输入问题,Ctrl+Enter 换行,Enter发送'
69+ "
70+ :autosize =" { minRows: 1, maxRows: isMobile ? 4 : 10 }"
71+ type =" textarea"
72+ :maxlength =" 100000"
73+ @keydown.enter =" sendChatHandle($event)"
74+ />
2075
21- <div class =" operate flex align-center" >
22- <span v-if =" props.applicationDetails.file_upload_enable" class =" flex align-center" >
23- <!-- accept="image/jpeg, image/png, image/gif"-->
24- <el-upload
25- action =" #"
26- :auto-upload =" false"
27- :show-file-list =" false"
28- :accept =" [...imageExtensions, ...documentExtensions].map((ext) => '.' + ext).join(',')"
29- :on-change =" (file: any, fileList: any) => uploadFile(file, fileList)"
30- >
31- <el-button text >
32- <el-icon ><Paperclip /></el-icon >
33- </el-button >
34- </el-upload >
35- <el-divider direction =" vertical" />
36- </span >
37- <span v-if =" props.applicationDetails.stt_model_enable" class =" flex align-center" >
38- <el-button text v-if =" mediaRecorderStatus" @click =" startRecording" >
39- <el-icon >
40- <Microphone />
41- </el-icon >
42- </el-button >
43- <div v-else class =" operate flex align-center" >
44- <el-text type =" info"
45- >00:{{ recorderTime < 10 ? `0${recorderTime}` : recorderTime }}</el-text
76+ <div class =" operate flex align-center" >
77+ <span v-if =" props.applicationDetails.file_upload_enable" class =" flex align-center" >
78+ <!-- accept="image/jpeg, image/png, image/gif"-->
79+ <el-upload
80+ action =" #"
81+ :auto-upload =" false"
82+ :show-file-list =" false"
83+ :accept ="
84+ [...imageExtensions, ...documentExtensions].map((ext) => '.' + ext).join(',')
85+ "
86+ :on-change =" (file: any, fileList: any) => uploadFile(file, fileList)"
4687 >
47- <el-button text type =" primary" @click =" stopRecording" :loading =" recorderLoading" >
48- <AppIcon iconName =" app-video-stop" ></AppIcon >
88+ <el-button text >
89+ <el-icon ><Paperclip /></el-icon >
90+ </el-button >
91+ </el-upload >
92+ <el-divider direction =" vertical" />
93+ </span >
94+ <span v-if =" props.applicationDetails.stt_model_enable" class =" flex align-center" >
95+ <el-button text v-if =" mediaRecorderStatus" @click =" startRecording" >
96+ <el-icon >
97+ <Microphone />
98+ </el-icon >
4999 </el-button >
50- </div >
51- <el-divider v-if =" !startRecorderTime && !recorderLoading" direction =" vertical" />
52- </span >
100+ <div v-else class =" operate flex align-center" >
101+ <el-text type =" info"
102+ >00:{{ recorderTime < 10 ? `0${recorderTime}` : recorderTime }}</el-text
103+ >
104+ <el-button text type =" primary" @click =" stopRecording" :loading =" recorderLoading" >
105+ <AppIcon iconName =" app-video-stop" ></AppIcon >
106+ </el-button >
107+ </div >
108+ <el-divider v-if =" !startRecorderTime && !recorderLoading" direction =" vertical" />
109+ </span >
53110
54- <el-button
55- v-if =" !startRecorderTime && !recorderLoading"
56- text
57- class =" sent-button"
58- :disabled =" isDisabledChart || loading"
59- @click =" sendChatHandle"
60- >
61- <img v-show =" isDisabledChart || loading" src =" @/assets/icon_send.svg" alt =" " />
62- <SendIcon v-show =" !isDisabledChart && !loading" />
63- </el-button >
111+ <el-button
112+ v-if =" !startRecorderTime && !recorderLoading"
113+ text
114+ class =" sent-button"
115+ :disabled =" isDisabledChart || loading"
116+ @click =" sendChatHandle"
117+ >
118+ <img v-show =" isDisabledChart || loading" src =" @/assets/icon_send.svg" alt =" " />
119+ <SendIcon v-show =" !isDisabledChart && !loading" />
120+ </el-button >
121+ </div >
64122 </div >
65123 </div >
66- <div
67- class =" text-center"
68- v-if =" applicationDetails.disclaimer"
69- style =" margin-top : 8px "
70- >
124+ <div class =" text-center" v-if =" applicationDetails.disclaimer" style =" margin-top : 8px " >
71125 <el-text type =" info" v-if =" applicationDetails.disclaimer" style =" font-size : 12px " >
72126 <auto-tooltip :content =" applicationDetails.disclaimer_value" >
73127 {{ applicationDetails.disclaimer_value }}
@@ -83,7 +137,9 @@ import applicationApi from '@/api/application'
83137import { MsgAlert } from ' @/utils/message'
84138import { type chatType } from ' @/api/type/application'
85139import { useRoute } from ' vue-router'
140+ import { getImgUrl } from ' @/utils/utils'
86141import ' recorder-core/src/engine/mp3'
142+
87143import ' recorder-core/src/engine/mp3-engine'
88144import { MsgWarning } from ' @/utils/message'
89145const route = useRoute ()
@@ -130,7 +186,6 @@ const localLoading = computed({
130186 }
131187})
132188
133-
134189const imageExtensions = [' jpg' , ' jpeg' , ' png' , ' gif' , ' bmp' ]
135190const documentExtensions = [' pdf' , ' docx' , ' txt' , ' xls' , ' xlsx' , ' md' , ' html' , ' csv' ]
136191const videoExtensions = [' mp4' , ' avi' , ' mov' , ' mkv' , ' flv' ]
@@ -209,6 +264,8 @@ const inputValue = ref<string>('')
209264const uploadImageList = ref <Array <any >>([])
210265const uploadDocumentList = ref <Array <any >>([])
211266const mediaRecorderStatus = ref (true )
267+ const showDelete = ref (' ' )
268+
212269// 定义响应式引用
213270const mediaRecorder = ref <any >(null )
214271const isDisabledChart = computed (
@@ -346,6 +403,21 @@ function sendChatHandle(event: any) {
346403 inputValue .value += ' \n '
347404 }
348405}
406+
407+ function deleteFile(index : number , val : string ) {
408+ if (val === ' image' ) {
409+ uploadImageList .value .splice (index , 1 )
410+ } else if (val === ' document' ) {
411+ uploadDocumentList .value .splice (index , 1 )
412+ }
413+ }
414+ function mouseenter(row : any ) {
415+ showDelete .value = row .url
416+ }
417+ function mouseleave() {
418+ showDelete .value = ' '
419+ }
420+
349421onMounted (() => {
350422 setTimeout (() => {
351423 if (quickInputRef .value && mode === ' embed' ) {
@@ -356,4 +428,14 @@ onMounted(() => {
356428 </script >
357429<style lang="scss" scope>
358430@import ' ../../index.scss' ;
431+ .file {
432+ position : relative ;
433+ overflow : inherit ;
434+ .delete-icon {
435+ position : absolute ;
436+ right : -5px ;
437+ top : -5px ;
438+ z-index : 1 ;
439+ }
440+ }
359441 </style >
0 commit comments