Commit 0fa41ff6 by lijiabin

【代码优化 11710】 refactor: 单独抽离出来一个视频卡片,在多页面使用

parent f2dec14d
<template>
<div
class="group relative rounded-lg overflow-hidden bg-white shadow-sm hover:shadow-lg transition-all duration-300 cursor-pointer"
>
<div class="relative overflow-hidden">
<img
:src="item.faceUrl"
:class="[
'w-full object-cover group-hover:scale-105 transition-transform duration-500',
isFromYaPage ? 'h-36 xl:h-44' : 'aspect-video',
]"
/>
<div class="absolute inset-0 bg-gradient-to-t from-black/40 to-transparent"></div>
<!-- 推荐角标 -->
<div
v-if="item.isRecommend"
class="absolute top-0 left-0 w-15 h-7 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"
>
<img class="w-6" src="@/assets/img/culture/recommend.png" alt="" />
<div class="text-12px text-#000 line-height-12px">推荐</div>
</div>
<!-- 时长:ya 页常显;其它页仅桌面端显示 -->
<div
v-if="item.videoDuration && !smallerThanXl"
class="absolute bottom-3 right-3 bg-black/80 text-white px-2 py-1 rounded-lg text-xs"
>
{{ item.videoDuration }}
</div>
<!-- 数据 -->
<div class="absolute bottom-3 left-3 flex gap-3 text-white text-xs">
<div class="flex items-center gap-1 bg-black/50 px-2 py-1 rounded-lg">
<el-icon class="text-sm"><IEpView /></el-icon>
<span>{{ Math.max(item.playCount ?? 0, item.viewCount) }}</span>
</div>
<div class="flex items-center gap-1 bg-black/50 px-2 py-1 rounded-lg">
<el-icon class="text-sm"><IEpChatDotRound /></el-icon>
<span>{{ item.replyCount }}</span>
</div>
<div class="flex items-center gap-1 bg-black/50 px-2 py-1 rounded-lg">
<el-icon class="text-sm"><IEpStar /></el-icon>
<!-- 后端两个字段名不一致,兜底兼容 -->
<span>{{ item.collectCount ?? item.collectionCount ?? 0 }}</span>
</div>
</div>
</div>
<div class="p-3 xl:p-4">
<h3
class="font-semibold text-base mb-2 group-hover:text-blue-600 transition-colors line-clamp-1"
>
{{ item.title }}
</h3>
<div class="flex items-center justify-between text-gray-500 text-xs">
<div class="flex items-center gap-2 max-w-55%">
<img :src="item.showAvatar" alt="" class="w-6 h-6 rounded-full object-cover" />
<el-tooltip :content="item.showName" placement="top">
<span class="font-medium line-clamp-1">{{ item.showName }}</span>
</el-tooltip>
</div>
<span>{{
smallerThanXl
? dayjs(time * 1000).format('YYYY-MM-DD')
: dayjs(time * 1000).format('YYYY-MM-DD HH:mm')
}}</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import dayjs from 'dayjs'
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'
/** 视频卡所需字段(兼容 getVideoList 的 collectCount 与 getArticleList 的 collectionCount) */
interface VideoCardItem {
faceUrl: string
isRecommend?: boolean | number
videoDuration?: string
playCount?: number
viewCount: number
replyCount: number
collectCount?: number
collectionCount?: number
title: string
showAvatar?: string
showName?: string
publishTime?: number
createTime?: number
}
const { item, isFromYaPage = false } = defineProps<{
item: VideoCardItem
/** 是否来自 ya 页面:决定封面尺寸 + 时长是否常显 */
isFromYaPage?: boolean
}>()
const breakpoints = useBreakpoints(breakpointsTailwind)
const smallerThanXl = breakpoints.smaller('xl')
// 发布时间优先取 publishTime,没有则取 createTime(单位:秒)
const time = computed(() => item.publishTime ?? item.createTime ?? 0)
</script>
......@@ -4,7 +4,10 @@
:style="{ '--dynamic-color': item.color }"
>
<!-- 专栏标题栏 -->
<div class="flex items-center justify-between px-5 py-3" :style="{ backgroundColor: item.color }">
<div
class="flex items-center justify-between px-5 py-3"
:style="{ backgroundColor: item.color }"
>
<h3 class="text-base font-semibold text-gray-800 flex items-center gap-2">
<span class="w-1 h-5 rounded-full bg-gray-700/60"></span>
{{ item.title }}
......@@ -24,12 +27,15 @@
v-if="item.yaColumnVoList.length"
class="grid grid-cols-1 grid-cols-3 xl:grid-cols-3 gap-5"
>
<YaArticleCard
v-for="i in item.yaColumnVoList"
:key="i.articleId"
:item="i"
@click="jumpToArticleDetailPage({ type: i.type, id: i.articleId })"
/>
<template v-for="i in item.yaColumnVoList" :key="i.articleId">
<!-- 默认渲染 YaArticleCard;调用方可用默认插槽自定义卡片内容 -->
<slot :item="i">
<YaArticleCard
:item="i"
@click="jumpToArticleDetailPage({ type: i.type, id: i.articleId })"
/>
</slot>
</template>
</div>
<div v-else class="flex items-center justify-center h-48">
<el-empty description="暂无数据" />
......@@ -42,11 +48,11 @@
import { useRouter, type RouteLocationRaw } from 'vue-router'
import { useNavigation } from '@/hooks'
import YaArticleCard from '@/components/common/YaArticleCard/index.vue'
import type { ColumnItemDto, InterviewItemDto } from '@/api/article/types'
import type { YaArticleCardVo } from '@/api/article/types'
defineProps<{
/** 一个专栏/专访分区的完整数据 */
item: ColumnItemDto | InterviewItemDto
/** 一个专栏/专访/视频分区的完整数据 */
item: { title: string; color?: string; yaColumnVoList: YaArticleCardVo[] }
/** 传入则展示「查看更多」并跳转该路由;不传则不展示 */
moreLink?: RouteLocationRaw
}>()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment