FamilyAlbum.vue 7.28 KB
<template>
  <view>
    <!-- Family album -->
    <view class="p-5 mt-4 mb-6 bg-white rounded-xl shadow-md mx-4">
      <view class="flex justify-between items-center mb-2">
        <!-- <h2 class="font-medium text-lg">多彩瞬间</h2> -->
        <h2 class="font-medium text-lg flex items-center">
          <IconFont size="20" name="https://cdn.ipadbiz.cn/lls_prog/icon/%E7%9B%B8%E5%86%8C.png" />
          <text class="ml-2">多彩瞬间</text>
        </h2>
        <view class="text-blue-500 flex items-center text-xs" @click="openAlbumList">
          查看更多
        </view>
      </view>
      <p class="text-sm text-gray-500 mb-3">记录每一个家庭活动瞬间</p>
      <!-- 加载状态 -->
      <view v-if="loading" class="grid grid-cols-2 gap-3">
        <view
          v-for="n in 4"
          :key="n"
          class="rounded-lg aspect-square bg-gray-200 animate-pulse"
        ></view>
      </view>

      <!-- 相册内容 -->
      <view v-else-if="albumData.length > 0" class="grid grid-cols-2 gap-3">
        <!-- 显示最多3张图片 -->
        <view
          v-for="(item, index) in displayedAlbumData"
          :key="item.id || index"
          class="rounded-lg overflow-hidden aspect-square relative cursor-pointer shadow-md"
          @click="handleItemClick(item, index)"
        >
          <image
            :src="item.media_type === 'VIDEO' ? item.thumbnail : item.media_url"
            alt="家庭活动照片"
            mode="aspectFill"
            class="w-full h-full object-cover rounded-lg"
          />
          <!-- 视频标识 -->
          <view
            v-if="item.media_type === 'VIDEO'"
            class="absolute top-2 left-2 px-2 py-1 bg-black bg-opacity-70 rounded text-white text-xs"
          >
            视频
          </view>
        </view>

        <!-- 上传照片功能框 -->
        <view
          class="rounded-lg aspect-square relative cursor-pointer shadow-md bg-gray-100 flex flex-col items-center justify-center border-2 border-dashed border-gray-100 hover:border-blue-400 transition-colors"
          @click="navigateToUpload"
        >
          <view class="text-gray-400 text-2xl mb-1">+</view>
          <view class="text-gray-500 text-xs text-center">拍照留念</view>
        </view>
      </view>

      <!-- 空状态 -->
      <view v-else class="grid grid-cols-2 gap-3">
        <!-- 空状态时的上传功能框 -->
        <view
          class="rounded-lg aspect-square relative cursor-pointer shadow-md bg-gray-100 flex flex-col items-center justify-center border-2 border-dashed border-gray-100 hover:border-blue-400 transition-colors"
          @click="navigateToUpload"
        >
          <view class="text-gray-400 mb-4">
            <Photograph size="28" />
          </view>
          <view class="text-gray-500 text-xs text-center px-2">上传第一张照片吧~</view>
        </view>
      </view>
    </view>



    <!-- 视频播放器 -->
    <view
      v-if="videoVisible"
      class="fixed inset-0 bg-black"
      style="z-index: 9999;"
      @click="closeVideo"
    >
      <!-- 关闭按钮 -->
      <view
        @click.stop="closeVideo"
        class="absolute top-4 right-4 w-10 h-10 bg-black bg-opacity-50 rounded-full flex items-center justify-center"
        style="z-index: 10000;"
      >
        <Close size="24" class="text-white" />
      </view>

      <!-- 视频播放器 -->
      <video
        v-if="currentVideo"
        :id="'family-album-video-' + videoId"
        :src="currentVideo.url"
        :poster="currentVideo.thumbnail"
        :controls="true"
        :autoplay="false"
        :show-center-play-btn="true"
        :show-play-btn="true"
        :object-fit="'contain'"
        :show-fullscreen-btn="true"
        style="width: 100vw; height: 50vh; position: absolute; top: 20vh; left: 0;"
        @click.stop
        @play="handleVideoPlay"
        @pause="handleVideoPause"
        @error="handleVideoError"
        @fullscreenchange="handleFullscreenChange"
      />
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted, computed } from 'vue';
import Taro, { useDidShow } from '@tarojs/taro';
import { Close, Photograph, IconFont } from '@nutui/icons-vue-taro';

import { getPhotoListAPI } from '@/api/photo';

// 视频播放相关状态
const videoVisible = ref(false);
const currentVideo = ref(null);
const videoId = ref(0);

/**
 * 处理媒体项点击事件
 * @param {Object} item - 媒体项
 * @param {number} index - 索引
 */
const handleItemClick = (item, index) => {
  if (item.media_type === 'VIDEO') {
    // 播放视频
    currentVideo.value = {
      url: item.media_url,
      thumbnail: item.thumbnail
    };
    videoId.value = Date.now();
    videoVisible.value = true;
  } else {
    // 预览图片
    const imageUrls = albumData.value
      .filter(media => media.media_type === 'IMAGE')
      .map(media => media.media_url);

    Taro.previewImage({
      urls: imageUrls,
      current: item.media_url
    });
  }
};

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

/**
 * 视频播放事件处理
 */
const handleVideoPlay = () => {
  console.log('视频开始播放');
};

/**
 * 视频暂停事件处理
 */
const handleVideoPause = () => {
  console.log('视频暂停播放');
};

/**
 * 视频全屏变化事件处理
 */
const handleFullscreenChange = () => {
  console.log('视频全屏状态变化');
};

/**
 * 视频错误事件处理
 */
const handleVideoError = (error) => {
  console.error('视频播放错误:', error);
  Taro.showToast({
    title: '视频播放失败',
    icon: 'none'
  });
};

// 家庭相册数据
const albumData = ref([]);
const loading = ref(false);

// 计算属性:显示最多3张图片
const displayedAlbumData = computed(() => {
  return albumData.value.slice(0, 5);
});

/**
 * 获取家庭相册数据
 * @param {boolean} isRefresh - 是否为刷新操作,刷新时不显示loading状态
 */
const fetchAlbumData = async (isRefresh = false) => {
  try {
    // 只有首次加载时才显示loading状态,刷新时保持原有内容
    if (!isRefresh) {
      loading.value = true;
    }

    const response = await getPhotoListAPI({
      page: 0,
      limit: 4 // 首页只显示4张
    }, {
      silent: true
    });

    if (response.code) {
      albumData.value = response.data || [];
    }
  } catch (error) {
    console.error('获取相册数据失败:', error);
  } finally {
    // 只有首次加载时才需要关闭loading状态
    if (!isRefresh) {
      loading.value = false;
    }
  }
};

/**
 * 打开相册列表页面
 */
const openAlbumList = () => {
  Taro.navigateTo({ url: '/pages/AlbumList/index' });
};

/**
 * 跳转到上传媒体页面
 */
const navigateToUpload = () => {
  Taro.navigateTo({ url: '/pages/UploadMedia/index' });
};

// 组件挂载时获取数据
onMounted(() => {
  // fetchAlbumData();
});

useDidShow(() => {
  // fetchAlbumData();
});

/**
 * 刷新相册数据(静默刷新,不显示loading状态)
 */
const refreshData = () => {
  fetchAlbumData(true);
};

// 暴露刷新方法给父组件
defineExpose({
  refreshData,
});
</script>

<style lang="less" scoped>
.grid {
  display: grid;
}

.grid-cols-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.gap-3 {
  gap: 0.75rem;
}

.aspect-square {
  aspect-ratio: 1 / 1;
}
</style>