feat: 添加视频组件并在公告中集成视频播放功能

This commit is contained in:
2026-01-22 22:10:35 +07:00
parent 0be8edd0a5
commit 4f3834fc52
2 changed files with 146 additions and 1 deletions

View File

@@ -0,0 +1,120 @@
<script lang='ts' setup>
import { modalController } from "@ionic/vue";
import { closeOutline } from "ionicons/icons";
interface VideoConfigItem {
title: string;
link: string;
}
const props = defineProps<{
title?: string;
config: VideoConfigItem[];
}>();
const activeIndex = ref(0);
const videoRef = ref<HTMLVideoElement | null>(null);
function handleClose() {
modalController.dismiss();
}
function handleVideoSelect(index: number) {
activeIndex.value = index;
// 切换视频时重新加载
nextTick(() => {
if (videoRef.value) {
videoRef.value.load();
}
});
}
const currentVideo = computed(() => props.config[activeIndex.value]);
</script>
<template>
<ion-page>
<ion-header class="ion-no-border">
<ion-toolbar>
<ion-title>{{ props.title || "视频播放" }}</ion-title>
<ion-button slot="end" fill="clear" color="dark" @click="handleClose">
<ion-icon :icon="closeOutline" />
</ion-button>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<div class="p-4">
<!-- 视频标题 -->
<div class="mb-4">
<h2 class="text-lg font-bold text-[#1a1a1a] mb-2">
{{ currentVideo.title }}
</h2>
</div>
<!-- 视频播放器 -->
<div class="video-container rounded-2xl overflow-hidden bg-black shadow-lg mb-4">
<video
ref="videoRef"
:src="currentVideo.link"
controls
playsinline
class="w-full h-auto"
controlslist="nodownload"
>
您的浏览器不支持视频播放
</video>
</div>
<!-- 多视频列表如果有多个视频 -->
<div v-if="config.length > 1" class="mt-6">
<div class="text-sm font-semibold text-[#666] mb-3">
直播列表 ({{ config.length }})
</div>
<div class="flex flex-col gap-2">
<div
v-for="(item, index) in config"
:key="index"
class="p-3 rounded-xl cursor-pointer transition-all"
:class="index === activeIndex
? 'bg-(--ion-color-primary) text-white shadow-md'
: 'bg-white text-[#333] active:bg-gray-50'"
@click="handleVideoSelect(index)"
>
<div class="flex items-center gap-3">
<div
class="w-8 h-8 rounded-lg flex-center font-semibold text-sm shrink-0"
:class="index === activeIndex
? 'bg-white/20'
: 'bg-(--ion-color-primary)/10 text-(--ion-color-primary)'"
>
{{ index + 1 }}
</div>
<div class="flex-1 text-sm line-clamp-2">
{{ item.title }}
</div>
</div>
</div>
</div>
</div>
</div>
</ion-content>
</ion-page>
</template>
<style lang='css' scoped>
.video-container {
position: relative;
aspect-ratio: 16 / 9;
}
video {
display: block;
max-height: 60vh;
}
/* iOS Safari 视频全屏优化 */
video::-webkit-media-controls-panel {
background-image: linear-gradient(transparent, rgba(0, 0, 0, 0.5));
}
</style>

View File

@@ -3,11 +3,13 @@ import type { Treaty } from "@elysiajs/eden";
import type { InfiniteScrollCustomEvent } from "@ionic/vue";
import type { Action } from "./";
import type { TreatyQuery } from "@/api/types";
import { modalController } from "@ionic/vue";
import { chevronForwardOutline, eyeOutline, megaphoneOutline, timeOutline } from "ionicons/icons";
import { client, safeClient } from "@/api";
import banner2 from "@/assets/images/home-banner2.jpg?url";
import banner1 from "@/assets/images/home-banner.jpg?url";
import { actions } from "./";
import Video from "./components/video.vue";
type NewsItem = Treaty.Data<typeof client.api.news.get>["data"][number];
type NewsQuery = TreatyQuery<typeof client.api.news.get>;
@@ -36,9 +38,32 @@ interface Announcement {
const announcements = ref<Announcement[]>([
{
id: 1,
title: "深化改革线上视频大会-18:30分",
onClick: async () => {
const modal = await modalController.create({
component: Video,
componentProps: {
title: "视频大会",
config: [
{
title: "深化改革线上视频大会18:30分",
link: "https://www.w3schools.com/html/mov_bbb.mp4",
},
{
title: "深化改革线上视频大会20:30分",
link: "https://www.w3schools.com/html/mov_bbb.mp4",
},
],
},
});
await modal.present();
},
},
{
id: 2,
title: "欢迎使用我们的服务平台,祝您投资顺利!",
onClick: () => {
console.log("点击了第一条公告");
console.log("公告2点击");
},
},
]);