feat: 添加视频组件并在公告中集成视频播放功能
This commit is contained in:
120
src/views/home/components/video.vue
Normal file
120
src/views/home/components/video.vue
Normal 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>
|
||||||
@@ -3,11 +3,13 @@ import type { Treaty } from "@elysiajs/eden";
|
|||||||
import type { InfiniteScrollCustomEvent } from "@ionic/vue";
|
import type { InfiniteScrollCustomEvent } from "@ionic/vue";
|
||||||
import type { Action } from "./";
|
import type { Action } from "./";
|
||||||
import type { TreatyQuery } from "@/api/types";
|
import type { TreatyQuery } from "@/api/types";
|
||||||
|
import { modalController } from "@ionic/vue";
|
||||||
import { chevronForwardOutline, eyeOutline, megaphoneOutline, timeOutline } from "ionicons/icons";
|
import { chevronForwardOutline, eyeOutline, megaphoneOutline, timeOutline } from "ionicons/icons";
|
||||||
import { client, safeClient } from "@/api";
|
import { client, safeClient } from "@/api";
|
||||||
import banner2 from "@/assets/images/home-banner2.jpg?url";
|
import banner2 from "@/assets/images/home-banner2.jpg?url";
|
||||||
import banner1 from "@/assets/images/home-banner.jpg?url";
|
import banner1 from "@/assets/images/home-banner.jpg?url";
|
||||||
import { actions } from "./";
|
import { actions } from "./";
|
||||||
|
import Video from "./components/video.vue";
|
||||||
|
|
||||||
type NewsItem = Treaty.Data<typeof client.api.news.get>["data"][number];
|
type NewsItem = Treaty.Data<typeof client.api.news.get>["data"][number];
|
||||||
type NewsQuery = TreatyQuery<typeof client.api.news.get>;
|
type NewsQuery = TreatyQuery<typeof client.api.news.get>;
|
||||||
@@ -36,9 +38,32 @@ interface Announcement {
|
|||||||
const announcements = ref<Announcement[]>([
|
const announcements = ref<Announcement[]>([
|
||||||
{
|
{
|
||||||
id: 1,
|
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: "欢迎使用我们的服务平台,祝您投资顺利!",
|
title: "欢迎使用我们的服务平台,祝您投资顺利!",
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
console.log("点击了第一条公告");
|
console.log("公告2点击");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
Reference in New Issue
Block a user