useMediaPreview.js 6.96 KB
import { ref } from 'vue';
import Taro from '@tarojs/taro';

/**
 * 媒体预览 composable
 * 提供图片和视频预览功能
 */
export function useMediaPreview() {
    // 图片预览相关状态
    const previewVisible = ref(false);
    const previewImages = ref([]);
    const previewIndex = ref(0);

    // 视频预览相关状态
    const videoVisible = ref(false);
    const currentVideo = ref(null);
    const videoId = ref(Date.now());

    /**
     * 处理媒体项目点击事件
     * @param {Object} item - 媒体项目
     * @param {number} item.id - 媒体ID
     * @param {string} item.media_type - 媒体类型 IMAGE=图片, VIDEO=视频
     * @param {string} item.media_url - 媒体文件URL
     * @param {string} item.thumbnail - 缩略图URL
     * @param {boolean} item.is_my - 是否是我的相册
     * @param {Array} mediaList - 完整的媒体列表
     */
    const handleMediaClick = (item, mediaList = []) => {
        if (item.media_type === 'IMAGE') {
            // 图片预览
            const imageItems = mediaList.filter(media => media.media_type === 'IMAGE');
            previewImages.value = imageItems.map(img => ({
                src: img.media_url,
                id: img.id,
                thumbnail: img.thumbnail,
                is_my: img.is_my
            }));

            // 计算当前图片在图片列表中的索引
            const imageIndex = imageItems.findIndex(img => img.media_url === item.media_url);
            previewIndex.value = imageIndex >= 0 ? imageIndex : 0;
            previewVisible.value = true;
        } else if (item.media_type === 'VIDEO') {
            // 视频播放
            currentVideo.value = {
                ...item,
                url: item.media_url, // 兼容原有的url字段
                type: 'video' // 兼容原有的type字段
            };
            videoId.value = Date.now(); // 生成新的视频ID
            videoVisible.value = true;
        }
    };

    /**
     * 预览单张图片
     * @param {string} imageUrl - 图片URL
     */
    const previewSingleImage = (imageUrl) => {
        previewImages.value = [{ src: imageUrl }];
        previewIndex.value = 0;
        previewVisible.value = true;
    };

    /**
     * 预览多张图片
     * @param {Array} images - 图片数组,可以是URL字符串数组或媒体对象数组
     * @param {number} index - 初始显示的图片索引
     */
    const previewMultipleImages = (images, index = 0) => {
        previewImages.value = images.map(item => {
            if (typeof item === 'string') {
                // 兼容URL字符串数组
                return { src: item };
            } else {
                // 处理媒体对象数组
                return {
                    src: item.media_url || item.url,
                    id: item.id,
                    thumbnail: item.thumbnail,
                    is_my: item.is_my
                };
            }
        });
        previewIndex.value = index;
        previewVisible.value = true;
    };

    /**
     * 播放视频
     * @param {Object} video - 视频对象
     * @param {string} video.media_url - 视频URL
     * @param {string} video.thumbnail - 缩略图URL
     * @param {number} video.id - 视频ID
     * @param {boolean} video.is_my - 是否是我的视频
     */
    const playVideo = (video) => {
        currentVideo.value = {
            ...video,
            url: video.media_url || video.url, // 兼容新旧字段
            type: 'video'
        };
        videoId.value = Date.now();
        videoVisible.value = true;
    };

    /**
     * 关闭图片预览
     */
    const closePreview = () => {
        previewVisible.value = false;
    };

    /**
     * 关闭视频播放
     */
    const closeVideo = () => {
        videoVisible.value = false;
        currentVideo.value = null;
    };

    /**
     * 处理视频播放
     */
    const handleVideoPlay = () => {
        // 视频开始播放
    };

    /**
     * 处理视频暂停
     */
    const handleVideoPause = () => {
        // 视频暂停播放
    };

    /**
     * 处理全屏状态变化
     */
    const handleFullscreenChange = () => {
        // 全屏状态变化
    };

    /**
     * 处理视频播放错误
     * @param {Event} error - 错误事件
     */
    const handleVideoError = (error) => {
        console.error('视频播放错误:', error);
        Taro.showToast({
            title: '视频播放失败',
            icon: 'error',
            duration: 2000
        });
        // 关闭视频弹框
        closeVideo();
    };

    /**
     * 格式化视频时长
     * @param {number} seconds - 秒数
     * @returns {string} 格式化后的时长
     */
    const formatDuration = (seconds) => {
        const minutes = Math.floor(seconds / 60);
        const remainingSeconds = seconds % 60;
        return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
    };

    /**
     * 判断媒体类型是否为图片
     * @param {Object} media - 媒体对象
     * @returns {boolean} 是否为图片
     */
    const isImage = (media) => {
        return media.media_type === 'IMAGE' || media.type === 'image';
    };

    /**
     * 判断媒体类型是否为视频
     * @param {Object} media - 媒体对象
     * @returns {boolean} 是否为视频
     */
    const isVideo = (media) => {
        return media.media_type === 'VIDEO' || media.type === 'video';
    };

    /**
     * 获取媒体URL
     * @param {Object} media - 媒体对象
     * @returns {string} 媒体URL
     */
    const getMediaUrl = (media) => {
        return media.media_url || media.url || '';
    };

    /**
     * 获取缩略图URL
     * @param {Object} media - 媒体对象
     * @returns {string} 缩略图URL
     */
    const getThumbnailUrl = (media) => {
        return media.thumbnail || media.media_url || media.url || '';
    };

    /**
     * 转换接口数据为预览格式
     * @param {Array} mediaList - 接口返回的媒体列表
     * @returns {Array} 转换后的媒体列表
     */
    const transformMediaList = (mediaList = []) => {
        return mediaList.map(item => ({
            id: item.id,
            type: item.media_type === 'IMAGE' ? 'image' : 'video',
            media_type: item.media_type,
            url: item.media_url,
            media_url: item.media_url,
            thumbnail: item.thumbnail,
            is_my: item.is_my
        }));
    };

    return {
        // 状态
        previewVisible,
        previewImages,
        previewIndex,
        videoVisible,
        currentVideo,
        videoId,

        // 方法
        handleMediaClick,
        previewSingleImage,
        previewMultipleImages,
        playVideo,
        closePreview,
        closeVideo,
        handleVideoPlay,
        handleVideoPause,
        handleFullscreenChange,
        handleVideoError,
        formatDuration,

        // 辅助方法
        isImage,
        isVideo,
        getMediaUrl,
        getThumbnailUrl,
        transformMediaList
    };
}