fix: 优化逻辑

This commit is contained in:
old burden 2026-04-08 13:33:57 +08:00
parent 19adf685e0
commit df3bcf67d6
2 changed files with 168 additions and 3 deletions

View File

@ -235,6 +235,42 @@
</label>
</div>
</a-modal>
<a-modal
v-model:visible="createAssetDialogVisible"
title="新增素材"
:footer="false"
:mask-closable="false"
width="680px">
<div class="vg-create-asset-block">
<div class="vg-create-asset-type">
<span class="vg-create-asset-type-label">类型选择</span>
<a-radio-group v-model="createAssetMediaType" type="button" @change="onCreateAssetTypeChange">
<a-radio value="image">图片</a-radio>
<a-radio value="video">视频</a-radio>
<a-radio value="audio">音频</a-radio>
</a-radio-group>
</div>
<div class="vg-create-asset-label">添加素材拖拽或者点击上传</div>
<a-upload
:key="createAssetUploaderKey"
draggable
multiple
:accept="uploadAcceptByType(createAssetMediaType)"
:custom-request="customCreateAssetRequest"
:show-file-list="true"
@change="onCreateAssetUploadChange" />
<div class="vg-create-asset-actions">
<a-button
type="primary"
:loading="createAssetSubmitting"
:disabled="!createAssetPendingUrls.length"
@click="submitCreateAssetModeration">
提交审核
</a-button>
<a-button @click="cancelCreateAssetDialog">取消</a-button>
</div>
</div>
</a-modal>
</div>
</template>
@ -348,6 +384,11 @@ const assetLoading = ref(false)
const assetPickerVisible = ref(false)
const assetQueryResults = ref([])
const assetPickerSelectedKeys = ref([])
const createAssetDialogVisible = ref(false)
const createAssetMediaType = ref('image')
const createAssetUploaderKey = ref(0)
const createAssetPendingUrls = ref([])
const createAssetSubmitting = ref(false)
/** 参考图区拖拽高亮(嵌套 dragenter/leave 计数) */
const referenceDragDepth = ref(0)
/** 仅「上传资产」按钮为 true左侧直接上传/拖拽/粘贴为 false */
@ -429,9 +470,9 @@ const openReferenceDirectUpload = () => {
/** 仅「上传资产」:/api/cos/upload(pathPrefix=asset) + /api/tos/asset与三方素材管理一致 */
const openFilePickerForAssetUpload = () => {
createAssetIntent.value = true
currentUploadIndex.value = -1
fileInputRef.value?.click()
createAssetMediaType.value = 'image'
clearCreateAssetUploads()
createAssetDialogVisible.value = true
}
const openFilePicker = () => {
@ -449,6 +490,100 @@ const openFilePickerFor = (index) => {
fileInputRef.value?.click()
}
const uploadAcceptByType = (mediaType) => {
if (mediaType === 'audio') return 'audio/*'
if (mediaType === 'video') return 'video/*'
return 'image/*'
}
const mediaDataKeyByType = (mediaType) => {
if (mediaType === 'audio') return 'audios'
if (mediaType === 'video') return 'videos'
return 'images'
}
const clearCreateAssetUploads = () => {
createAssetPendingUrls.value = []
createAssetUploaderKey.value += 1
}
const onCreateAssetTypeChange = () => {
clearCreateAssetUploads()
}
const cancelCreateAssetDialog = () => {
clearCreateAssetUploads()
createAssetDialogVisible.value = false
}
const customCreateAssetRequest = async (option) => {
const { onProgress, onError, onSuccess, fileItem } = option || {}
try {
const form = new FormData()
form.append('file', fileItem.file)
form.append('pathPrefix', 'asset')
const res = await request({
url: 'api/cos/upload',
method: 'post',
data: form,
headers: {
'Content-Type': 'multipart/form-data;boundary=' + new Date().getTime()
},
onUploadProgress: (evt) => {
if (evt.total && onProgress) onProgress(evt.loaded / evt.total, evt)
}
})
if (res && res.code === 200 && res.url) {
createAssetPendingUrls.value.push(res.url)
if (onSuccess) onSuccess(res)
} else {
const msg = (res && res.msg) || '上传失败'
throw new Error(msg)
}
} catch (err) {
const msg = err?.message || '上传失败'
Message.error(msg)
if (onError) onError(err)
}
}
const onCreateAssetUploadChange = (_list, fileItem) => {
const st = fileItem && fileItem.status
if (st === 'removed' && fileItem.response && fileItem.response.url) {
const u = fileItem.response.url
const idx = createAssetPendingUrls.value.findIndex((x) => x === u)
if (idx >= 0) createAssetPendingUrls.value.splice(idx, 1)
}
}
const submitCreateAssetModeration = async () => {
if (!createAssetPendingUrls.value.length) {
Message.warning('请先上传素材')
return
}
const payload = {
[mediaDataKeyByType(createAssetMediaType.value)]: [...createAssetPendingUrls.value]
}
createAssetSubmitting.value = true
try {
const res = await request({
url: 'api/tos/asset',
method: 'post',
data: payload
})
if (res.code !== 200) {
throw new Error(res.msg || '提交失败')
}
Message.success('已提交审核')
clearCreateAssetUploads()
createAssetDialogVisible.value = false
} catch (err) {
Message.error(err?.message || '提交失败')
} finally {
createAssetSubmitting.value = false
}
}
const acceptAttr = computed(() => {
const types = new Set(props.allowedMediaTypes || [])
const hasI = types.has('image')
@ -1972,6 +2107,35 @@ defineExpose({
padding: 8px 0;
}
.vg-create-asset-block {
padding: 2px 0;
}
.vg-create-asset-type {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 12px;
}
.vg-create-asset-type-label {
color: rgba(255, 255, 255, 0.85);
font-size: 13px;
}
.vg-create-asset-label {
margin-bottom: 10px;
color: rgba(255, 255, 255, 0.75);
font-size: 14px;
}
.vg-create-asset-actions {
margin-top: 14px;
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.hidden-input {
display: none;
}

View File

@ -302,6 +302,7 @@ export default {
<style lang="less" scoped>
.tpa-page {
padding: 20px;
width: 100%;
min-height: 100%;
box-sizing: border-box;
}