index.vue 4.61 KB
<template>
  <div class="video-wrapper">
    <div :id="'mui-player-' + item.id" class="video-div" />
    <div class="normal-module">
      <div class="video-bar">
        <van-row>
          <van-col span="12" @click="setComment">
            <van-image round width="2rem" height="2rem" class="avatar" :src="item.avatar ? item.avatar : icon_avatar" />
            <span class="text">{{ item.name }}</span>
          </van-col>
          <van-col span="12">
            <div style="padding: 0.25rem; padding-top: 0.5rem; text-align: right;">
              <span @click="setComment">
                <van-icon :name="icon_liuyan" size="1.2rem" style="vertical-align: bottom;" />
                {{ item.comment_num }}
              </span>
              &nbsp;&nbsp;&nbsp;
              <span @click="handleAction('like', detail.id)">
                <van-icon :name="!detail.is_like ? icon_dianzan1 : icon_dianzan2" size="1.2rem"
                  style="vertical-align: bottom;" />
                {{ detail.like_num }}
              </span>
            </div>
          </van-col>
        </van-row>
      </div>
      <slot name="bookDetailSub" />
    </div>
    <div class="audit-module" />
  </div>
</template>

<script setup>
/**
 * 视频组件通用模块
 */
import { icon_dianzan1, icon_dianzan2, icon_liuyan, icon_avatar } from '@/utils/generateIcons.js'
import { ref, onMounted } from 'vue'
import { _, Toast } from '@/utils/generatePackage.js'
import { useRouter } from 'vue-router'
import 'mui-player/dist/mui-player.min.css'
import MuiPlayer from 'mui-player'
import { prodActionAPI, prodInfoAPI } from '@/api/C/prod.js'
import { useDebounce } from '@/hooks/useDebounce.js'
import { DEFAULT_COVER } from '@/constant'

const $router = useRouter();
const props = defineProps({
  item: {
    type: Object,
    default(rawProps) {
      return rawProps
    }
  }
})

// 作品用户操作
/**
 * 两个请求顺序执行,处理直接写在请求函数里面似乎有点问题,get请求数据似乎无法顺利渲染显示
 */
// TAG:防抖处理
const handleAction = useDebounce(async (action_type, prod_id) => {
  const { msg } = await prodActionAPI({ action_type, prod_id });
  if (msg === `${action_type}-add-OK`) { // 动作操作成功
    if (action_type === 'favor') {
      Toast('收藏成功');
    }
    if (action_type === 'like') {
      Toast('点赞成功');
    }
  } else { // 取消操作,播放动作不提示
    if (action_type !== 'play') {
      Toast('取消成功');
    }
  }
  getProductDetail(action_type, prod_id); // 更新信息
});

// 查询作品详情
const getProductDetail = async (action_type, prod_id) => {
  const { data } = await prodInfoAPI({ prod_id });
  // 更新详情显示
  detail.value[`is_${action_type}`] = data[`is_${action_type}`];
  detail.value[`${action_type}_num`] = data[`${action_type}_num`];
}

let detail = ref({});

onMounted(() => {
  const mp = new MuiPlayer({
    container: '#mui-player-' + props.item.id,
    title: props.item.title,
    src: props.item.video,
    // poster: props.item.cover,
    poster: DEFAULT_COVER,
    autoFit: false,
    videoAttribute: [ // 声明启用同层播放, 不让会自动全屏播放
      { attrKey: 'webkit-playsinline', attrValue: 'webkit-playsinline' },
      { attrKey: 'playsinline', attrValue: 'playsinline' },
      { attrKey: 'x5-video-player-type', attrValue: 'h5-page' },
    ]
  })
  detail.value = _.cloneDeep(props.item);
  const video = mp.video();
  // 监听原生video事件
  video && video.addEventListener('play', function () {
    handleAction('play', props.item.id)
  });
});

const goTo = () => { // 跳转作品详情页
  $router.push({
    path: '/client/videoDetail',
    query: {
      prod_id: props.item.id,
      book_id: props.item.book_id,
      type: props.item.type, // 特殊标识,判断入口 为keepAlive使用
      perf_id: props.item.perf_id
    }
  });
}

const setComment = () => {
  $router.push({
    path: '/client/videoDetail/comment',
    query: {
      prod_id: props.item.id,
      book_id: props.item.book_id,
      type: props.item.type, // 特殊标识,判断入口 为keepAlive使用
    }
  });
}

</script>

<style lang="less" scoped>
.video-wrapper {
  margin: 1rem;
  border-bottom-left-radius: 5px;
  border-bottom-right-radius: 5px;
  box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.13);

  .video-div {
    border-top-left-radius: 5px;
    border-top-right-radius: 5px;
  }

  .video-bar {
    color: #713610;
    padding: 1rem;
    padding-bottom: 0.5rem;
    .avatar {
      vertical-align: middle;
    }
    .text {
      font-size: 1.05rem;vertical-align: middle; display: inline-block; padding-left: 1rem;
    }
  }
}
</style>