Files
huangguo_dhz/src/components/Post/index.vue
T
谢宇宁andClaude Opus 4.8 c957b45bad 初始化黄果短剧 H5 客户端
对接后端 hgmjapi.mfcg.me:
- 接口解密 key 更新为 resKey360
- 登录 sysType 使用原生 getDevType(后端已放开 pc/android)
- 修正榜单接口路径 /vid/rangking → /vid/ranking,方法改为 GET

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-08 19:41:43 +07:00

585 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="post-box" @click="$router.push({ path: '/postDetail', query: { postid: props.postInfo.id } })">
<!-- header-->
<div class="post-top" v-if="!props.isHiddenAvatar">
<div class="post-top-left flex-center-center" @click.stop="toUserpage">
<div class="post-avatar">
<lazyImg
:src="props.postInfo.publisher?.portrait"
round
:key="props.postInfo.publisher?.portrait"
/>
</div>
<div class="post-info">
<div class="username_box ellipsis">
<span>{{ props.postInfo.publisher?.name }}</span>
<span v-if="props.postInfo.publisher.vipLevel > 0" class="vipLevel">
LV.{{ props.postInfo.publisher.vipLevel }}
</span>
<!-- <img v-if="props.postInfo.publisher?.superUser" src="@/assets/images/png/isCentral.png" alt="" />-->
<!-- <SvgIcon class="vipIcon icon" name="vipIcon" v-if="state.publisher?.vipLevel > 0" />-->
</div>
<!--显示时间-->
<div class="location-box flex-vcenter">
<!-- <span v-if="props.postInfo.publisher?.vipLevel != 0">
{{
props.postInfo.publisher?.vipLevel == 1
? '月卡用户'
: props.postInfo.publisher?.vipLevel == 2
? '季卡用户'
: props.postInfo.publisher?.vipLevel == 3
? '月卡用户'
: ''
}}
</span> -->
<span v-if="props.postInfo.publisher?.vipName">{{ props.postInfo.publisher?.vipName }}</span>
{{ fromNowTime(props.postInfo.reviewAt) }}
</div>
</div>
</div>
<!-- 关注 -->
<div
@click.stop="followUp"
v-if="userStore.userInfo.uid != props.postInfo.publisher?.uid && route.path != '/personal'"
>
<div class="post-top-right-follow flex-center-center" v-if="props.postInfo.publisher?.hasFollowed">已关注</div>
<div class="post-top-right flex-center-center" v-else>
<svgIcon name="follow_add"></svgIcon>
关注
</div>
</div>
<!-- 审核状态 -->
<div
class="statusClass"
v-if="userStore.userInfo.uid == props.postInfo.publisher?.uid && route.path == '/myPublish'"
>
<div @click.stop="props.postInfo?.status == 2 ? showReason() : ''">
{{ setText(props.postInfo?.status) }}
</div>
<!-- <div v-else>-->
<!-- 被拒原因:-->
<!-- <p>{{ props.postInfo?.reason }}</p>-->
<!-- </div>-->
</div>
</div>
<div class="post-time" v-else>发布时间:1小时前</div>
<!--content -->
<div class="post-text">
<TextOverflow :text="props.postInfo.title" :maxLines="3" :isTopping="props.postInfo.isTopping">
<template #default="{ clickToggle, expanded }">
<div @click.stop="clickToggle" class="text-btn">
{{ expanded ? '收起' : '全文' }}
</div>
</template>
</TextOverflow>
</div>
<!-- 图片+视频 -->
<div class="post-media">
<!-- 如果只有图片 没有视频 -->
<template v-if="props.postInfo.seriesCover && props.postInfo.seriesCover.length && !props.postInfo.sourceURL">
<lazyImg
:src="src"
v-for="(src, index) in props.postInfo.seriesCover.slice(0, 3)"
:key="src + index"
class="img_item"
>
<div v-if="index == 2 && props.postInfo.seriesCover.length > 3" class="filter">
+{{ props.postInfo.seriesCover.length - 3 }}
</div>
</lazyImg>
</template>
<!-- 如果有图片 也有有视频 -->
<template v-if="props.postInfo.seriesCover && props.postInfo.seriesCover.length && props.postInfo.sourceURL">
<!-- 图片第一张为封面 -->
<!-- 如果图片第一张地址和封面图一样-->
<template v-if="props.postInfo.seriesCover[0] == props.postInfo.cover">
<!-- 如果图片大于4张 只展示图片 不用展示视频 -->
<template v-if="props.postInfo.seriesCover.length >= 4">
<lazyImg
:src="src"
v-for="(src, index) in props.postInfo.seriesCover.slice(1, 4)"
:key="src + index"
class="img_item"
>
<!-- <div v-if="index == 2 && props.postInfo.seriesCover.length >= 4 && !props.postInfo.sourceURL" class="filter">
+{{ props.postInfo.seriesCover.length -1 - 3 }}
</div> -->
<div
v-if="index == 2 && props.postInfo.seriesCover.length >= 4 && props.postInfo.sourceURL"
class="filter"
>
+{{ props.postInfo.seriesCover.length - 4 + 1 }}
</div>
</lazyImg>
</template>
<!-- 否则图片+视频 -->
<template v-else>
<lazyImg
:src="src"
v-for="(src, index) in props.postInfo.seriesCover.slice(1)"
:key="src + index"
class="img_item"
></lazyImg>
<lazyImg :src="props.postInfo.cover" :key="props.postInfo.cover" class="img_item">
<div class="play_box">
<img class="icon" src="@/assets/images/png/playIcon.png" alt="" />
">
</div>
</lazyImg>
</template>
</template>
<!-- 图片不一样正常展示 -->
<template v-else>
<template v-if="props.postInfo.seriesCover.length >= 3">
<lazyImg
:src="src"
v-for="(src, index) in props.postInfo.seriesCover.slice(0, 3)"
:key="src + index"
class="img_item"
>
<div
v-if="index == 2 && props.postInfo.seriesCover.length > 3 && !props.postInfo.sourceURL"
class="filter"
>
+{{ props.postInfo.seriesCover.length - 3 }}
</div>
<div
v-if="index == 2 && props.postInfo.seriesCover.length > 3 && props.postInfo.sourceURL"
class="filter"
>
+{{ props.postInfo.seriesCover.length + 1 - 3 }}
</div>
</lazyImg>
</template>
<!-- 否则图片+视频 -->
<template v-else>
<lazyImg
:src="src"
v-for="(src, index) in props.postInfo.seriesCover"
:key="src + index"
class="img_item"
></lazyImg>
<lazyImg :src="props.postInfo.cover" :key="props.postInfo.cover" class="img_item">
<div class="play_box">
<img class="icon" src="@/assets/images/png/playIcon.png" alt="" />
">
</div>
</lazyImg>
</template>
</template>
</template>
<!-- 只有视频 没有图片 -->
<template v-if="props.postInfo.seriesCover && !props.postInfo.seriesCover.length && props.postInfo.sourceURL">
<lazyImg :src="props.postInfo.cover" :key="props.postInfo.cover" class="video_item">
<div class="play_box">
<img class="icon" src="@/assets/images/png/playIcon.png" alt="" />
">
</div>
</lazyImg>
</template>
<!-- 如果有图片且图片大于三张 有无视频都无所谓-->
<!-- <template v-if="props.postInfo.seriesCover && props.postInfo.seriesCover.length >= 3">
<lazyImg
:src="src"
v-for="(src, index) in props.postInfo.seriesCover.slice(0, 3)"
:key="src + index"
class="img_item"
>
<div v-if="index == 2 && props.postInfo.seriesCover.length > 3 && !props.postInfo.sourceURL" class="filter">
+{{ props.postInfo.seriesCover.length - 3 }}
</div>
<div v-if="index == 2 && props.postInfo.seriesCover.length > 3 && props.postInfo.sourceURL" class="filter">
+{{ props.postInfo.seriesCover.length + 1 - 3 }}
</div>
</lazyImg>
</template> -->
<!-- 有图片 并且图片小于三张 或者没有图片 且 有视频 -->
<!-- <template v-if="props.postInfo.seriesCover && props.postInfo.seriesCover.length < 3 && props.postInfo.sourceURL">
<lazyImg
:src="src"
v-for="(src, index) in props.postInfo.seriesCover"
:key="src + index"
class="img_item"
></lazyImg>
<lazyImg :src="props.postInfo.cover" :key="props.postInfo.cover" class="img_item">
<div class="play_box">
<SvgIcon name="playIcon" />
</div>
</lazyImg>
</template> -->
</div>
<!-- 操作栏 -->
<div class="post_menu">
<div class="post_menu_left">
<div class="item">
<img class="icon" src="@/assets/images/png/post_eye.png" />
<span class="ellipsis">{{ watchCountText(props.postInfo.playCount) }}</span>
</div>
<div class="item">
<img class="icon" src="@/assets/images/png/post_commit.png" />
<span class="ellipsis">{{ watchCountText(props.postInfo.commentCount) }}</span>
</div>
<div class="item" @click.stop="clickLike">
<img class="icon" v-if="props.postInfo.vidStatus?.hasLiked" src="@/assets/images/png/post_inheart.png" />
<img class="icon" v-else src="@/assets/images/png/post_heart.png" />
<span class="ellipsis">{{ watchCountText(props.postInfo.likeCount) }}</span>
</div>
</div>
<div class="post_menu_right" @click.stop="goTagPage">
{{ props.postInfo.tags && props.postInfo.tags.length ? '#' + props.postInfo.tags[0].name : '' }}
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive, inject, onActivated } from 'vue';
import { watchCountText, watchCount, fromNowTime } from '@/utils/index';
import { useRouter, useRoute } from 'vue-router';
import { showToast } from 'vant';
import { useUserStore } from '@/stores/user';
import CommunityApi from '@/service/community';
import VideoApi from '@/service/video';
const router = useRouter();
const route = useRoute();
const userStore = useUserStore();
const userInfo = userStore.userInfo;
const props = defineProps<{
postInfo: any;
currentIndex: any;
list: Array<Types.Video.VInfosItem>;
isHiddenAvatar?: boolean;
}>();
const state = reactive({
info: props.postInfo,
});
onActivated(() => {
const userStore = useUserStore();
const userInfo = userStore.userInfo;
});
// 关注
const followUp = async () => {
try {
let req = {
isFollow: !props.postInfo.publisher.hasFollowed,
followUID: props.postInfo.publisher?.uid,
};
await CommunityApi.careOrcancle(req);
props.postInfo.publisher.hasFollowed = !props.postInfo.publisher.hasFollowed;
showToast(`${props.postInfo.publisher.hasFollowed ? '关注' : '取消'}成功`);
} catch (e) {
console.log(e);
}
};
// 点赞
const clickLike = async () => {
localStorage.removeItem('operateData');
try {
let req = {
type: 'image',
objID: props.postInfo.id,
};
if (!props.postInfo.vidStatus.hasLiked) {
await CommunityApi.zan(req);
props.postInfo.vidStatus.hasLiked = true;
// getDetails(props.postInfo.id)
props.postInfo.likeCount++;
showToast('点赞成功');
} else {
await CommunityApi.cancleZan(req);
props.postInfo.vidStatus.hasLiked = false;
props.postInfo.likeCount--;
showToast('取消成功');
// getDetails(props.postInfo.id)
}
} catch (e) {
console.log(e);
}
};
const emit = defineEmits(['showReason', 'setNewData']);
// 获取帖子详情
const getDetails = async (id: any) => {
try {
let req = {
videoID: id,
};
let res: any = await VideoApi.queryVideoInfo(req);
emit('setNewData', res);
} catch (e) {
console.log(e);
}
};
const goTagPage = () => {
if (route.path == '/communityTagDeatil') {
router.replace({ path: '/communityTagDeatil', query: { id: props.postInfo.tags[0].id } });
} else {
router.push({ path: '/communityTagDeatil', query: { id: props.postInfo.tags[0].id } });
}
};
const toUserpage = () => {
router.push({ path: '/userInfo', query: { uid: props.postInfo.publisher.uid } });
localStorage.removeItem('isChange');
};
const setText = (data: any) => {
if (data == 0) {
return '待审核';
} else if (data == 1) {
return '已通过';
} else if (data == 2) {
return '查看原因';
}
};
const showReason = () => {
emit('showReason', props.postInfo?.reason);
};
</script>
<style lang="scss" scoped>
.post-box {
width: 100%;
//background: rgba(65, 55, 72, 0.3);
padding: 10px 16px;
box-sizing: border-box;
border-radius: 8px;
.post-top {
display: flex;
justify-content: space-between;
align-items: flex-end;
.post-top-left {
.post-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 8px;
:deep(.loading) {
background-size: 28px 21px;
}
}
.post-info {
width: 200px;
display: flex;
flex-direction: column;
.username_box {
display: flex;
align-items: center;
margin-bottom: 5px;
span {
display: inline-block;
font-size: 14px;
font-weight: 600;
letter-spacing: 0.36px;
margin-right: 5px;
color: #ffffff;
}
img {
width: 20px;
}
.vipLevel {
padding: 1px 4px;
//width: 30px;
//height: 14px;
background: #f1a100;
border-radius: 8px;
font-size: 10px;
color: #000;
//display: flex;
//align-items: center;
//justify-content: center;
}
}
.location-box {
padding-top: 5px;
font-size: 12px;
color: rgb(172, 186, 191);
span {
font-size: 10px;
color: rgb(102, 56, 0);
display: inline-block;
border-radius: 3px;
background: linear-gradient(to right, rgb(238, 217, 180), rgb(174, 138, 95));
padding: 2px 5px;
box-sizing: border-box;
margin: 0 5px 0 0;
}
}
}
}
.post-top-right {
svg {
width: 12px;
height: 12px;
margin: 0 3px 0 0;
}
border: solid 1px #f1a100;
border-radius: 20px;
font-size: 12px;
color: #f1a100;
width: 60px;
height: 24px;
}
.post-top-right-follow {
width: 60px;
height: 24px;
color: #fff;
background: #333;
border-radius: 20px;
font-size: 12px;
}
}
.post-time {
font-size: 12px;
color: #ffffff;
font-weight: 400;
}
.post-text {
padding-top: 6px;
padding-bottom: 6px;
display: flex;
align-items: center;
width: 100%;
}
.post-media {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-row-gap: 8px;
grid-column-gap: 5px;
.img_item {
width: 111px;
height: 111px;
border-radius: 8px;
overflow: hidden;
position: relative;
z-index: 1;
.filter {
position: absolute;
bottom: 5px;
right: 5px;
background: rgba(0, 0, 0, 0.6);
color: #f1f1f1;
padding: 3px 12px;
box-sizing: border-box;
font-size: 12px;
border-radius: 8px;
}
.play_box {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 1;
> svg {
width: 20px;
height: 20px;
}
.icon {
width: 30px;
height: 30px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
}
}
.video_item {
width: 230px;
height: 130px;
border-radius: 8px;
overflow: hidden;
position: relative;
z-index: 1;
.play_box {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
> svg {
width: 30px;
height: 30px;
}
.icon {
width: 30px;
height: 30px;
}
}
}
}
.post_menu {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 15px;
.post_menu_left {
display: flex;
align-items: center;
justify-content: space-between;
.item {
display: flex;
align-items: center;
margin-right: 22px;
.icon {
width: 20px;
height: 20px;
margin-right: 5px;
}
.ellipsis {
font-size: 12px;
color: rgb(172, 186, 191);
}
}
}
.post_menu_right {
font-size: 14px;
color: #246bfd;
}
}
.statusClass {
box-sizing: border-box;
width: 72px;
height: 24px;
color: #fff;
background: #333;
border-radius: 12px;
font-size: 12px;
text-align: center;
line-height: 24px;
p {
margin: 6px 0 0 0;
}
}
}
</style>