|
@@ -7,7 +7,6 @@ import type { ResponseInfo } from '@/types/axios.ts'
|
|
|
|
|
|
|
|
import axiosInstance from '@/utils/axios/axiosInstance.ts'
|
|
import axiosInstance from '@/utils/axios/axiosInstance.ts'
|
|
|
import type {
|
|
import type {
|
|
|
- AddTagRes,
|
|
|
|
|
GameData,
|
|
GameData,
|
|
|
GameSelectItem,
|
|
GameSelectItem,
|
|
|
ImgUploadRes,
|
|
ImgUploadRes,
|
|
@@ -21,16 +20,18 @@ import type {
|
|
|
UploadFile,
|
|
UploadFile,
|
|
|
UploadFiles,
|
|
UploadFiles,
|
|
|
UploadInstance,
|
|
UploadInstance,
|
|
|
|
|
+ UploadRawFile,
|
|
|
UploadRequestOptions,
|
|
UploadRequestOptions,
|
|
|
} from 'element-plus'
|
|
} from 'element-plus'
|
|
|
import { ElMessageBox } from 'element-plus'
|
|
import { ElMessageBox } from 'element-plus'
|
|
|
import { nextTick, onMounted, type Reactive, reactive, ref, toRaw } from 'vue'
|
|
import { nextTick, onMounted, type Reactive, reactive, ref, toRaw } from 'vue'
|
|
|
import { VideoProcessor } from '@/utils/file/handleVideoFile.ts'
|
|
import { VideoProcessor } from '@/utils/file/handleVideoFile.ts'
|
|
|
import { ImageProcessor } from '@/utils/file/handleImgFile.ts'
|
|
import { ImageProcessor } from '@/utils/file/handleImgFile.ts'
|
|
|
|
|
+import TagSelect from '@/components/Material/TagSelect.vue'
|
|
|
|
|
|
|
|
const { getAllTags } = useMaterial()
|
|
const { getAllTags } = useMaterial()
|
|
|
const { isValidFile, handleFile } = useFileUpload()
|
|
const { isValidFile, handleFile } = useFileUpload()
|
|
|
-const { getGameInfo, createFilter } = useMaterial()
|
|
|
|
|
|
|
+const { getGameInfo } = useMaterial()
|
|
|
|
|
|
|
|
// 表单数据
|
|
// 表单数据
|
|
|
const uploadForm = reactive<UploadAssetForm>({
|
|
const uploadForm = reactive<UploadAssetForm>({
|
|
@@ -45,6 +46,8 @@ const uploadForm = reactive<UploadAssetForm>({
|
|
|
width: 0,
|
|
width: 0,
|
|
|
height: 0,
|
|
height: 0,
|
|
|
},
|
|
},
|
|
|
|
|
+ headImgPath: '',
|
|
|
|
|
+ videoType: 1,
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
// 表单规则
|
|
// 表单规则
|
|
@@ -68,7 +71,7 @@ const gameSelect = reactive<GameSelectItem[]>([]) // 游戏级联选择框数据
|
|
|
const uploadRef = ref<UploadInstance>()
|
|
const uploadRef = ref<UploadInstance>()
|
|
|
const fileFormRef = ref<FormInstance>()
|
|
const fileFormRef = ref<FormInstance>()
|
|
|
const tagInput = ref('') // 标签输入框数据
|
|
const tagInput = ref('') // 标签输入框数据
|
|
|
-const autocompleteRef = ref()
|
|
|
|
|
|
|
+
|
|
|
const isVideo = ref(false) // 当前上传的时候是视频
|
|
const isVideo = ref(false) // 当前上传的时候是视频
|
|
|
const limit = 1 // 限制上传文件数量
|
|
const limit = 1 // 限制上传文件数量
|
|
|
const allTags: Array<TagItem> = [] // 所有标签
|
|
const allTags: Array<TagItem> = [] // 所有标签
|
|
@@ -78,6 +81,7 @@ const previewUrl = ref('')
|
|
|
const previewVideoRef = ref<HTMLVideoElement>()
|
|
const previewVideoRef = ref<HTMLVideoElement>()
|
|
|
|
|
|
|
|
const coverUrl = ref('') // 封面图片地址
|
|
const coverUrl = ref('') // 封面图片地址
|
|
|
|
|
+const coverFile = ref<File | null>(null) // 封面图片文件
|
|
|
|
|
|
|
|
// 级联选择框属性配置
|
|
// 级联选择框属性配置
|
|
|
const cascadePropsConfig = {
|
|
const cascadePropsConfig = {
|
|
@@ -120,31 +124,6 @@ const generateGameSelect = (
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 标签搜索
|
|
|
|
|
- * @param queryString 搜索值
|
|
|
|
|
- * @param cb 回调
|
|
|
|
|
- */
|
|
|
|
|
-const tagSearch = async (queryString: string, cb: any) => {
|
|
|
|
|
- const result = queryString
|
|
|
|
|
- ? allTags.filter(createFilter(queryString))
|
|
|
|
|
- : allTags
|
|
|
|
|
-
|
|
|
|
|
- cb(result)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * 处理标签选择后的事件
|
|
|
|
|
- * @param tags 选中的标签
|
|
|
|
|
- */
|
|
|
|
|
-const handleTagSelect = (tags: TagItem) => {
|
|
|
|
|
- uploadForm.tags.push(tags.id)
|
|
|
|
|
- // 需要在下一帧出发blur,否则无法选中
|
|
|
|
|
- nextTick(() => {
|
|
|
|
|
- autocompleteRef.value.blur()
|
|
|
|
|
- })
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
* 当文件列表发生变化时的处理事件
|
|
* 当文件列表发生变化时的处理事件
|
|
|
*
|
|
*
|
|
|
* @param file 选择的文件
|
|
* @param file 选择的文件
|
|
@@ -170,12 +149,14 @@ const handleFileChange = (file: UploadFile, fileList: UploadFiles) => {
|
|
|
// 重置文件状态保证可重复上传
|
|
// 重置文件状态保证可重复上传
|
|
|
fileList.forEach(f => (f.status = 'ready'))
|
|
fileList.forEach(f => (f.status = 'ready'))
|
|
|
|
|
|
|
|
- console.log(file)
|
|
|
|
|
// 如果是视频的话,还需要生成封面
|
|
// 如果是视频的话,还需要生成封面
|
|
|
if (isVideo.value) {
|
|
if (isVideo.value) {
|
|
|
nextTick(async () => {
|
|
nextTick(async () => {
|
|
|
const videoProcessor = new VideoProcessor(previewUrl.value)
|
|
const videoProcessor = new VideoProcessor(previewUrl.value)
|
|
|
const { width, height } = await videoProcessor.getVideoInfo()
|
|
const { width, height } = await videoProcessor.getVideoInfo()
|
|
|
|
|
+ coverFile.value = await videoProcessor.generateCoverFile()
|
|
|
|
|
+ // await uploadFormFile(file, true)
|
|
|
|
|
+ // isUploading.value = false
|
|
|
coverUrl.value = await videoProcessor.generateCover()
|
|
coverUrl.value = await videoProcessor.generateCover()
|
|
|
uploadForm.resolution = {
|
|
uploadForm.resolution = {
|
|
|
width,
|
|
width,
|
|
@@ -236,32 +217,54 @@ const submitAsset = async (formEl: FormInstance | undefined) => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
|
+ * 上传单个文件,获得回显
|
|
|
|
|
+ * @param file 上传的文件
|
|
|
|
|
+ * @returns 回显信息,上传失败则是null
|
|
|
|
|
+ */
|
|
|
|
|
+const uploadSingleFile = async (
|
|
|
|
|
+ file: UploadRawFile | File,
|
|
|
|
|
+): Promise<ResFileInfo | null> => {
|
|
|
|
|
+ const formData = new FormData()
|
|
|
|
|
+ formData.append('file', file)
|
|
|
|
|
+ const result = (await axiosInstance.postForm(
|
|
|
|
|
+ MaterialAPI.uploadAsset,
|
|
|
|
|
+ formData,
|
|
|
|
|
+ )) as ResFileInfo
|
|
|
|
|
+ if (result.code !== 0) {
|
|
|
|
|
+ ElMessage.error('上传素材失败')
|
|
|
|
|
+ return null
|
|
|
|
|
+ }
|
|
|
|
|
+ return result
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
* 文件上传
|
|
* 文件上传
|
|
|
*
|
|
*
|
|
|
* 表单提交需要先拿到文件上传成功后的回显,所以文件上传成功后才会执行表单的提交
|
|
* 表单提交需要先拿到文件上传成功后的回显,所以文件上传成功后才会执行表单的提交
|
|
|
* @param options 上传文件信息
|
|
* @param options 上传文件信息
|
|
|
*/
|
|
*/
|
|
|
-const uploadFile = async (options: UploadRequestOptions) => {
|
|
|
|
|
- isUploading.value = true
|
|
|
|
|
|
|
+const uploadFormFile = async (options: UploadRequestOptions) => {
|
|
|
if (!options || !options.file) {
|
|
if (!options || !options.file) {
|
|
|
ElMessage.warning('请先上传文件')
|
|
ElMessage.warning('请先上传文件')
|
|
|
- isUploading.value = false
|
|
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
+ isUploading.value = true
|
|
|
|
|
+ // 如果有封面图片,需要上传封面图片
|
|
|
|
|
+ if (coverFile.value !== null) {
|
|
|
|
|
+ const res = await uploadSingleFile(coverFile.value)
|
|
|
|
|
+ if (!res) {
|
|
|
|
|
+ isUploading.value = false
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ uploadForm.headImgPath = res.path
|
|
|
|
|
+ }
|
|
|
const file = options.file
|
|
const file = options.file
|
|
|
- const formData = new FormData()
|
|
|
|
|
- formData.append('file', file)
|
|
|
|
|
- const result = (await axiosInstance.postForm(
|
|
|
|
|
- MaterialAPI.uploadAsset,
|
|
|
|
|
- formData,
|
|
|
|
|
- )) as ResFileInfo
|
|
|
|
|
- if (result.code !== 0) {
|
|
|
|
|
- ElMessage.error('上传素材失败')
|
|
|
|
|
|
|
+ const res = await uploadSingleFile(file)
|
|
|
|
|
+ if (!res) {
|
|
|
isUploading.value = false
|
|
isUploading.value = false
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- const { md5, path } = result
|
|
|
|
|
|
|
+ const { md5, path } = res
|
|
|
uploadForm.md5 = md5
|
|
uploadForm.md5 = md5
|
|
|
uploadForm.filePath = path
|
|
uploadForm.filePath = path
|
|
|
|
|
|
|
@@ -269,6 +272,15 @@ const uploadFile = async (options: UploadRequestOptions) => {
|
|
|
await submitForm()
|
|
await submitForm()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// 判断横版还是竖版,返回数字
|
|
|
|
|
+const getVideoType = (): 1 | 2 => {
|
|
|
|
|
+ const { width, height } = uploadForm.resolution
|
|
|
|
|
+ if (width > height) {
|
|
|
|
|
+ return 1
|
|
|
|
|
+ }
|
|
|
|
|
+ return 2
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const submitForm = async () => {
|
|
const submitForm = async () => {
|
|
|
const url = isVideo.value ? MaterialAPI.videoSubmit : MaterialAPI.imgSubmit
|
|
const url = isVideo.value ? MaterialAPI.videoSubmit : MaterialAPI.imgSubmit
|
|
|
const nFormData = JSON.parse(JSON.stringify(toRaw(uploadForm)))
|
|
const nFormData = JSON.parse(JSON.stringify(toRaw(uploadForm)))
|
|
@@ -276,6 +288,7 @@ const submitForm = async () => {
|
|
|
// 区分视频和图片,他们需要的字段不同
|
|
// 区分视频和图片,他们需要的字段不同
|
|
|
if (isVideo.value) {
|
|
if (isVideo.value) {
|
|
|
nFormData.videoPath = nFormData.filePath
|
|
nFormData.videoPath = nFormData.filePath
|
|
|
|
|
+ nFormData.videoType = getVideoType()
|
|
|
// 对于视频上传需要删除掉九宫格字段信息
|
|
// 对于视频上传需要删除掉九宫格字段信息
|
|
|
delete nFormData.isImg9
|
|
delete nFormData.isImg9
|
|
|
} else {
|
|
} else {
|
|
@@ -300,6 +313,7 @@ const submitForm = async () => {
|
|
|
uploadRef.value?.clearFiles()
|
|
uploadRef.value?.clearFiles()
|
|
|
tagInput.value = ''
|
|
tagInput.value = ''
|
|
|
fileFormRef.value?.resetFields()
|
|
fileFormRef.value?.resetFields()
|
|
|
|
|
+ coverFile.value = null
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -310,47 +324,6 @@ const goBack = () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 新增tag
|
|
|
|
|
- * @param val 传新增值
|
|
|
|
|
- */
|
|
|
|
|
-const tagAdd = async (val: string) => {
|
|
|
|
|
- const isExist = allTags.find(item => item.name === val)
|
|
|
|
|
- const newTagName = val
|
|
|
|
|
- // 首先要判断是否已经存在这个标签,不存在则需要先走新建流程,所以不要直接添加进去,先移除
|
|
|
|
|
- uploadForm.tags.splice(uploadForm.tags.length - 1, 1)
|
|
|
|
|
- let id = -1
|
|
|
|
|
- if (!isExist) {
|
|
|
|
|
- const confirm = await ElMessageBox.confirm('不存在改标签,是否创建?', {
|
|
|
|
|
- confirmButtonText: '确定',
|
|
|
|
|
- cancelButtonText: '取消',
|
|
|
|
|
- type: 'warning',
|
|
|
|
|
- })
|
|
|
|
|
- if (!confirm) return
|
|
|
|
|
- const res = (await axiosInstance.post(MaterialAPI.addTag, {
|
|
|
|
|
- name: newTagName,
|
|
|
|
|
- })) as AddTagRes
|
|
|
|
|
- if (res.code !== 0) {
|
|
|
|
|
- ElMessage.error('创建标签失败')
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- ElMessage.success('创建标签成功')
|
|
|
|
|
-
|
|
|
|
|
- await updateTags()
|
|
|
|
|
- id = res.data.id
|
|
|
|
|
- } else {
|
|
|
|
|
- id = isExist.id
|
|
|
|
|
- }
|
|
|
|
|
- uploadForm.tags.push(id)
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * 清空标签输入框
|
|
|
|
|
- */
|
|
|
|
|
-const clearTagInput = () => {
|
|
|
|
|
- uploadForm.tags = []
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
* 更新tag标签列表
|
|
* 更新tag标签列表
|
|
|
*/
|
|
*/
|
|
|
const updateTags = async () => {
|
|
const updateTags = async () => {
|
|
@@ -425,38 +398,7 @@ onMounted(async () => {
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
<el-form-item label="标签" prop="tags">
|
|
<el-form-item label="标签" prop="tags">
|
|
|
<div class="tagContainer">
|
|
<div class="tagContainer">
|
|
|
- <!-- 这里需要修改value-key,否则会导致警告 -->
|
|
|
|
|
- <el-autocomplete
|
|
|
|
|
- :debounce="200"
|
|
|
|
|
- v-model="tagInput"
|
|
|
|
|
- value-key="name"
|
|
|
|
|
- :fetch-suggestions="tagSearch"
|
|
|
|
|
- clearable
|
|
|
|
|
- class="inline-input w220"
|
|
|
|
|
- placeholder="请输入标签以搜索"
|
|
|
|
|
- @select="handleTagSelect"
|
|
|
|
|
- ref="autocompleteRef"
|
|
|
|
|
- >
|
|
|
|
|
- <template #default="{ item }">
|
|
|
|
|
- <div class="value">{{ item.name }}</div>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-autocomplete>
|
|
|
|
|
- <el-input-tag
|
|
|
|
|
- clearable
|
|
|
|
|
- class="inputTag"
|
|
|
|
|
- v-model="uploadForm.tags"
|
|
|
|
|
- tag-type="primary"
|
|
|
|
|
- tag-effect="plain"
|
|
|
|
|
- @add-tag="tagAdd"
|
|
|
|
|
- @clear="clearTagInput"
|
|
|
|
|
- placeholder="如需新建标签,请直接在此处输入后回车"
|
|
|
|
|
- >
|
|
|
|
|
- <template #tag="{ value }">
|
|
|
|
|
- <span>{{
|
|
|
|
|
- allTags.find(item => item.id === value)?.name
|
|
|
|
|
- }}</span>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-input-tag>
|
|
|
|
|
|
|
+ <tag-select v-model:selected-tag="uploadForm.tags"></tag-select>
|
|
|
</div>
|
|
</div>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
<!-- :limit="limit"-->
|
|
<!-- :limit="limit"-->
|
|
@@ -469,7 +411,7 @@ onMounted(async () => {
|
|
|
list-type="picture"
|
|
list-type="picture"
|
|
|
:on-change="handleFileChange"
|
|
:on-change="handleFileChange"
|
|
|
ref="uploadRef"
|
|
ref="uploadRef"
|
|
|
- :http-request="uploadFile"
|
|
|
|
|
|
|
+ :http-request="uploadFormFile"
|
|
|
>
|
|
>
|
|
|
<template #file="{ file }">
|
|
<template #file="{ file }">
|
|
|
<div class="fileInfo">
|
|
<div class="fileInfo">
|