|
|
@@ -1,48 +1,48 @@
|
|
|
<template>
|
|
|
- <el-col style="padding-right: 7px; padding-left: 7px">
|
|
|
- <div style="cursor: pointer" :title="video.title">
|
|
|
- <el-card :body-style="{ padding: '0px' }" class="card">
|
|
|
- <router-link target="_blank" :to="`/video/${video.videoId}`">
|
|
|
- <div class="imgs">
|
|
|
+ <el-col class="video-card-container">
|
|
|
+ <div class="video-card-wrapper" :title="video.title">
|
|
|
+ <el-card :body-style="{ padding: '0px' }" class="video-card shadow-hover">
|
|
|
+ <router-link target="_blank" :to="`/video/${video.videoId}`" class="cover-link">
|
|
|
+ <div class="image-container">
|
|
|
<el-image
|
|
|
lazy
|
|
|
fit="cover"
|
|
|
- class="coverImg"
|
|
|
+ class="cover-img"
|
|
|
:src="video.coverUrl"
|
|
|
/>
|
|
|
- <span style="position: absolute; top: 0; left: 0; color:red">
|
|
|
- <i v-if="!video.cached" class="el-icon-close" />
|
|
|
- </span>
|
|
|
- <span style="position: absolute; top: 0; left: 60%; color:white"> {{ video.duration }} </span>
|
|
|
- <span style="position: absolute; bottom: 0; left: 0; color:white">
|
|
|
- <i v-if="video.horizontal" class="el-icon-monitor" />
|
|
|
- <i v-else class="el-icon-mobile-phone" />
|
|
|
- </span>
|
|
|
- <span style="position: absolute; bottom: 0; left: 10%; color:white">
|
|
|
- <i class="el-icon-video-play">{{ getVisited(video.view) }}</i>
|
|
|
- </span>
|
|
|
- <span style="position: absolute; bottom: 0; left: 40%; color:white">
|
|
|
- <i class="el-icon-s-comment">{{ getVisited(video.comment) }}</i>
|
|
|
- </span>
|
|
|
+
|
|
|
+ <div class="status-bar top-bar">
|
|
|
+ <span class="left-tag">
|
|
|
+ <i v-if="!video.cached" class="el-icon-warning-outline uncache-icon" />
|
|
|
+ </span>
|
|
|
+ <span class="duration-tag">{{ video.duration }}</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="status-bar bottom-bar">
|
|
|
+ <div class="data-group">
|
|
|
+ <i v-if="video.horizontal" class="el-icon-monitor device-icon" />
|
|
|
+ <i v-else class="el-icon-mobile-phone device-icon" />
|
|
|
+ <span class="data-item"><i class="el-icon-video-play" /> {{ getVisited(video.view) }}</span>
|
|
|
+ <span class="data-item"><i class="el-icon-chat-dot-round" /> {{ getVisited(video.comment) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</router-link>
|
|
|
- <div style="padding: 14px">
|
|
|
- <router-link style="text-decoration-line: none" target="_blank" :to="`/video/${video.videoId}`">
|
|
|
- <span style="left: 0;margin-bottom: 0px;color: black;" v-html="video.title">
|
|
|
-<!-- {{ video.title | ellipsis }}-->
|
|
|
- </span>
|
|
|
+
|
|
|
+ <div class="content-body">
|
|
|
+ <router-link class="title-link" target="_blank" :to="`/video/${video.videoId}`">
|
|
|
+ <h3 class="video-title" v-html="video.title"></h3>
|
|
|
</router-link>
|
|
|
- </div>
|
|
|
- <div v-if="video.user !== undefined && video.user !== null" style="padding: 14px">
|
|
|
- <span style="left: 0;margin-bottom: 0px;color: black;">
|
|
|
- <router-link target="_blank" :to="`/user/${video.user.userId}`">
|
|
|
- <i class="el-icon-user"> {{ video.user.screenName | ellipsisUsername }} </i></router-link> • {{ video.pubDateStr }}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
- <div v-if="video.user === undefined || video.user === null" style="padding: 14px">
|
|
|
- <span style="left: 0;margin-bottom: 0px;color: black;">
|
|
|
- {{ video.pubDateStr }}
|
|
|
- </span>
|
|
|
+
|
|
|
+ <div class="meta-info">
|
|
|
+ <template v-if="video.user">
|
|
|
+ <router-link class="user-link" target="_blank" :to="`/user/${video.user.userId}`">
|
|
|
+ <i class="el-icon-user"></i> {{ video.user.screenName | ellipsisUsername }}
|
|
|
+ </router-link>
|
|
|
+ <span class="dot-split">•</span>
|
|
|
+ </template>
|
|
|
+ <span class="date-text">{{ video.pubDateStr }}</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</el-card>
|
|
|
</div>
|
|
|
@@ -55,21 +55,10 @@ import { handleVisited } from 'assets/js/utils'
|
|
|
export default {
|
|
|
name: 'SearchVideoCard',
|
|
|
filters: {
|
|
|
- ellipsis(value) {
|
|
|
- if (!value) return ''
|
|
|
- const max = 10
|
|
|
- if (value.length > max) {
|
|
|
- return value.slice(0, max) + '...'
|
|
|
- }
|
|
|
- return value
|
|
|
- },
|
|
|
ellipsisUsername(value) {
|
|
|
if (!value) return ''
|
|
|
- const max = 5
|
|
|
- if (value.length > max) {
|
|
|
- return value.slice(0, max) + '...'
|
|
|
- }
|
|
|
- return value
|
|
|
+ const max = 8 // 增加了一点用户名的可见长度
|
|
|
+ return value.length > max ? value.slice(0, max) + '...' : value
|
|
|
}
|
|
|
},
|
|
|
props: {
|
|
|
@@ -77,7 +66,6 @@ export default {
|
|
|
type: Object,
|
|
|
default: null
|
|
|
},
|
|
|
- // 时间前的描述
|
|
|
dateTit: {
|
|
|
type: String,
|
|
|
default: ''
|
|
|
@@ -86,117 +74,192 @@ export default {
|
|
|
methods: {
|
|
|
getVisited(visited) {
|
|
|
return handleVisited(visited)
|
|
|
- },
|
|
|
- convertTimestamp(value) {
|
|
|
- const date = new Date(value * 1000)
|
|
|
- var month = date.getMonth()
|
|
|
- if (month < 10) {
|
|
|
- if (month === 0) {
|
|
|
- month = '01'
|
|
|
- } else {
|
|
|
- month = '0' + month
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- var day = date.getDay()
|
|
|
- if (day < 10) {
|
|
|
- day = '0' + day
|
|
|
- }
|
|
|
- return month + '-' + day
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
-<style scoped>
|
|
|
-.time {
|
|
|
- font-size: 15px;
|
|
|
- color: #999;
|
|
|
+<style lang="scss" scoped>
|
|
|
+.video-card-container {
|
|
|
+ padding: 8px; // 统一通过容器控制间距
|
|
|
}
|
|
|
|
|
|
-.bottom {
|
|
|
- margin-top: 13px;
|
|
|
- line-height: 12px;
|
|
|
+.video-card-wrapper {
|
|
|
+ cursor: pointer;
|
|
|
+ width: 100%;
|
|
|
}
|
|
|
|
|
|
-.tit {
|
|
|
- font-weight: 700;
|
|
|
- font-size: 18px;
|
|
|
-
|
|
|
- height: 50px;
|
|
|
+.video-card {
|
|
|
+ border: none !important;
|
|
|
+ border-radius: 12px;
|
|
|
overflow: hidden;
|
|
|
- text-overflow: ellipsis;
|
|
|
- text-overflow: ellipsisUsername;
|
|
|
- display: -webkit-box;
|
|
|
- -webkit-line-clamp: 2; /*行数*/
|
|
|
- -webkit-box-orient: vertical;
|
|
|
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
|
|
+ background: #fff;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ transform: translateY(-5px);
|
|
|
+ box-shadow: 0 10px 20px rgba(0,0,0,0.1) !important;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.num {
|
|
|
+.image-container {
|
|
|
position: relative;
|
|
|
- font-size: 15px;
|
|
|
- padding-top: 9px;
|
|
|
-}
|
|
|
+ width: 100%;
|
|
|
+ aspect-ratio: 16 / 9; // 锁定比例,防止布局跳动
|
|
|
+ background: #f0f0f0;
|
|
|
+ overflow: hidden;
|
|
|
|
|
|
-/*处于手机屏幕时*/
|
|
|
-@media screen and (max-width: 768px) {
|
|
|
- .tit {
|
|
|
- font-weight: 600;
|
|
|
- font-size: 12px;
|
|
|
- height: 32px;
|
|
|
- }
|
|
|
- .time {
|
|
|
- font-size: 10px;
|
|
|
- color: #999;
|
|
|
+ .cover-img {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ transition: transform 0.5s;
|
|
|
}
|
|
|
- .num {
|
|
|
- font-size: 9px;
|
|
|
- padding-top: 3px;
|
|
|
- }
|
|
|
- .bottom {
|
|
|
- margin-top: 2px;
|
|
|
- line-height: 7px;
|
|
|
- }
|
|
|
- .coverImg {
|
|
|
- height: 120px !important;
|
|
|
+
|
|
|
+ &:hover .cover-img {
|
|
|
+ transform: scale(1.05);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.imgs {
|
|
|
- position: relative;
|
|
|
+/* 状态栏通用样式 */
|
|
|
+.status-bar {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ padding: 8px 10px;
|
|
|
+ color: #fff;
|
|
|
+ font-size: 12px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ z-index: 2;
|
|
|
+ pointer-events: none;
|
|
|
}
|
|
|
|
|
|
-.coverImg {
|
|
|
- width: 100%;
|
|
|
- height: 175px;
|
|
|
- display: block;
|
|
|
+.top-bar {
|
|
|
+ top: 0;
|
|
|
+ background: linear-gradient(to bottom, rgba(0,0,0,0.5), transparent);
|
|
|
+
|
|
|
+ .uncache-icon {
|
|
|
+ color: #ff4d4f;
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 14px;
|
|
|
+ filter: drop-shadow(0 0 2px rgba(0,0,0,0.5));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.clearfix:before,
|
|
|
-.clearfix:after {
|
|
|
- display: table;
|
|
|
- content: "";
|
|
|
+.bottom-bar {
|
|
|
+ bottom: 0;
|
|
|
+ background: linear-gradient(to top, rgba(0,0,0,0.6), transparent);
|
|
|
+
|
|
|
+ .data-group {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+
|
|
|
+ .device-icon {
|
|
|
+ font-size: 14px;
|
|
|
+ margin-right: -4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 3px;
|
|
|
+ text-shadow: 0 1px 2px rgba(0,0,0,0.8);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.clearfix:after {
|
|
|
- clear: both;
|
|
|
+/* 文字内容区域 */
|
|
|
+.content-body {
|
|
|
+ padding: 12px;
|
|
|
+
|
|
|
+ .title-link {
|
|
|
+ text-decoration: none;
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .video-title {
|
|
|
+ margin: 0;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #222;
|
|
|
+ line-height: 1.5;
|
|
|
+ height: 42px; // 固定两行高度
|
|
|
+ font-weight: 500;
|
|
|
+ display: -webkit-box;
|
|
|
+ -webkit-line-clamp: 2;
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
+ overflow: hidden;
|
|
|
+ transition: color 0.2s;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: #409EFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 处理搜索高亮词的颜色 */
|
|
|
+ ::v-deep em {
|
|
|
+ color: #f73131;
|
|
|
+ font-style: normal;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.card {
|
|
|
- margin-bottom: 20px;
|
|
|
- transition: all 0.6s; /*所有属性变化在0.6秒内执行动画*/
|
|
|
+.meta-info {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #9499a0;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ .user-link {
|
|
|
+ text-decoration: none;
|
|
|
+ color: #61666d;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 4px;
|
|
|
+ max-width: 60%;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: #409EFF;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .dot-split {
|
|
|
+ margin: 0 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .date-text {
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-/*.card:hover {
|
|
|
- !*鼠标放上之后元素变成1.06倍大小*!
|
|
|
- transform: scale(1.06);
|
|
|
-}*/
|
|
|
-.play-icon {
|
|
|
- position: absolute;
|
|
|
- /*top: -15px;*/
|
|
|
- right: 2%;
|
|
|
- bottom: 5px;
|
|
|
- z-index: 7;
|
|
|
- width: 40px;
|
|
|
+/* 移动端适配 */
|
|
|
+@media screen and (max-width: 768px) {
|
|
|
+ .video-card-container {
|
|
|
+ padding: 5px; // 手机端缩小边距
|
|
|
+ }
|
|
|
+
|
|
|
+ .content-body {
|
|
|
+ padding: 8px;
|
|
|
+
|
|
|
+ .video-title {
|
|
|
+ font-size: 13px;
|
|
|
+ height: 38px;
|
|
|
+ line-height: 1.4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-bar {
|
|
|
+ padding: 4px 6px;
|
|
|
+ font-size: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .meta-info {
|
|
|
+ font-size: 11px;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|