Skip to content

Commit 4b5af71

Browse files
committed
feat: 支持上传本地音视频
1 parent 306ec94 commit 4b5af71

File tree

3 files changed

+75
-18
lines changed

3 files changed

+75
-18
lines changed

src/hooks/useCreateElement.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { storeToRefs } from 'pinia'
22
import { nanoid } from 'nanoid'
33
import { useMainStore, useSlidesStore } from '@/store'
44
import { getImageSize } from '@/utils/image'
5-
import type { PPTLineElement, PPTElement, TableCell, TableCellStyle, PPTShapeElement, ChartType } from '@/types/slides'
5+
import type { PPTLineElement, PPTElement, TableCell, TableCellStyle, PPTShapeElement, ChartType, PPTVideoElement, PPTAudioElement } from '@/types/slides'
66
import { type ShapePoolItem, SHAPE_PATH_FORMULAS } from '@/configs/shapes'
77
import type { LinePoolItem } from '@/configs/lines'
88
import { CHART_DEFAULT_DATA } from '@/configs/chart'
@@ -276,8 +276,8 @@ export default () => {
276276
* 创建视频元素
277277
* @param src 视频地址
278278
*/
279-
const createVideoElement = (src: string) => {
280-
createElement({
279+
const createVideoElement = (src: string, ext?: string) => {
280+
const newElement: PPTVideoElement = {
281281
type: 'video',
282282
id: nanoid(10),
283283
width: 500,
@@ -287,15 +287,17 @@ export default () => {
287287
top: (viewportSize.value * viewportRatio.value - 300) / 2,
288288
src,
289289
autoplay: false,
290-
})
290+
}
291+
if (ext) newElement.ext = ext
292+
createElement(newElement)
291293
}
292294

293295
/**
294296
* 创建音频元素
295297
* @param src 音频地址
296298
*/
297-
const createAudioElement = (src: string) => {
298-
createElement({
299+
const createAudioElement = (src: string, ext?: string) => {
300+
const newElement: PPTAudioElement = {
299301
type: 'audio',
300302
id: nanoid(10),
301303
width: 50,
@@ -308,7 +310,9 @@ export default () => {
308310
fixedRatio: true,
309311
color: theme.value.themeColors[0],
310312
src,
311-
})
313+
}
314+
if (ext) newElement.ext = ext
315+
createElement(newElement)
312316
}
313317

314318
return {

src/views/Editor/CanvasTool/MediaInput.vue

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,26 @@
99
<template v-if="type === 'video'">
1010
<Input v-model:value="videoSrc" placeholder="请输入视频地址,e.g. https://xxx.mp4"></Input>
1111
<div class="btns">
12-
<Button @click="emit('close')" style="margin-right: 10px;">取消</Button>
13-
<Button type="primary" @click="insertVideo()">确认</Button>
12+
<FileInput accept="video/*" @change="files => uploadVideo(files)">
13+
<Button>上传本地视频</Button>
14+
</FileInput>
15+
<div class="group">
16+
<Button @click="emit('close')" style="margin-right: 10px;">取消</Button>
17+
<Button type="primary" @click="insertVideo()">确认</Button>
18+
</div>
1419
</div>
1520
</template>
1621

1722
<template v-if="type === 'audio'">
1823
<Input v-model:value="audioSrc" placeholder="请输入音频地址,e.g. https://xxx.mp3"></Input>
1924
<div class="btns">
20-
<Button @click="emit('close')" style="margin-right: 10px;">取消</Button>
21-
<Button type="primary" @click="insertAudio()">确认</Button>
25+
<FileInput accept="audio/*" @change="files => uploadAudio(files)">
26+
<Button>上传本地音频</Button>
27+
</FileInput>
28+
<div class="group">
29+
<Button @click="emit('close')" style="margin-right: 10px;">取消</Button>
30+
<Button type="primary" @click="insertAudio()">确认</Button>
31+
</div>
2232
</div>
2333
</template>
2434
</div>
@@ -30,6 +40,34 @@ import message from '@/utils/message'
3040
import Tabs from '@/components/Tabs.vue'
3141
import Input from '@/components/Input.vue'
3242
import Button from '@/components/Button.vue'
43+
import FileInput from '@/components/FileInput.vue'
44+
45+
const MIME_MAP: { [key: string]: string } = {
46+
47+
// 音频类型
48+
'audio/aac': 'aac',
49+
'audio/mpeg': 'mp3',
50+
'audio/ogg': 'oga',
51+
'audio/wav': 'wav',
52+
'audio/webm': 'weba',
53+
'audio/flac': 'flac',
54+
'audio/mp4': 'm4a',
55+
'audio/x-aiff': 'aif',
56+
'audio/x-ms-wma': 'wma',
57+
'audio/midi': 'mid',
58+
59+
// 视频类型
60+
'video/mp4': 'mp4',
61+
'video/mpeg': 'mpeg',
62+
'video/ogg': 'ogv',
63+
'video/webm': 'webm',
64+
'video/x-msvideo': 'avi',
65+
'video/quicktime': 'mov',
66+
'video/x-ms-wmv': 'wmv',
67+
'video/x-flv': 'flv',
68+
'video/3gpp': '3gp',
69+
'video/3gpp2': '3g2'
70+
}
3371
3472
type TypeKey = 'video' | 'audio'
3573
interface TabItem {
@@ -38,8 +76,8 @@ interface TabItem {
3876
}
3977
4078
const emit = defineEmits<{
41-
(event: 'insertVideo', payload: string): void
42-
(event: 'insertAudio', payload: string): void
79+
(event: 'insertVideo', payload: { src: string, ext?: string }): void
80+
(event: 'insertAudio', payload: { src: string, ext?: string }): void
4381
(event: 'close'): void
4482
}>()
4583
@@ -55,12 +93,26 @@ const tabs: TabItem[] = [
5593
5694
const insertVideo = () => {
5795
if (!videoSrc.value) return message.error('请先输入正确的视频地址')
58-
emit('insertVideo', videoSrc.value)
96+
emit('insertVideo', { src: videoSrc.value })
5997
}
6098
6199
const insertAudio = () => {
62100
if (!audioSrc.value) return message.error('请先输入正确的音频地址')
63-
emit('insertAudio', audioSrc.value)
101+
emit('insertAudio', { src: audioSrc.value })
102+
}
103+
104+
const uploadVideo = (files: FileList) => {
105+
const file = files[0]
106+
if (!file) return
107+
const ext = MIME_MAP[file.type] || ''
108+
emit('insertVideo', { src: URL.createObjectURL(file), ext })
109+
}
110+
111+
const uploadAudio = (files: FileList) => {
112+
const file = files[0]
113+
if (!file) return
114+
const ext = MIME_MAP[file.type] || ''
115+
emit('insertAudio', { src: URL.createObjectURL(file), ext })
64116
}
65117
</script>
66118

@@ -70,6 +122,7 @@ const insertAudio = () => {
70122
}
71123
.btns {
72124
margin-top: 10px;
73-
text-align: right;
125+
display: flex;
126+
justify-content: space-between;
74127
}
75128
</style>

src/views/Editor/CanvasTool/index.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@
7575
<template #content>
7676
<MediaInput
7777
@close="mediaInputVisible = false"
78-
@insertVideo="src => { createVideoElement(src); mediaInputVisible = false }"
79-
@insertAudio="src => { createAudioElement(src); mediaInputVisible = false }"
78+
@insertVideo="({ src, ext }) => { createVideoElement(src, ext); mediaInputVisible = false }"
79+
@insertAudio="({ src, ext }) => { createAudioElement(src, ext); mediaInputVisible = false }"
8080
/>
8181
</template>
8282
<IconVideoTwo class="handler-item" v-tooltip="'插入音视频'" />

0 commit comments

Comments
 (0)