mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
feat: 支持导出音视频(#219)
This commit is contained in:
parent
c2597216d5
commit
c3af67e0ac
@ -353,7 +353,7 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 导出PPTX文件
|
// 导出PPTX文件
|
||||||
const exportPPTX = (_slides: Slide[], masterOverwrite: boolean) => {
|
const exportPPTX = (_slides: Slide[], masterOverwrite: boolean, ignoreMedia: boolean) => {
|
||||||
exporting.value = true
|
exporting.value = true
|
||||||
const pptx = new pptxgen()
|
const pptx = new pptxgen()
|
||||||
|
|
||||||
@ -743,6 +743,28 @@ export default () => {
|
|||||||
|
|
||||||
pptxSlide.addImage(options)
|
pptxSlide.addImage(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (!ignoreMedia && (el.type === 'video' || el.type === 'audio')) {
|
||||||
|
const options: pptxgen.MediaProps = {
|
||||||
|
x: el.left / INCH_PX_RATIO,
|
||||||
|
y: el.top / INCH_PX_RATIO,
|
||||||
|
w: el.width / INCH_PX_RATIO,
|
||||||
|
h: el.height / INCH_PX_RATIO,
|
||||||
|
path: el.src,
|
||||||
|
type: el.type,
|
||||||
|
}
|
||||||
|
if (el.type === 'video' && el.poster) options.cover = el.poster
|
||||||
|
|
||||||
|
const extMatch = el.src.match(/\.([a-zA-Z0-9]+)(?:[\?#]|$)/)
|
||||||
|
if (extMatch && extMatch[1]) options.extn = extMatch[1]
|
||||||
|
else if (el.ext) options.extn = el.ext
|
||||||
|
|
||||||
|
const videoExts = ['avi', 'mp4', 'm4v', 'mov', 'wmv']
|
||||||
|
const audioExts = ['mp3', 'm4a', 'mp4', 'wav', 'wma']
|
||||||
|
if (options.extn && [...videoExts, ...audioExts].includes(options.extn)) {
|
||||||
|
pptxSlide.addMedia(options)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,11 +568,14 @@ export interface PPTLatexElement extends PPTBaseElement {
|
|||||||
* src: 视频地址
|
* src: 视频地址
|
||||||
*
|
*
|
||||||
* poster: 预览封面
|
* poster: 预览封面
|
||||||
|
*
|
||||||
|
* ext: 视频后缀,当资源链接缺少后缀时用该字段确认资源类型
|
||||||
*/
|
*/
|
||||||
export interface PPTVideoElement extends PPTBaseElement {
|
export interface PPTVideoElement extends PPTBaseElement {
|
||||||
type: 'video'
|
type: 'video'
|
||||||
src: string
|
src: string
|
||||||
poster?: string
|
poster?: string
|
||||||
|
ext?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -589,14 +592,17 @@ export interface PPTVideoElement extends PPTBaseElement {
|
|||||||
* autoplay: 自动播放
|
* autoplay: 自动播放
|
||||||
*
|
*
|
||||||
* src: 音频地址
|
* src: 音频地址
|
||||||
|
*
|
||||||
|
* ext: 音频后缀,当资源链接缺少后缀时用该字段确认资源类型
|
||||||
*/
|
*/
|
||||||
export interface PPTAudioElement extends PPTBaseElement {
|
export interface PPTAudioElement extends PPTBaseElement {
|
||||||
type: 'audio'
|
type: 'audio'
|
||||||
fixedRatio: boolean
|
fixedRatio: boolean
|
||||||
color: string,
|
color: string
|
||||||
loop: boolean,
|
loop: boolean
|
||||||
autoplay: boolean,
|
autoplay: boolean
|
||||||
src: string
|
src: string
|
||||||
|
ext?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="title">忽略在线字体:</div>
|
<div class="title">忽略在线字体:</div>
|
||||||
<div class="config-item">
|
<div class="config-item">
|
||||||
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="导出时默认忽略在线字体,若您在幻灯片中使用了在线字体,且希望导出后保留相关样式,可选择关闭【忽略在线字体】选项,但要注意这将会增加导出用时。">
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.1" title="导出时默认忽略在线字体,若您在幻灯片中使用了在线字体,且希望导出后保留相关样式,可选择关闭【忽略在线字体】选项,但要注意这将会增加导出用时。">
|
||||||
<Switch v-model:checked="ignoreWebfont" />
|
<Switch v-model:checked="ignoreWebfont" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tip">
|
<div class="tip">
|
||||||
注意:若打印预览与实际样式不一致,请在弹出的打印窗口中勾选【背景图形】选项。
|
提示:若打印预览与实际样式不一致,请在弹出的打印窗口中勾选【背景图形】选项。
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -23,15 +23,30 @@
|
|||||||
v-model:value="range"
|
v-model:value="range"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="title">忽略音频/视频:</div>
|
||||||
|
<div class="config-item">
|
||||||
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.1" title="导出时默认忽略音视频,若您的幻灯片中存在音视频元素,且希望将其导出到PPTX文件中,可选择关闭【忽略音视频】选项,但要注意这将会大幅增加导出用时。">
|
||||||
|
<Switch v-model:checked="ignoreMedia" />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="title">覆盖默认母版:</div>
|
<div class="title">覆盖默认母版:</div>
|
||||||
<div class="config-item">
|
<div class="config-item">
|
||||||
<Switch v-model:checked="masterOverwrite" />
|
<Switch v-model:checked="masterOverwrite" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tip" v-if="!ignoreMedia">
|
||||||
|
提示:
|
||||||
|
1. 支持导出的视频格式:avi、mp4、m4v、mov、wmv;
|
||||||
|
2. 支持导出的音频格式:mp3、m4a、mp4、wav、wma;
|
||||||
|
3. 跨域资源无法导出。
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btns">
|
<div class="btns">
|
||||||
<Button class="btn export" type="primary" @click="exportPPTX(selectedSlides, masterOverwrite)">导出 PPTX</Button>
|
<Button class="btn export" type="primary" @click="exportPPTX(selectedSlides, masterOverwrite, ignoreMedia)">导出 PPTX</Button>
|
||||||
<Button class="btn close" @click="emit('close')">关闭</Button>
|
<Button class="btn close" @click="emit('close')">关闭</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -47,6 +62,7 @@ import useExport from '@/hooks/useExport'
|
|||||||
|
|
||||||
import FullscreenSpin from '@/components/FullscreenSpin.vue'
|
import FullscreenSpin from '@/components/FullscreenSpin.vue'
|
||||||
import {
|
import {
|
||||||
|
Tooltip,
|
||||||
Button,
|
Button,
|
||||||
Slider,
|
Slider,
|
||||||
Switch,
|
Switch,
|
||||||
@ -65,6 +81,7 @@ const { exportPPTX, exporting } = useExport()
|
|||||||
const rangeType = ref<'all' | 'current' | 'custom'>('all')
|
const rangeType = ref<'all' | 'current' | 'custom'>('all')
|
||||||
const range = ref<[number, number]>([1, slides.value.length])
|
const range = ref<[number, number]>([1, slides.value.length])
|
||||||
const masterOverwrite = ref(true)
|
const masterOverwrite = ref(true)
|
||||||
|
const ignoreMedia = ref(true)
|
||||||
|
|
||||||
const selectedSlides = computed(() => {
|
const selectedSlides = computed(() => {
|
||||||
if (rangeType.value === 'all') return slides.value
|
if (rangeType.value === 'all') return slides.value
|
||||||
@ -115,6 +132,13 @@ const selectedSlides = computed(() => {
|
|||||||
.config-item {
|
.config-item {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tip {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #aaa;
|
||||||
|
line-height: 1.8;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.btns {
|
.btns {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user