Skip to content

Commit

Permalink
实现了文件预览功能, 添加了video包
Browse files Browse the repository at this point in the history
  • Loading branch information
WFengYueWuQing committed Mar 8, 2025
1 parent fa114a4 commit f689b67
Show file tree
Hide file tree
Showing 6 changed files with 336 additions and 6 deletions.
47 changes: 47 additions & 0 deletions components/ui/DisplayBox/HandleDisplay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!-- 用于处理文件类型,并选择适合的播放器 -->
<script setup lang="ts">
import ImageBox from './ImageBox.vue';
import VideoBox from './VideoBox.vue';
// 处理函数
function checkMediaType(url: string) {
// 清理 URL(移除查询参数和哈希)
const cleanUrl = url.split(/[?#]/)[0];
// 提取扩展名(转为小写)
const extension = (cleanUrl.split('.').pop() || '').toLowerCase();

// 图片类型列表
const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'];
// 视频类型列表
const videoExtensions = ['mp4', 'mov', 'avi', 'mkv', 'webm', 'flv', 'wmv'];

if (imageExtensions.includes(extension)) {
return 'image';
} else if (videoExtensions.includes(extension)) {
return 'video';
} else {
return 'unknown';
}
}

// 定义 props, 传输展示地址
const props = defineProps<{
srcKey: string;
}>();
// onMounted(()=> {
// console.log('props.srcKey', props.srcKey);
// console.log('checkMediaType', checkMediaType(props.srcKey));
// })

</script>

<template>
<div class="max-h-100% justify-center items-center">
<ImageBox v-if="checkMediaType(props.srcKey) === 'image'" :imageKey="props.srcKey" />
<VideoBox v-else-if="checkMediaType(props.srcKey) === 'video'" :videoKey="props.srcKey" />
<span v-else>未知文件类型, 无法预览</span>
</div>
</template>

<style scoped>

</style>
41 changes: 41 additions & 0 deletions components/ui/DisplayBox/ImageBox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!-- 用于展示图片的组件 -->
<!-- 使用VueUse的Image -->
<script setup lang="ts">
import { useImage } from '@vueuse/core';
import { ref } from 'vue';
// 初始化查询前置
const { $api } = useNuxtApp();
const queryClient = useQueryClient();
// 定义 props, 传输图片地址
const props = defineProps<{
imageKey: string;
}>();

// 进行图片查询操作
console.log('props.imageKey', props.imageKey);
const url = await $api.s3.getViewURL.query({s3FileId: props.imageKey});
console.log('url', url);

// 使用 useImage 处理图片加载状态
const { isLoading, error } = useImage({
// @ts-ignore
src: url,
});

// 实现点击放大(已废弃)
// const isFullScreen = ref(false);
// const img = ref<HTMLImageElement | null>(null);
// function handleFullScreen() {
// isFullScreen.value = !isFullScreen.value;
// img.value?.style.setProperty('max-width', isFullScreen.value ? '100%' : '50%');
// }
</script>

<template>
<span v-if="isLoading" class="text-center">加载中...</span>
<span v-else-if="error" class="text-center">加载失败</span>
<img class="h-[71vh] w-auto m-auto" ref="img" v-else :src="url || undefined">
</template>

<style scoped>
</style>
39 changes: 39 additions & 0 deletions components/ui/DisplayBox/VideoBox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!-- 视频播放器 -->
<!-- 注: VideoPlayer有内部样式, 需要样式覆盖才能够修改大小 -->
<script setup lang="ts">
import { VideoPlayer } from '@videojs-player/vue'
import 'video.js/dist/video-js.css'
const { $api } = useNuxtApp();
// 定义 props, 传输视频地址
const props = defineProps<{
videoKey: string;
}>();

// 进行图片查询操作
console.log('props.videoKey', props.videoKey);
const url = await $api.s3.getViewURL.query({s3FileId: props.videoKey});
console.log('url', url);

// 定义视频播放器的配置项
const playerOptions = {
autoplay: true,
controls: true,
responsive: true,
preload: 'auto',
notSupportedMessage: '此视频暂无法播放,请稍后再试',
};
</script>

<template>
<!-- 在小屏下默认最大高度为50vh,大于768px时设置为600px,同时设置宽度自适应、居中和16:9 横纵比 -->
<div class="w-full mx-auto aspect-[16/9] max-h-[50vh] md:max-h-[600px]">
<!-- video-player 组件设置为充满容器 -->
<video-player class="w-full h-full"
:src="typeof url === 'string' ? url : undefined"
:options="playerOptions"/>
</div>
</template>

<style scoped>

</style>
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@trpc/server": "^10.45.2",
"@typescript-eslint/eslint-plugin": "^7.9.0",
"@typescript-eslint/parser": "^7.9.0",
"@videojs-player/vue": "^1.0.0",
"@vueuse/components": "^10.9.0",
"@vueuse/core": "^10.9.0",
"@vueuse/integrations": "^10.9.0",
Expand All @@ -45,7 +46,9 @@
"tailwindcss-animate": "^1.0.7",
"trpc-nuxt": "^0.10.21",
"tsx": "^4.19.3",
"video.js": "^8.21.0",
"vue-sonner": "^1.1.2",
"vue-video-player": "^6.0.0",
"zod": "^3.23.8"
},
"devDependencies": {
Expand Down
8 changes: 6 additions & 2 deletions pages/content/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,14 @@
查看
</Button>
</DialogTrigger>
<DialogContent class="sm:max-w-[425px]">
<DialogContent class="sm:max-w-[94vw] sm:max-h-[90vh]">
<DialogHeader>
<DialogTitle>源文件预览</DialogTitle>
</DialogHeader>
<div>
待实现
<!-- 奇怪的警告, 还是去了吧 -->
<!-- eslint-disable-next-line vue/attribute-hyphenation -->
<HandleDisplay :srcKey="content.S3FileId" />
</div>
<DialogClose>
<Button type="submit">
Expand Down Expand Up @@ -311,12 +313,14 @@
</template>

<script setup lang="ts">
import { useImage } from '@vueuse/core';
import { ref } from 'vue';
import { BookmarkCheck, Loader2, Pencil, Trash2 } from 'lucide-vue-next';
import { toast } from 'vue-sonner';
import { Checkbox } from '@/components/ui/checkbox';
import Badge from '~/components/ui/Badge/Badge.vue';
import Textarea from '~/components/ui/Textarea/Textarea.vue';
import HandleDisplay from '~/components/ui/DisplayBox/HandleDisplay.vue';
import { Button } from '@/components/ui/button';
import {
Card,
Expand Down
Loading

0 comments on commit f689b67

Please sign in to comment.