perf: url upload style
parent
97eb80882b
commit
7db2714197
|
|
@ -4,8 +4,7 @@
|
||||||
<el-button class="border-primary video-stop-button" @click="stopChat">
|
<el-button class="border-primary video-stop-button" @click="stopChat">
|
||||||
<app-icon iconName="app-video-stop" class="mr-8"></app-icon>
|
<app-icon iconName="app-video-stop" class="mr-8"></app-icon>
|
||||||
{{ $t('chat.operation.stopChat') }}
|
{{ $t('chat.operation.stopChat') }}
|
||||||
</el-button
|
</el-button>
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="operate-textarea">
|
<div class="operate-textarea">
|
||||||
|
|
@ -43,7 +42,7 @@
|
||||||
@mouseleave.stop="mouseleave()"
|
@mouseleave.stop="mouseleave()"
|
||||||
>
|
>
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<img :src="getImgUrl(item && item?.name)" alt="" width="24"/>
|
<img :src="getImgUrl(item && item?.name)" alt="" width="24" />
|
||||||
<div class="ml-4 ellipsis-1" :title="item && item?.name">
|
<div class="ml-4 ellipsis-1" :title="item && item?.name">
|
||||||
{{ item && item?.name }}
|
{{ item && item?.name }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -54,7 +53,7 @@
|
||||||
v-if="showDelete === item.url"
|
v-if="showDelete === item.url"
|
||||||
>
|
>
|
||||||
<el-icon style="font-size: 16px; top: 2px">
|
<el-icon style="font-size: 16px; top: 2px">
|
||||||
<CircleCloseFilled/>
|
<CircleCloseFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -81,7 +80,7 @@
|
||||||
@mouseleave.stop="mouseleave()"
|
@mouseleave.stop="mouseleave()"
|
||||||
>
|
>
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<img :src="getImgUrl(item && item?.name)" alt="" width="24"/>
|
<img :src="getImgUrl(item && item?.name)" alt="" width="24" />
|
||||||
<div class="ml-4 ellipsis-1" :title="item && item?.name">
|
<div class="ml-4 ellipsis-1" :title="item && item?.name">
|
||||||
{{ item && item?.name }}
|
{{ item && item?.name }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -92,7 +91,7 @@
|
||||||
v-if="showDelete === item.url"
|
v-if="showDelete === item.url"
|
||||||
>
|
>
|
||||||
<el-icon style="font-size: 16px; top: 2px">
|
<el-icon style="font-size: 16px; top: 2px">
|
||||||
<CircleCloseFilled/>
|
<CircleCloseFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -116,7 +115,7 @@
|
||||||
@mouseleave.stop="mouseleave()"
|
@mouseleave.stop="mouseleave()"
|
||||||
>
|
>
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<img :src="getImgUrl(item && item?.name)" alt="" width="24"/>
|
<img :src="getImgUrl(item && item?.name)" alt="" width="24" />
|
||||||
<div class="ml-4 ellipsis-1" :title="item && item?.name">
|
<div class="ml-4 ellipsis-1" :title="item && item?.name">
|
||||||
{{ item && item?.name }}
|
{{ item && item?.name }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -127,7 +126,7 @@
|
||||||
v-if="showDelete === item.url"
|
v-if="showDelete === item.url"
|
||||||
>
|
>
|
||||||
<el-icon style="font-size: 16px; top: 2px">
|
<el-icon style="font-size: 16px; top: 2px">
|
||||||
<CircleCloseFilled/>
|
<CircleCloseFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -147,7 +146,7 @@
|
||||||
v-if="showDelete === item.url"
|
v-if="showDelete === item.url"
|
||||||
>
|
>
|
||||||
<el-icon style="font-size: 16px; top: 2px">
|
<el-icon style="font-size: 16px; top: 2px">
|
||||||
<CircleCloseFilled/>
|
<CircleCloseFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
<el-image
|
<el-image
|
||||||
|
|
@ -174,13 +173,14 @@
|
||||||
v-if="showDelete === item.url"
|
v-if="showDelete === item.url"
|
||||||
>
|
>
|
||||||
<el-icon style="font-size: 16px; top: 2px">
|
<el-icon style="font-size: 16px; top: 2px">
|
||||||
<CircleCloseFilled/>
|
<CircleCloseFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
<video
|
<video
|
||||||
v-if="item.url"
|
v-if="item.url"
|
||||||
:src="item.url"
|
:src="item.url"
|
||||||
controls style="width: 100px; display: block"
|
controls
|
||||||
|
style="width: 100px; display: block"
|
||||||
class="border-r-6"
|
class="border-r-6"
|
||||||
autoplay
|
autoplay
|
||||||
/>
|
/>
|
||||||
|
|
@ -213,7 +213,7 @@
|
||||||
|
|
||||||
<div class="operate flex-between">
|
<div class="operate flex-between">
|
||||||
<div>
|
<div>
|
||||||
<slot name="userInput"/>
|
<slot name="userInput" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<template v-if="props.applicationDetails.stt_model_enable">
|
<template v-if="props.applicationDetails.stt_model_enable">
|
||||||
|
|
@ -223,7 +223,7 @@
|
||||||
<AppIcon v-if="isMicrophone" iconName="app-keyboard"></AppIcon>
|
<AppIcon v-if="isMicrophone" iconName="app-keyboard"></AppIcon>
|
||||||
<el-icon v-else>
|
<el-icon v-else>
|
||||||
<!-- 录音 -->
|
<!-- 录音 -->
|
||||||
<Microphone/>
|
<Microphone />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -235,13 +235,13 @@
|
||||||
v-if="recorderStatus === 'STOP'"
|
v-if="recorderStatus === 'STOP'"
|
||||||
>
|
>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Microphone/>
|
<Microphone />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<div v-else class="operate flex align-center">
|
<div v-else class="operate flex align-center">
|
||||||
<el-text type="info"
|
<el-text type="info"
|
||||||
>00:{{ recorderTime < 10 ? `0${recorderTime}` : recorderTime }}</el-text
|
>00:{{ recorderTime < 10 ? `0${recorderTime}` : recorderTime }}</el-text
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button
|
||||||
text
|
text
|
||||||
|
|
@ -257,6 +257,16 @@
|
||||||
|
|
||||||
<template v-if="recorderStatus === 'STOP' || mode === 'mobile'">
|
<template v-if="recorderStatus === 'STOP' || mode === 'mobile'">
|
||||||
<span v-if="props.applicationDetails.file_upload_enable" class="flex align-center ml-4">
|
<span v-if="props.applicationDetails.file_upload_enable" class="flex align-center ml-4">
|
||||||
|
<!-- 如果URL地址 -->
|
||||||
|
<!-- <el-button
|
||||||
|
text
|
||||||
|
:disabled="checkMaxFilesLimit() || loading"
|
||||||
|
class="mt-4"
|
||||||
|
@click="showURLSetting = true"
|
||||||
|
>
|
||||||
|
<el-icon><Paperclip /></el-icon>
|
||||||
|
</el-button> -->
|
||||||
|
<!-- 没有URL地址 -->
|
||||||
<el-upload
|
<el-upload
|
||||||
action="#"
|
action="#"
|
||||||
multiple
|
multiple
|
||||||
|
|
@ -275,18 +285,16 @@
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="break-all pre-wrap">
|
<div class="break-all pre-wrap">
|
||||||
{{ $t('chat.uploadFile.label') }}:{{
|
{{ $t('chat.uploadFile.label') }}:{{ $t('chat.uploadFile.most')
|
||||||
$t('chat.uploadFile.most')
|
}}{{ props.applicationDetails.file_upload_setting.maxFiles
|
||||||
}}{{
|
|
||||||
props.applicationDetails.file_upload_setting.maxFiles
|
|
||||||
}}{{ $t('chat.uploadFile.limit') }}
|
}}{{ $t('chat.uploadFile.limit') }}
|
||||||
{{ props.applicationDetails.file_upload_setting.fileLimit }}MB<br/>{{
|
{{ props.applicationDetails.file_upload_setting.fileLimit }}MB<br />{{
|
||||||
$t('chat.uploadFile.fileType')
|
$t('chat.uploadFile.fileType')
|
||||||
}}:{{ getAcceptList().replace(/\./g, '').replace(/,/g, '、').toUpperCase() }}
|
}}:{{ getAcceptList().replace(/\./g, '').replace(/,/g, '、').toUpperCase() }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-button text :disabled="checkMaxFilesLimit() || loading" class="mt-4">
|
<el-button text :disabled="checkMaxFilesLimit() || loading" class="mt-4">
|
||||||
<el-icon><Paperclip/></el-icon>
|
<el-icon><Paperclip /></el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
|
|
@ -309,7 +317,7 @@
|
||||||
src="@/assets/icon_send.svg"
|
src="@/assets/icon_send.svg"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
<SendIcon v-show="!isDisabledChat && !loading && !uploadLoading"/>
|
<SendIcon v-show="!isDisabledChat && !loading && !uploadLoading" />
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -323,28 +331,78 @@
|
||||||
</auto-tooltip>
|
</auto-tooltip>
|
||||||
</el-text>
|
</el-text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 弹出URL设置框 -->
|
||||||
|
<div class="popperURLSetting" v-if="showURLSetting">
|
||||||
|
<el-card shadow="always" class="border-r-8" style="--el-card-padding: 16px">
|
||||||
|
<el-form label-position="top" ref="urlFormRef" :model="urlForm">
|
||||||
|
<el-form-item>
|
||||||
|
<template #label>
|
||||||
|
<div class="flex-between">
|
||||||
|
<span>URL 地址</span>
|
||||||
|
<el-select
|
||||||
|
:teleported="false"
|
||||||
|
v-model="urlForm.type"
|
||||||
|
size="small"
|
||||||
|
style="width: 85px"
|
||||||
|
>
|
||||||
|
<el-option :label="$t('common.fileUpload.image')" value="image" />
|
||||||
|
<el-option :label="$t('common.fileUpload.audio')" value="audio" />
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-input
|
||||||
|
v-model="urlForm.source_url"
|
||||||
|
placeholder="请输入URL地址,每行一个地址"
|
||||||
|
:rows="5"
|
||||||
|
type="textarea"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div class="text-right">
|
||||||
|
<el-button @click="showURLSetting = false">{{ $t('common.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="showURLSetting = false">{{
|
||||||
|
$t('common.confirm')
|
||||||
|
}}</el-button>
|
||||||
|
</div>
|
||||||
|
<el-divider style="margin: 16px 0" />
|
||||||
|
<el-upload
|
||||||
|
action="#"
|
||||||
|
multiple
|
||||||
|
:auto-upload="false"
|
||||||
|
:show-file-list="false"
|
||||||
|
:accept="getAcceptList()"
|
||||||
|
:on-change="(file: any, fileList: any) => uploadFile(file, fileList)"
|
||||||
|
v-model:file-list="fileAllList"
|
||||||
|
ref="upload"
|
||||||
|
class="import-button"
|
||||||
|
>
|
||||||
|
<el-button class="w-full url-upload-button">本地上传</el-button>
|
||||||
|
</el-upload>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed, onMounted, nextTick, reactive, type Ref} from 'vue'
|
import { ref, computed, onMounted, nextTick, reactive, type Ref } from 'vue'
|
||||||
import {t} from '@/locales'
|
import { t } from '@/locales'
|
||||||
import Recorder from 'recorder-core'
|
import Recorder from 'recorder-core'
|
||||||
import TouchChat from './TouchChat.vue'
|
import TouchChat from './TouchChat.vue'
|
||||||
import applicationApi from '@/api/application/application'
|
import applicationApi from '@/api/application/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, useRouter} from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import {getImgUrl} from '@/utils/common'
|
import { getImgUrl } from '@/utils/common'
|
||||||
import bus from '@/bus'
|
import bus from '@/bus'
|
||||||
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'
|
||||||
import chatAPI from '@/api/chat/chat'
|
import chatAPI from '@/api/chat/chat'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const {
|
const {
|
||||||
query: {mode, question},
|
query: { mode, question },
|
||||||
} = route as any
|
} = route as any
|
||||||
const quickInputRef = ref()
|
const quickInputRef = ref()
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
|
|
@ -387,6 +445,12 @@ const localLoading = computed({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const showURLSetting = ref(false)
|
||||||
|
const urlForm = reactive({
|
||||||
|
source_url: '',
|
||||||
|
type: '',
|
||||||
|
})
|
||||||
|
|
||||||
const uploadLoading = computed(() => {
|
const uploadLoading = computed(() => {
|
||||||
return Object.values(filePromisionDict.value).length > 0
|
return Object.values(filePromisionDict.value).length > 0
|
||||||
})
|
})
|
||||||
|
|
@ -408,7 +472,7 @@ const audioExtensions = ['MP3', 'WAV', 'OGG', 'AAC', 'M4A']
|
||||||
const otherExtensions = ref(['PPT', 'DOC'])
|
const otherExtensions = ref(['PPT', 'DOC'])
|
||||||
|
|
||||||
const getAcceptList = () => {
|
const getAcceptList = () => {
|
||||||
const {image, document, audio, video, other} = props.applicationDetails.file_upload_setting
|
const { image, document, audio, video, other } = props.applicationDetails.file_upload_setting
|
||||||
let accepts: any = []
|
let accepts: any = []
|
||||||
if (image) {
|
if (image) {
|
||||||
accepts = [...imageExtensions]
|
accepts = [...imageExtensions]
|
||||||
|
|
@ -438,15 +502,15 @@ const checkMaxFilesLimit = () => {
|
||||||
return (
|
return (
|
||||||
props.applicationDetails.file_upload_setting.maxFiles <=
|
props.applicationDetails.file_upload_setting.maxFiles <=
|
||||||
uploadImageList.value.length +
|
uploadImageList.value.length +
|
||||||
uploadDocumentList.value.length +
|
uploadDocumentList.value.length +
|
||||||
uploadAudioList.value.length +
|
uploadAudioList.value.length +
|
||||||
uploadVideoList.value.length +
|
uploadVideoList.value.length +
|
||||||
uploadOtherList.value.length
|
uploadOtherList.value.length
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const filePromisionDict: any = ref<any>({})
|
const filePromisionDict: any = ref<any>({})
|
||||||
const uploadFile = async (file: any, fileList: any) => {
|
const uploadFile = async (file: any, fileList: any) => {
|
||||||
const {maxFiles, fileLimit} = props.applicationDetails.file_upload_setting
|
const { maxFiles, fileLimit } = props.applicationDetails.file_upload_setting
|
||||||
// 单次上传文件数量限制
|
// 单次上传文件数量限制
|
||||||
const file_limit_once =
|
const file_limit_once =
|
||||||
uploadImageList.value.length +
|
uploadImageList.value.length +
|
||||||
|
|
@ -612,8 +676,7 @@ const TouchEnd = (bool?: boolean) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 取消录音控制台日志
|
// 取消录音控制台日志
|
||||||
Recorder.CLog = function () {
|
Recorder.CLog = function () {}
|
||||||
}
|
|
||||||
|
|
||||||
class RecorderManage {
|
class RecorderManage {
|
||||||
recorder?: any
|
recorder?: any
|
||||||
|
|
@ -919,16 +982,16 @@ onMounted(() => {
|
||||||
// 获取当前路由信息
|
// 获取当前路由信息
|
||||||
const route = router.currentRoute.value
|
const route = router.currentRoute.value
|
||||||
// 复制query对象
|
// 复制query对象
|
||||||
const query = {...route.query}
|
const query = { ...route.query }
|
||||||
// 删除特定的参数
|
// 删除特定的参数
|
||||||
delete query.question
|
delete query.question
|
||||||
const newRoute =
|
const newRoute =
|
||||||
Object.entries(query)?.length > 0
|
Object.entries(query)?.length > 0
|
||||||
? route.path +
|
? route.path +
|
||||||
'?' +
|
'?' +
|
||||||
Object.entries(query)
|
Object.entries(query)
|
||||||
.map(([key, value]) => `${key}=${value}`)
|
.map(([key, value]) => `${key}=${value}`)
|
||||||
.join('&')
|
.join('&')
|
||||||
: route.path
|
: route.path
|
||||||
|
|
||||||
history.pushState(null, '', '/chat' + newRoute)
|
history.pushState(null, '', '/chat' + newRoute)
|
||||||
|
|
@ -1026,14 +1089,21 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.popperURLSetting {
|
||||||
|
right: 30px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.popperUserInput {
|
.popperURLSetting {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
left: 0;
|
right: 60px;
|
||||||
bottom: 50px;
|
bottom: 65px;
|
||||||
width: calc(100% - 50px);
|
width: calc(100% - 50px);
|
||||||
max-width: 400px;
|
max-width: 320px;
|
||||||
|
.url-upload-button {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,9 @@ export default {
|
||||||
image: 'Image',
|
image: 'Image',
|
||||||
audio: 'Audio',
|
audio: 'Audio',
|
||||||
video: 'Video',
|
video: 'Video',
|
||||||
|
other: 'Other',
|
||||||
|
addExtensions: 'Add Extensions',
|
||||||
|
existingExtensionsTip: 'The following extensions already exist',
|
||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
label: 'Status',
|
label: 'Status',
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,9 @@ export default {
|
||||||
image: '圖片',
|
image: '圖片',
|
||||||
audio: '音頻',
|
audio: '音頻',
|
||||||
video: '視頻',
|
video: '視頻',
|
||||||
|
other: '其他文件',
|
||||||
|
addExtensions: '添加後綴名',
|
||||||
|
existingExtensionsTip: '文件後綴已存在',
|
||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
label: '狀態',
|
label: '狀態',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue