@ -1,14 +1,16 @@
< script lang = "tsx" >
import { Drawer , Button , Upload , Table , Input , Progress } from 'ant-design-vue' ;
import { Drawer , Button , Upload , Table , Input , Progress , message , Select , Modal } from 'ant-design-vue' ;
const { Column } = Table ;
const { TextArea } = Input ;
const { Option } = Select ;
import CommonSelect from '@/components/common-select' ;
import ImgLazyLoad from '@/components/img-lazy-load' ;
import TextOverTips from '@/components/text-over-tips' ;
import { formatFileSize , getVideoInfo , getFileExtension , formatUploadSpeed } from '@/utils/tools' ;
import { getRawMaterialTagsList } from '@/api/all/generationWorkshop' ;
import { formatFileSize , getVideoInfo , getFileExtension } from '@/utils/tools' ;
import { getRawMaterialTagsList , postBatchRawMaterial , posRawMaterialTags } from '@/api/all/generationWorkshop' ;
import { getFilePreSignedUrl } from '@/api/all/common' ;
import icon1 from '@/assets/img/media-account/icon-delete.png' ;
@ -26,11 +28,13 @@ enum EnumUploadStatus {
}
export default defineComponent ( {
setup ( _ , { attrs , slots , expose } ) {
emits : [ 'update' ] ,
setup ( _ , { emit , expose } ) {
const visible = ref ( false ) ;
const submitLoading = ref ( false ) ;
const uploadData = ref ( [ ] ) ;
const tagData = ref ( [ ] ) ;
const modalRef = ref ( null ) ;
const uploadSuccessNum = computed ( ( ) => {
return uploadData . value . filter ( ( item ) => item . uploadStatus === EnumUploadStatus . done ) . length ;
@ -43,6 +47,80 @@ export default defineComponent({
}
} ;
const handleTagChange = ( record ) => {
console . log ( record . tag _ids ) ;
} ;
// 添加处理标签输入的函数
const handleTagInputPressEnter = async ( e , record ) => {
const inputValue = e . target . value . trim ( ) ;
if ( ! inputValue ) return ;
if ( record . tag _ids . length >= 5 ) {
message . warning ( '最多选择5个' ) ;
return ;
}
const _target = tagData . value . find ( ( item ) => item . name === inputValue ) ;
if ( _target ) {
record . tag _ids = [ ... record . tag _ids , _target . id ] ;
return ;
}
try {
const { code , data } = await posRawMaterialTags ( { name : inputValue } ) ;
if ( code === 200 && data ) {
tagData . value . push ( {
id : data . id ,
name : data . name ,
} ) ;
e . target . value = '' ;
record . tag _ids = [ ... record . tag _ids , data . id ] ;
}
} catch ( error ) {
message . error ( '添加标签失败' ) ;
}
} ;
const onCancel = ( ) => {
if ( ! uploadData . value . length ) {
onClose ( ) ;
return ;
}
modalRef . value = Modal . warning ( {
title : '确定要取消上传吗?' ,
content : '取消后上传将中断,已传输的内容不会保存' ,
cancelText : '取消' ,
okText : '确定' ,
centered : true ,
footer : (
< div class = "flex items-center justify-end mt-24px" >
< Button
onClick = { ( ) => {
modalRef . value . destroy ( ) ;
onClose ( ) ;
} }
class = "mr-12px"
>
确认取消
< / Button >
< Button
type = "primary"
onClick = { ( ) => {
modalRef . value . destroy ( ) ;
} }
>
继续上传
< / Button >
< / div >
) ,
} ) ;
} ;
const open = ( ) => {
getTagData ( ) ;
visible . value = true ;
@ -53,6 +131,8 @@ export default defineComponent({
uploadData . value = [ ] ;
tagData . value = [ ] ;
modalRef . value ? . destroy ( ) ;
modalRef . value = null ;
submitLoading . value = false ;
} ;
@ -76,18 +156,21 @@ export default defineComponent({
statusText = '文件大小超出限制' ;
}
const { fileTypeLabel , cover } = await getFileInfo ( file ) ;
const { fileTypeLabel , cover , fileType } = await getFileInfo ( file ) ;
const currentData = {
uid ,
name ,
// type,
type : fileType ,
uploadStatus : statusText ? EnumUploadStatus . error : EnumUploadStatus . uploading ,
statusText ,
percent : 0 ,
size : formatFileSize ( size ) ,
size ,
fileTypeLabel ,
tag _ids : [ ] ,
cover ,
file : '' ,
} ;
uploadData . value . push ( currentData ) ;
@ -95,7 +178,9 @@ export default defineComponent({
try {
const response = await getFilePreSignedUrl ( { suffix : getFileExtension ( name ) } ) ;
const { upload _url } = response ? . data ;
const { upload _url , file _url } = response ? . data ;
const _target = uploadData . value . find ( ( item ) => item . uid === uid ) ;
_target . file = file _url ;
if ( ! upload _url ) {
throw new Error ( '未能获取有效的预签名上传地址' ) ;
}
@ -104,7 +189,6 @@ export default defineComponent({
await axios . put ( upload _url , blob , {
headers : { 'Content-Type' : type } ,
onUploadProgress : ( progressEvent ) => {
const _target = uploadData . value . find ( ( item ) => item . uid === uid ) ;
const percentCompleted = Math . round ( progressEvent . progress * 100 ) ;
_target . percent = percentCompleted ;
@ -123,21 +207,25 @@ export default defineComponent({
if ( imageExtensions . includes ( ext ) ) {
return {
fileTypeLabel : '图片' ,
fileType : 0 ,
cover : URL . createObjectURL ( file ) ,
} ;
} else if ( videoExtensions . includes ( ext ) ) {
const { firstFrame } = await getVideoInfo ( file ) ;
return {
fileTypeLabel : '视频' ,
fileType : 1 ,
cover : firstFrame ,
} ;
} else if ( documentExtensions . includes ( ext ) ) {
return {
fileTypeLabel : '文本' ,
fileType : 2 ,
cover : icon2 ,
} ;
} else {
return {
fileType : '' ,
fileTypeLabel : '其他' ,
cover : '' ,
} ;
@ -145,10 +233,52 @@ export default defineComponent({
} ;
const onConfirm = async ( ) => {
console . log ( 'onConfirm' ) ;
const hasUploading = uploadData . value . some ( ( item ) => item . uploadStatus === EnumUploadStatus . uploading ) ;
if ( hasUploading ) {
modalRef . value = Modal . warning ( {
title : '上传未完成' ,
content : < p class = "h-22px" > 当前原料正在上传中 , 关闭弹窗将导致上传失败 , 请等待上传完成后再点击 “ 确定 ” < / p > ,
okText : '我知道了' ,
centered : true ,
} ) ;
return ;
}
const { code , data } = await postBatchRawMaterial ( { raw _materials : uploadData . value } ) ;
if ( code === 200 ) {
message . success ( '上传成功' ) ;
emit ( 'update' ) ;
onClose ( ) ;
}
} ;
const handle Delete = ( file ) => {
uploadData . value = uploadData . value . filter ( ( item ) => item . uid !== file . uid ) ;
const open DeleteModal = ( file ) => {
modalRef . value = Modal . warning ( {
title : '确定删除该文件吗?' ,
content : < p class = "h-22px" > < / p > ,
cancelText : '取消' ,
okText : '确定' ,
centered : true ,
footer : (
< div class = "flex items-center justify-end mt-24px" >
< Button
onClick = { ( ) => {
modalRef . value . destroy ( ) ;
} }
class = "mr-12px"
>
取消
< / Button >
< Button
type = "primary"
onClick = { ( ) => {
uploadData . value = uploadData . value . filter ( ( item ) => item . uid !== file . uid ) ;
modalRef . value . destroy ( ) ;
} }
>
确定
< / Button >
< / div >
) ,
} ) ;
} ;
const renderUploadStatus = ( record ) => {
@ -165,7 +295,7 @@ export default defineComponent({
< span class = "upload-text ml-26px" >
{ record . uploadStatus === EnumUploadStatus . done ? '上传成功' : '上传中' }
< / span >
< Progress percent = { record . percent } class = "m-0 p-0 " strokeColor = "#25C883" / >
< Progress percent = { record . percent } class = "m-0 p-0 " / >
< / div >
) ;
} ;
@ -173,19 +303,23 @@ export default defineComponent({
const renderUploadList = ( ) => {
if ( ! uploadData . value . length ) return null ;
console . log ( 'renderUploadList' , uploadData . value ) ;
return (
< >
< p class = "cts !color-#939499 mb-10px" >
已上传 : < span class = "!color-#211F24" > { ` ${ uploadSuccessNum . value } / ${ uploadData . value . length } ` } < / span >
< / p >
< Table ref = "tableRef" dataSource = { uploadData . value } pagination = { false } class = "manuscript-table w-100% flex-1" >
< Table
ref = "tableRef"
dataSource = { uploadData . value }
pagination = { false }
class = "w-100% flex-1"
scroll = { { y : '100%' } }
>
< Column
title = "文件名称"
dataIndex = "name"
key = "name"
width = { 347 }
width = { 385 }
ellipsis = { true }
customRender = { ( { text , record } ) => {
return (
@ -218,39 +352,62 @@ export default defineComponent({
width = { 243 }
customRender = { ( { text , record } ) => {
return (
< Common Select
v -model ={ record.tag_ids }
class = "w-full"
multiple
options = { tagData . value }
< Select
disabled ={ record. uploadStatus === EnumUploadStatus . uploading }
v -model : value = { record . tag _ids }
mode = "tags"
size = "middle"
placeholder = "请选择标签"
/ >
allowClear
class = "w-full"
showSearch
showArrow
maxTagCount = { 5 }
maxTagTextLength = { 5 }
onChnange = { ( ) => handleTagChange ( record ) }
onInputKeyDown = { ( e ) => {
// 检测回车键
if ( e . key === 'Enter' ) {
e . preventDefault ( ) ;
handleTagInputPressEnter ( e , record ) ;
}
} }
>
{ tagData . value . map ( ( item ) => (
< Option value = { item . id } key = { item . id } >
{ item . name }
< / Option >
) ) }
< / Select >
) ;
} }
/ >
< Column title = "类型" dataIndex = "fileTypeLabel" key = "fileTypeLabel" width = { 80 } / >
< Column title = "大小" dataIndex = "size" key = "size" width = { 100 } / >
< Column
title = "大小"
dataIndex = "size"
key = "size"
width = { 100 }
customRender = { ( { record } ) => {
return formatFileSize ( record . size ) ;
} }
/ >
< Column
title = "操作"
key = "action"
width = { 11 8}
width = { 80 }
fixed = "right"
align = "right"
customRender = { ( { text , record } ) => {
return (
< div class = "flex items-center" >
{ record . uploadStatus === EnumUploadStatus . uploading && (
< Button type = "text" class = "!h-22px !p-0 mr-16px" >
取消生成
< / Button >
) }
< div class = "flex items-center justify-end " >
< img
alt = ""
class = "cursor-pointer"
src = { icon1 }
width = "14"
height = "14"
onClick = { ( ) => handle Delete( record ) }
onClick = { ( ) => open DeleteModal ( record ) }
/ >
< / div >
) ;
@ -272,8 +429,8 @@ export default defineComponent({
v -model : open = { visible . value }
onClose = { onClose }
>
< section class = "content flex-1 pt-8px px-24px pb-24px" >
< div class = " rounded-16px bg-#F7F8FA p-16px flex flex-col items-center mb-24px" >
< section class = "content flex-1 pt-8px px-24px pb-24px overflow-hidden flex flex-col " >
< div class = "rounded-16px bg-#F7F8FA p-16px flex flex-col items-center mb-24px" >
< Upload
file -list = { uploadData.value }
action = "/"
@ -296,16 +453,10 @@ export default defineComponent({
< / section >
< footer class = "footer h-68px px-24px flex items-center justify-end" >
< div class = "flex items-center" >
< Button size = "large" onClick = { onClose } class = "mr-12px" >
< Button size = "large" onClick = { onCancel } class = "mr-12px" >
取消
< / Button >
< Button
size = "large"
type = "primary"
onClick = { onConfirm }
loading = { submitLoading . value }
disabled = { ! uploadSuccessNum . value }
>
< Button size = "large" type = "primary" onClick = { onConfirm } loading = { submitLoading . value } >
确定
< / Button >
< / div >