提交 dadb1266 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 b4a2b124
...@@ -12,32 +12,36 @@ const form = reactive({ ...@@ -12,32 +12,36 @@ const form = reactive({
name: '0', name: '0',
classification: '' classification: ''
}) })
defineProps({
isShowBatchImport: {
type: Boolean
}
})
interface Emits { interface Emits {
(e: 'update:isShowBatchImport', isShowBatchImport: boolean): void (e: 'update:modelValue', modelValue: boolean): void
(e: 'update'): void (e: 'update'): void
} }
const uploadMultipleVideoRef = ref()
const handleConfirm = () => { const handleConfirm = () => {
emit('update:isShowBatchImport', false) emit('update:modelValue', false)
emit('update') emit('update')
} }
const handleCancel = () => { const handleCancel = () => {
if (closeStatus.value !== false) { const fileList = uploadMultipleVideoRef.value?.uploader?._uploadList || []
emit('update:isShowBatchImport', false) if (fileList.length) {
for (const item of fileList) {
if (item.state === 'Uploading') {
return ElMessage.error('请先完成上传')
}
}
} }
emit('update:modelValue', false)
} }
// 上传视频成功 // 上传视频成功
const uploadVideo = (data: any) => { const uploadVideo = (data: any) => {
const { file, videoId } = data
const params = { const params = {
name: data.name.slice(0, data.name.lastIndexOf('.')), name: file.name.slice(0, file.name.lastIndexOf('.')),
source: '2', source: '2',
classification: form.classification, classification: form.classification,
knowledge_points: '', knowledge_points: '',
source_id: data.videoId, source_id: videoId,
cover: '' cover: ''
} }
createVideo(params).then(() => { createVideo(params).then(() => {
...@@ -49,7 +53,7 @@ const handleClose = (val: any) => { ...@@ -49,7 +53,7 @@ const handleClose = (val: any) => {
} }
</script> </script>
<template> <template>
<el-dialog :model-value="isShowBatchImport" title="批量导入视频" :before-close="handleCancel"> <el-dialog title="批量导入视频" :close-on-click-modal="false" :before-close="handleCancel">
<el-form :model="form" label-suffix=":"> <el-form :model="form" label-suffix=":">
<el-form-item label="视频分类" prop="classification"> <el-form-item label="视频分类" prop="classification">
<el-tree-select <el-tree-select
...@@ -64,7 +68,7 @@ const handleClose = (val: any) => { ...@@ -64,7 +68,7 @@ const handleClose = (val: any) => {
/> />
</el-form-item> </el-form-item>
<el-form-item label="视频文件" prop="source_id" v-if="form.classification !== ''"> <el-form-item label="视频文件" prop="source_id" v-if="form.classification !== ''">
<UploadMultipleVideo @upload="uploadVideo" @canClose="handleClose" /> <UploadMultipleVideo @upload="uploadVideo" @canClose="handleClose" ref="uploadMultipleVideoRef" />
</el-form-item> </el-form-item>
<el-form-item label="视频名称" prop="name"> <el-form-item label="视频名称" prop="name">
<el-radio-group v-model="form.name"> <el-radio-group v-model="form.name">
...@@ -73,11 +77,8 @@ const handleClose = (val: any) => { ...@@ -73,11 +77,8 @@ const handleClose = (val: any) => {
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<span> <el-button type="primary" @click="handleConfirm" :disabled="closeStatus === false">保存</el-button>
{{ closeStatus }} <el-button @click="handleCancel" :disabled="closeStatus === false">取消</el-button>
<el-button type="primary" @click="handleConfirm" :disabled="closeStatus === false">保存</el-button>
<el-button @click="handleCancel" :disabled="closeStatus === false">取消</el-button>
</span>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
......
<script setup lang="ts"> <script setup lang="ts">
import VideoDetail from './VideoDetail.vue' import VideoDetail from './VideoDetail.vue'
import { getCreateAuth, updateAuth } from '@/api/base' import { getCreateAuth, updateAuth } from '@/api/base'
import { ElMessage } from 'element-plus'
const idShowMore = ref(false) const idShowMore = ref(false)
const props = defineProps({
createFlag: { // uploadInfo 包含要上传的文件信息
type: Number interface UploadInfo {
} bucket: string
}) checkpoint: { file: File; name: string; fileSize: number; partSize: number; uploadId: string }
/** endpoint: string
* upload 上传状态 {code: -1(待上传)0(成功) 1(开始上传) 2(上传失败), msg: '上传信息'} file: File
* progress 上传进度 fileHash: string
**/ isImage: boolean
interface IUpload { loaded: number
id?: number object: string
code: number region: string
name?: string retry: boolean
msg?: string ri: string
progress?: number state: string
videoId?: string userData: string
videoId: string
videoInfo: any
progress: number
} }
let uploadData = $ref<IUpload>({ code: -1 })
let uploadData1 = $ref<IUpload[]>([])
const emit = defineEmits(['upload', 'canClose']) const emit = defineEmits(['upload', 'canClose'])
const form: any = reactive({
timeout: '', let uploader = createUploader()
partSize: '', let fileList = $ref<UploadInfo[]>([])
parallel: '',
retryCount: '', const fileChange = (event: Event) => {
retryDuration: '', const element = event.currentTarget as HTMLInputElement
region: 'cn-shanghai', let files: FileList | null = element.files
userId: '1303984639806000', if (!files) return
file: null, for (const file of files) {
authProgress: 0, uploader.addFile(file, null, null, null, '{"Vod":{}}')
uploader: null,
statusText: ''
})
const fileChange = (e: any) => {
if (props.createFlag === 1) {
form.file = e.target.files[0]
if (form.file.name.indexOf('.mp4') === -1) {
ElMessage.warning('请上传mp4格式视频')
return
}
var userData = '{"Vod":{}}'
if (form.uploader) {
form.uploader.stopUpload()
form.authProgress = 0
form.statusText = ''
}
form.uploader = createUploader()
form.uploader.addFile(form.file, null, null, null, userData)
form.uploader.startUpload()
} else {
console.log(e.target.files)
form.file = e.target.files
form.file.forEach((item: any) => {
if (item.name.indexOf('.mp4') === -1) {
ElMessage('请上传mp4格式视频')
} else {
var userData = '{"Vod":{}}'
if (form.uploader) {
form.uploader.stopUpload()
form.authProgress = 0
form.statusText = ''
}
setTimeout(() => {
form.uploader = createUploader()
form.uploader.addFile(item, null, null, null, userData)
form.uploader.startUpload()
}, 1000)
}
})
} }
uploader.startUpload()
fileList = uploader._uploadList
} }
let id = ref(0) function updateFileList(uploadInfo: UploadInfo) {
const createUploader: any = () => { if (!uploadInfo) return
const w = window as any fileList = fileList.map(item => {
// for if (item.ri === uploadInfo.ri) {
const uploader = new w.AliyunUpload.Vod({ return { ...item, ...uploadInfo }
timeout: form.timeout || 60000,
partSize: form.partSize || 1048576,
parallel: form.parallel || 5,
retryCount: form.retryCount || 3,
retryDuration: form.retryDuration || 2,
region: form.region,
userId: form.userId,
// 开始上传
onUploadstarted: function (uploadInfo: any) {
console.log(window.localStorage.fileData)
const fileData = JSON.parse(window.localStorage.fileData || '{}')
console.log(fileData.sourceId)
// 判断有没有上传过
const isFile = !!fileData.sourceId
if (!isFile) {
// 没上传过请求凭证上传
getCreateAuth({ title: uploadInfo.file.name, file_name: uploadInfo.file.name }).then((data: any) => {
window.localStorage.fileData = JSON.stringify({
uploadAuth: data.data.upload_auth,
uploadAddress: data.data.upload_address,
videoId: data.data.source_id,
fileName: uploadInfo.file.name,
fileSize: uploadInfo.file.size
})
uploader.setUploadAuthAndAddress(
uploadInfo,
data.data.upload_auth,
data.data.upload_address,
data.data.source_id
)
})
} else {
console.log(fileData, uploadInfo)
// 上传过判断一下上次上传的文件和本次上传的文件一不一样,一样的话继续上传
if (fileData.fileName === uploadInfo.file.name && fileData.fileSize === uploadInfo.file.size) {
uploader.setUploadAuthAndAddress(uploadInfo, fileData.uploadAuth, fileData.uploadAddress, fileData.videoId)
} else {
getCreateAuth({ title: uploadInfo.file.name, file_name: uploadInfo.file.name }).then((data: any) => {
uploader.setUploadAuthAndAddress(
uploadInfo,
data.data.upload_auth,
data.data.upload_address,
data.data.source_id
)
})
}
}
if (props.createFlag === 1) {
uploadData = {
code: 1,
name: uploadInfo.file.name,
msg: '开始上传'
}
} else {
uploadData1.push({
code: 1,
name: uploadInfo.file.name,
msg: '开始上传'
})
emit('canClose', { closeStatus: false })
}
},
// 文件上传成功
onUploadSucceed: function (uploadInfo: any) {
const fileData = window.localStorage.fileData ? JSON.parse(window.localStorage.fileData) : {}
if (props.createFlag === 1) {
uploadData = {
code: 0,
name: uploadInfo.file.name,
videoId: fileData.videoId,
msg: '上传成功'
}
} else {
const findIndex = uploadData1.findIndex(item => item.name === uploadInfo.file.name)
uploadData1[findIndex] = {
code: 0,
name: uploadInfo.file.name,
videoId: fileData.videoId,
msg: '上传成功'
}
}
emit('upload', { videoId: fileData.videoId, name: uploadInfo.file.name })
emit('canClose', { closeStatus: true })
},
// 文件上传失败
// code:any, message:any
onUploadFailed: function (uploadInfo: any) {
if (props.createFlag === 1) {
uploadData = {
code: 2,
name: uploadInfo.file.name,
msg: '文件上传失败'
}
} else {
const findIndex = uploadData1.findIndex(item => item.id === id.value)
uploadData1[findIndex] = {
id: id.value,
code: 2,
name: uploadInfo.file.name,
msg: '文件上传失败'
}
}
},
// 文件上传进度,单位:字节, 可以在这个函数中拿到上传进度并显示在页面上
onUploadProgress: function (uploadInfo: any, totalSize: any, progress: any) {
let progressPercent = Math.ceil(progress * 100)
form.authProgress = progressPercent
if (props.createFlag === 1) {
uploadData.progress = progressPercent
} else {
const findIndex = uploadData1.findIndex(item => item.name === uploadInfo.file.name)
uploadData1[findIndex].progress = progressPercent
}
},
// 上传凭证超时
onUploadTokenExpired: function (uploadInfo: any) {
const fileData = JSON.parse(window.localStorage.fileData || '{}')
updateAuth({ source_id: fileData.videoId }).then(({ data }) => {
let uploadAuth = data.UploadAuth
window.localStorage.fileData = JSON.stringify({
uploadAuth: data.data.upload_auth,
uploadAddress: data.data.upload_address,
videoId: data.data.source_id,
fileName: uploadInfo.file.name,
fileSize: uploadInfo.file.size
})
uploader.resumeUploadWithAuth(uploadAuth)
})
} }
return item
})
}
function createUploader() {
return new window['AliyunUpload'].Vod({
//userID,必填,您可以使用阿里云账号访问账号中心(https://account.console.aliyun.com/),即可查看账号ID
userId: '1303984639806000',
//上传到视频点播的地域,默认值为'cn-shanghai',
//eu-central-1,ap-southeast-1
region: 'cn-shanghai',
//分片大小默认1 MB,不能小于100 KB(100*1024)
partSize: 1048576,
//并行上传分片个数,默认5
parallel: 5,
//网络原因失败时,重新上传次数,默认为3
retryCount: 3,
//网络原因失败时,重新上传间隔时间,默认为2秒
retryDuration: 2,
//开始上传
onUploadstarted: onUploadStarted,
//文件上传成功
onUploadSucceed: onUploadSucceed,
//文件上传失败
onUploadFailed: onUploadFailed,
//文件上传进度,单位:字节
onUploadProgress: onUploadProgress,
//上传凭证或STS token超时
onUploadTokenExpired: onUploadTokenExpired,
//全部文件上传结束
onUploadEnd: onUploadEnd
})
}
// 开始上传
function onUploadStarted(uploadInfo: UploadInfo) {
console.log('onUploadStarted', uploadInfo)
getCreateAuth({ title: uploadInfo.file.name, file_name: uploadInfo.file.name }).then(res => {
uploader.setUploadAuthAndAddress(uploadInfo, res.data.upload_auth, res.data.upload_address, res.data.source_id)
})
updateFileList(uploadInfo)
}
// 文件上传成功
function onUploadSucceed(uploadInfo: UploadInfo) {
console.log('onUploadSucceed', uploadInfo)
updateFileList(uploadInfo)
emit('upload', uploadInfo)
}
//文件上传失败
function onUploadFailed(uploadInfo: UploadInfo, code: number, message: string) {
console.log('onUploadFailed', uploadInfo, code, message)
updateFileList(uploadInfo)
}
//文件上传进度,单位:字节
function onUploadProgress(uploadInfo: UploadInfo, totalSize: number, loadedPercent: number) {
console.log('onUploadProgress', uploadInfo.file.name, uploadInfo, totalSize, loadedPercent)
updateFileList(uploadInfo)
}
//上传凭证或STS token超时
function onUploadTokenExpired(uploadInfo: UploadInfo) {
console.log('onUploadTokenExpired', uploadInfo)
updateAuth({ source_id: uploadInfo.videoId }).then(res => {
uploader.resumeUploadWithAuth(res.data.UploadAuth)
}) })
return uploader updateFileList(uploadInfo)
} }
// 全部文件上传结束
function onUploadEnd(uploadInfo: UploadInfo) {
console.log('onUploadEnd', uploadInfo)
updateFileList(uploadInfo)
}
const handleView = () => { const handleView = () => {
idShowMore.value = true idShowMore.value = true
} }
// 进度条
function percentage(value: number) {
return parseFloat((value ? value * 100 : 0).toFixed(2))
}
defineExpose({ uploader, fileList })
</script> </script>
<template> <template>
<div v-if="props.createFlag === 1"> <div class="upload-video" style="display: flex; flex-direction: column; align-items: flex-start">
<div class="upload-video"> <div class="upload-btn">
<div class="upload-btn"> 本地文件
本地文件 <input accept=".mp4" type="file" id="fileUpload" multiple @change="fileChange" />
<!-- accept=".mp4" -->
<input accept=".mp4" type="file" id="fileUpload" @change="fileChange($event)" />
</div>
<div class="demo-progress" v-if="uploadData.code === 1">
<el-progress style="width: 340px" :percentage="uploadData.progress" />
</div>
<div class="error video-info" v-if="uploadData.code === 2">
<div class="name">上传失败(请重新选择文件进行上传)</div>
</div>
<div class="video-info" v-if="uploadData.code === 0">
<div class="name">{{ uploadData.name }}</div>
</div>
</div> </div>
<div class="tips">推荐视频格式:帧率为25fps\输出码率为4M\输出格式为mp4,建议采用格式工厂等工具处理后上传。</div> <div class="tips">推荐视频格式:帧率为25fps\输出码率为4M\输出格式为mp4,建议采用格式工厂等工具处理后上传。</div>
</div>
<div v-else>
<div class="upload-video" style="display: flex; flex-direction: column; align-items: flex-start">
<div class="upload-btn">
本地文件
<input accept=".mp4" type="file" id="fileUpload" @change="fileChange($event)" multiple />
</div>
<div class="tips">推荐视频格式:帧率为25fps\输出码率为4M\输出格式为mp4,建议采用格式工厂等工具处理后上传。</div>
<div v-for="(item, index) in uploadData1" :key="index" style="display: flex; flex-direction: column"> <div v-for="(item, index) in fileList" :key="index">
<div class="demo-progress" v-if="item.code === 1"> <div>
<span style="min-width: 340px">{{ item.name }}</span> <span>{{ item.file.name }}</span>
<el-progress style="width: 200px" :percentage="item.progress" /> <el-progress style="width: 200px" :percentage="percentage(item.loaded)" />
</div>
<div class="error video-info" v-if="item.code === 2">
<div class="name">上传失败(请重新选择文件进行上传)</div>
</div>
<div class="video-info" v-if="item.code === 0">
<div class="name1">{{ item.name }}</div>
</div>
</div> </div>
<el-link type="primary" v-if="uploadData1.length > 3" @click="handleView"
>{{ uploadData1.length }}个文件,查看更多</el-link
>
</div> </div>
<el-link type="primary" v-if="fileList.length > 3" @click="handleView"
>{{ fileList.length }}个文件,查看更多</el-link
>
</div> </div>
<VideoDetail :videoList="uploadData1" v-model:idShowMore="idShowMore" v-if="idShowMore === true" /> <VideoDetail :videoList="fileList" v-model="idShowMore" v-if="idShowMore === true" />
</template> </template>
<style lang="scss"> <style lang="scss">
.demo-progress { .demo-progress {
......
<script lang="ts" setup> <script lang="ts" setup>
const emit = defineEmits<Emits>() interface UploadInfo {
bucket: string
checkpoint: { file: File; name: string; fileSize: number; partSize: number; uploadId: string }
endpoint: string
file: File
fileHash: string
isImage: boolean
loaded: number
object: string
region: string
retry: boolean
ri: string
state: string
userData: string
videoId: string
videoInfo: any
progress: number
}
interface Props {
videoList: UploadInfo[]
}
interface Emits {
(e: 'update:modelValue', modelValue: boolean): void
}
const props = defineProps<Props>() const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const currentPage = ref(1) const currentPage = ref(1)
const page = reactive({ const page = reactive({
size: 10, size: 10,
currentPage: 1 currentPage: 1
}) })
interface IUpload {
id?: number
code: number
name?: string
msg?: string
progress?: number
videoId?: string
}
interface Props {
idShowMore: boolean
videoList: IUpload[]
}
interface Emits {
(e: 'update:idShowMore', isShowBatchImport: boolean): void
}
const handleCancel = () => { const handleCancel = () => {
emit('update:idShowMore', false) emit('update:modelValue', false)
} }
const handleSizeChange = (val: any) => { const handleSizeChange = (val: any) => {
page.size = val page.size = val
...@@ -33,12 +41,12 @@ const handleCurrentChange = (val: any) => { ...@@ -33,12 +41,12 @@ const handleCurrentChange = (val: any) => {
} }
</script> </script>
<template> <template>
<el-dialog :model-value="idShowMore" title="更多视频文件" :before-close="handleCancel"> <el-dialog title="更多视频文件" :before-close="handleCancel">
<div <div
v-for="(item, index) in props.videoList.slice((page.currentPage - 1) * page.size, page.currentPage * page.size)" v-for="(item, index) in props.videoList.slice((page.currentPage - 1) * page.size, page.currentPage * page.size)"
:key="index" :key="index"
> >
{{ item.name }} {{ item.file.name }}
</div> </div>
<el-pagination <el-pagination
v-model:currentPage="currentPage" v-model:currentPage="currentPage"
......
...@@ -180,11 +180,7 @@ const handleBatchImport = () => { ...@@ -180,11 +180,7 @@ const handleBatchImport = () => {
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
<BatchImportVideo <BatchImportVideo v-model="isShowBatchImport" v-if="isShowBatchImport === true" @update="typeFilter" />
v-model:isShowBatchImport="isShowBatchImport"
v-if="isShowBatchImport === true"
@update="typeFilter"
/>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.card-list { .card-list {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论