删除无用组件
This commit is contained in:
@@ -1,105 +0,0 @@
|
||||
<template>
|
||||
<div class="accountCredentialsPop">
|
||||
<!-- 账号凭证弹窗 -->
|
||||
<van-overlay v-model:show="state.showActTip" z-index="2001">
|
||||
<div class="wrapper">
|
||||
<div class="actTipBox">
|
||||
<div class="title">防止账号丢失</div>
|
||||
<div class="info">1.受行业因素,请绑定手机或保存好您的账号凭证(ios用户务必保存)</div>
|
||||
<div class="info">2.如账号不小心遗失,可再设置里通过凭证找回账号</div>
|
||||
<div class="actTipBtn flex-center-center">
|
||||
<div class="btn" @click="saved">我已保存</div>
|
||||
<div class="btn pink" @click="$router.push('/accountCertificate')">立即保存</div>
|
||||
</div>
|
||||
<div class="close" @click="close">
|
||||
<SvgIcon name="close" class="closeIcon" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import { useAppStore } from '@/stores/app';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const userStore = useUserStore();
|
||||
const state = reactive({
|
||||
showActTip: !appStore.isCertificate && !userStore.isSessionCertificate,
|
||||
});
|
||||
const saved = () => {
|
||||
appStore.setCertificate(true);
|
||||
state.showActTip = false;
|
||||
};
|
||||
const close = () => {
|
||||
userStore.setSessionCertificate(true);
|
||||
state.showActTip = false;
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.accountCredentialsPop {
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
.actTipBox {
|
||||
width: 308px;
|
||||
height: 258px;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
position: relative;
|
||||
background-color: rgb(255, 255, 255);
|
||||
padding: 16px 25px 0;
|
||||
border-radius: 6px;
|
||||
.title {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.info {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
color: rgb(38, 38, 38);
|
||||
padding: 0 10px;
|
||||
line-height: 22px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.actTipBtn {
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
.btn {
|
||||
width: 129px;
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
font-size: 14px;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
color: rgb(153, 153, 153);
|
||||
border: 1.5px solid rgb(219, 219, 219);
|
||||
}
|
||||
.pink {
|
||||
background-color: $themeColor;
|
||||
color: white;
|
||||
border: unset;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.close {
|
||||
position: absolute;
|
||||
bottom: -60px;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
.closeIcon {
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,133 +0,0 @@
|
||||
<template>
|
||||
<div class="sharePopup">
|
||||
<van-popup v-model:show="state.isRewardShow" :style="{ backgroundColor: 'rgba(0, 0, 0, 0)' }">
|
||||
<div class="popupBox">
|
||||
<LazyImg class="cover" :src="state.videoInfo?.horizontalCover || state.videoInfo?.verticalCover || state.videoInfo?.cover" />
|
||||
<div class="bottom"></div>
|
||||
<SvgIcon name="title2" class="title" />
|
||||
<div class="qrcode">
|
||||
<qrcode-vue :value="state.qrCodeUrl" :size="90" level="L" />
|
||||
</div>
|
||||
<div class="desc">{{ state.videoInfo?.title }}</div>
|
||||
</div>
|
||||
<div class="btnBox flex-center-between">
|
||||
<div class="btn" @click="showToast('请手动截图保存')">保存图片</div>
|
||||
<div class="btn copyBtn" @click="copyLink">复制链接</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive,nextTick } from 'vue';
|
||||
import { showToast } from 'vant';
|
||||
import QrcodeVue from 'qrcode.vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import useClipboard from 'vue-clipboard3';
|
||||
|
||||
const { toClipboard } = useClipboard();
|
||||
const userStore = useUserStore();
|
||||
const userInfo: any = userStore.userInfo;
|
||||
const props = defineProps<{
|
||||
videoInfo?: any;
|
||||
}>();
|
||||
const state = reactive({
|
||||
isRewardShow: false,
|
||||
qrCodeUrl: userInfo.promoteURL,
|
||||
promotionCode: userInfo.promotionCode,
|
||||
videoInfo: props.videoInfo,
|
||||
})
|
||||
|
||||
const openPop = () => {
|
||||
state.isRewardShow = true;
|
||||
};
|
||||
const copyLink = async () => {
|
||||
try {
|
||||
if (!state.qrCodeUrl) {
|
||||
showToast('复制失败');
|
||||
return;
|
||||
}
|
||||
await toClipboard(state.qrCodeUrl); //实现复制
|
||||
showToast('复制成功');
|
||||
} catch (e: any) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
defineExpose({
|
||||
openPop,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.sharePopup {
|
||||
background-color: rgba(255,255,255);
|
||||
.popupBox {
|
||||
background: rgba(255,255,255);
|
||||
border-radius: 6px;
|
||||
height: 271px;
|
||||
width: 301px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
.cover {
|
||||
height: 191px;
|
||||
width: 100%;
|
||||
}
|
||||
.bottom {
|
||||
height: 109px;
|
||||
width: 100%;
|
||||
}
|
||||
.title {
|
||||
height: 35px;
|
||||
width: 124.6px;
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 15px;
|
||||
}
|
||||
.qrcode {
|
||||
height: 90px;
|
||||
width: 90px;
|
||||
position: absolute;
|
||||
left: 19px;
|
||||
top: 147px;
|
||||
border-radius: 6px;
|
||||
// background: rgba(238,118,47);
|
||||
// padding:0 5px 3px 0;
|
||||
}
|
||||
.desc {
|
||||
position: absolute;
|
||||
right: 17.3px;
|
||||
bottom: 29px;
|
||||
width: 157px;
|
||||
height: 37px;
|
||||
color: rgba(38, 38, 38);
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.btnBox {
|
||||
margin: 23px auto;
|
||||
.btn {
|
||||
height: 48px;
|
||||
width: 144px;
|
||||
border-radius: 24px;
|
||||
text-align: center;
|
||||
line-height: 48px;
|
||||
background-color: white;
|
||||
}
|
||||
.copyBtn {
|
||||
color: white;
|
||||
background-color: $themeColor;
|
||||
}
|
||||
}
|
||||
:deep(.van-popup) {
|
||||
border-radius: 8px;
|
||||
}
|
||||
:deep(.van-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,93 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="swiperContent2">
|
||||
<swiper
|
||||
:modules="modules"
|
||||
:loop="true"
|
||||
effect="coverflow"
|
||||
slides-per-view="auto"
|
||||
:centeredSlides="true"
|
||||
:speed="300"
|
||||
:autoplay="{ delay: 3000, disableOnInteraction: false }"
|
||||
:coverflowEffect="{ rotate: 0, stretch: 0, depth: 150, modifier: 1 }"
|
||||
:observer="true"
|
||||
:observeParents="true"
|
||||
:style="{ height }"
|
||||
>
|
||||
<swiper-slide v-for="(item, index) in props.list" :key="index" :data-index="index" @click="open(item)">
|
||||
<LazyImg class="swiperImg" :src="item.horizontalCover || item.verticalCover" />
|
||||
</swiper-slide>
|
||||
</swiper>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { EffectCoverflow, Autoplay } from 'swiper';
|
||||
import { Swiper, SwiperSlide } from 'swiper/vue';
|
||||
import 'swiper/swiper.min.css';
|
||||
import { addVideoHistory, jumpAdv } from '@/utils';
|
||||
import { HistoryVideoType } from '@/enums/app';
|
||||
import { useRouter } from 'vue-router';
|
||||
const router = useRouter();
|
||||
|
||||
const modules = [EffectCoverflow, Autoplay];
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
list: any;
|
||||
height?: string;
|
||||
isShowIndicators?: boolean;
|
||||
}>(),
|
||||
{
|
||||
list: () => <any>[],
|
||||
height: '156px',
|
||||
isShowIndicators: true,
|
||||
},
|
||||
);
|
||||
|
||||
const open = async (item: any) => {
|
||||
if (item.kind == 1 || item.kind == 4) {
|
||||
router.push({
|
||||
path: '/novelDetailsPage',
|
||||
query: {
|
||||
id: item.id,
|
||||
// uid: state.videoInfo.publisher?.uid,
|
||||
// queryPath: state.queryPath,
|
||||
},
|
||||
});
|
||||
} else if (item.kind == 5) {
|
||||
router.push({
|
||||
path: '/portrayPage',
|
||||
query: {
|
||||
id: item.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.swiperContent1 {
|
||||
width: 600px;
|
||||
margin-left: -130px;
|
||||
}
|
||||
.swiperContent2 {
|
||||
// width: 100%;
|
||||
// margin-left: -88px;
|
||||
.swiper-slide {
|
||||
width: 320px !important;
|
||||
}
|
||||
// .swiper-slide-visible {
|
||||
// width: 320px !important;
|
||||
// }
|
||||
.swiperImg {
|
||||
// width: 320px;
|
||||
:deep(.animationImg) {
|
||||
border-radius: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.swiper-slide) {
|
||||
width: 320px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,495 +0,0 @@
|
||||
<template>
|
||||
<div class="adv_swiper">
|
||||
<div class="swiper-container">
|
||||
<div class="swiper-wrapper">
|
||||
<div class="swiper-slide" v-for="(item, index) in props.list">
|
||||
<!-- <lazyImg class="cover" :src="item.cover" :key="item.id" />-->
|
||||
<AnimationImg class="cover" :src="item.cover" :key="item.id" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="swiper">-->
|
||||
<!-- <div class="swiper-wrapper">-->
|
||||
<!-- <div class="swiper-slide" v-for="(item, index) in props.list">-->
|
||||
<!-- <lazyImg-->
|
||||
<!-- :src="item.cover"-->
|
||||
<!-- :key="item.id"-->
|
||||
<!-- />-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- <div class="swiperBox">-->
|
||||
<!-- <div class="carousel">-->
|
||||
<!-- <div-->
|
||||
<!-- class="carousel-item"-->
|
||||
<!-- @touchstart="handleTouchstart"-->
|
||||
<!-- @touchmove="handleTouchmove"-->
|
||||
<!-- @touchend="handleTouchend"-->
|
||||
<!-- v-for="(item, index) in state.items"-->
|
||||
<!-- :key="index"-->
|
||||
<!-- :style="{-->
|
||||
<!-- transform: `scale(${item.scale}) translate(${item.translateX}px, ${item.translateY}px)`,-->
|
||||
<!-- zIndex: item.zIndex,-->
|
||||
<!-- width: `${item.width}px`,-->
|
||||
<!-- height: `${item.height}px`,-->
|
||||
<!-- }"-->
|
||||
<!-- >-->
|
||||
<!-- <DecryptImg-->
|
||||
<!-- :src="props.list[index].cover"-->
|
||||
<!-- :key="item.id"-->
|
||||
<!-- :style="{ width: '100%', height: '100%' }"-->
|
||||
<!-- :alt="'ImageError ' + (index + 1)"-->
|
||||
<!-- />-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
import { nextTick, reactive } from 'vue';
|
||||
import Swiper from 'Swiper';
|
||||
import 'swiper/swiper.min.css';
|
||||
import AnimationImg from '@/components/AnimationImg/index.vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
list: [];
|
||||
height?: string;
|
||||
isShowIndicators?: boolean;
|
||||
}>(),
|
||||
{
|
||||
list: () => [],
|
||||
height: '156px',
|
||||
isShowIndicators: true,
|
||||
},
|
||||
);
|
||||
|
||||
const state = reactive({
|
||||
startX: 0, // 触摸开始时的X坐标
|
||||
currentX: 0, // 当前轮播图的X坐标
|
||||
currentIndex: 0,
|
||||
items: [
|
||||
{
|
||||
width: 300,
|
||||
height: 140,
|
||||
scale: 1,
|
||||
translateX: -25,
|
||||
translateY: 0,
|
||||
zIndex: 1,
|
||||
},
|
||||
{
|
||||
width: 300,
|
||||
height: 160,
|
||||
scale: 1,
|
||||
translateX: 0,
|
||||
translateY: 0,
|
||||
zIndex: 2,
|
||||
},
|
||||
{
|
||||
width: 300,
|
||||
height: 140,
|
||||
scale: 1,
|
||||
translateX: 25,
|
||||
translateY: 0,
|
||||
zIndex: 1,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const handleTouchstart = (event: any) => {
|
||||
state.startX = event.touches[0].clientX;
|
||||
};
|
||||
|
||||
const handleTouchmove = (event: any) => {
|
||||
const dx = event.touches[0].clientX - state.startX; // 计算滑动距离
|
||||
state.currentX += dx; // 更新轮播图位置
|
||||
state.startX = event.touches[0].clientX; // 更新触摸位置
|
||||
};
|
||||
|
||||
const handleTouchend = () => {
|
||||
if (state.currentX < 0) {
|
||||
next();
|
||||
} else if (state.currentX > 0) {
|
||||
previous();
|
||||
}
|
||||
state.currentX = 0; // 重置currentX
|
||||
};
|
||||
|
||||
/**
|
||||
* 轮播图下一张
|
||||
*/
|
||||
const next = () => {
|
||||
state.currentIndex = (state.currentIndex + 1) % state.items.length;
|
||||
// console.log(state.currentIndex);
|
||||
// if (state.currentIndex == 0) {
|
||||
// state.items = [
|
||||
// {
|
||||
// width: 300,
|
||||
// height: 140,
|
||||
// scale: 1,
|
||||
// translateX: -25,
|
||||
// translateY: 0,
|
||||
// zIndex: 1,
|
||||
// },
|
||||
// {
|
||||
// width: 300,
|
||||
// height: 160,
|
||||
// scale: 1,
|
||||
// translateX: 0,
|
||||
// translateY: 0,
|
||||
// zIndex: 2,
|
||||
// },
|
||||
// {
|
||||
// width: 300,
|
||||
// height: 140,
|
||||
// scale: 1,
|
||||
// translateX: 25,
|
||||
// translateY: 0,
|
||||
// zIndex: 1,
|
||||
// },
|
||||
// ];
|
||||
// } else if (state.currentIndex == 1) {
|
||||
// state.items = [
|
||||
// {
|
||||
// width: 300,
|
||||
// height: 140,
|
||||
// scale: 1,
|
||||
// translateX: 25,
|
||||
// translateY: 0,
|
||||
// zIndex: 1,
|
||||
// },
|
||||
// {
|
||||
// width: 300,
|
||||
// height: 140,
|
||||
// scale: 1,
|
||||
// translateX: -25,
|
||||
// translateY: 0,
|
||||
// zIndex: 1,
|
||||
// },
|
||||
// {
|
||||
// width: 300,
|
||||
// height: 160,
|
||||
// scale: 1,
|
||||
// translateX: 0,
|
||||
// translateY: 0,
|
||||
// zIndex: 2,
|
||||
// },
|
||||
// ];
|
||||
// } else if (state.currentIndex == 2) {
|
||||
// state.items = [
|
||||
// {
|
||||
// width: 300,
|
||||
// height: 160,
|
||||
// scale: 1,
|
||||
// translateX: 0,
|
||||
// translateY: 0,
|
||||
// zIndex: 2,
|
||||
// },
|
||||
// {
|
||||
// width: 300,
|
||||
// height: 140,
|
||||
// scale: 1,
|
||||
// translateX: 25,
|
||||
// translateY: 0,
|
||||
// zIndex: 1,
|
||||
// },
|
||||
// {
|
||||
// width: 300,
|
||||
// height: 140,
|
||||
// scale: 1,
|
||||
// translateX: -25,
|
||||
// translateY: 0,
|
||||
// zIndex: 1,
|
||||
// },
|
||||
// ];
|
||||
// }
|
||||
};
|
||||
|
||||
const previous = () => {
|
||||
state.currentIndex = (state.currentIndex - 1 + state.items.length) % state.items.length;
|
||||
console.log(state.currentIndex);
|
||||
if (state.currentIndex == 0) {
|
||||
state.items = [
|
||||
{
|
||||
width: 300,
|
||||
height: 140,
|
||||
scale: 1,
|
||||
translateX: -25,
|
||||
translateY: 0,
|
||||
zIndex: 1,
|
||||
},
|
||||
{
|
||||
width: 300,
|
||||
height: 160,
|
||||
scale: 1,
|
||||
translateX: 0,
|
||||
translateY: 0,
|
||||
zIndex: 2,
|
||||
},
|
||||
{
|
||||
width: 300,
|
||||
height: 140,
|
||||
scale: 1,
|
||||
translateX: 25,
|
||||
translateY: 0,
|
||||
zIndex: 1,
|
||||
},
|
||||
];
|
||||
} else if (state.currentIndex == 1) {
|
||||
state.items = [
|
||||
{
|
||||
width: 300,
|
||||
height: 160,
|
||||
scale: 1,
|
||||
translateX: 0,
|
||||
translateY: 0,
|
||||
zIndex: 2,
|
||||
},
|
||||
{
|
||||
width: 300,
|
||||
height: 140,
|
||||
scale: 1,
|
||||
translateX: 25,
|
||||
translateY: 0,
|
||||
zIndex: 1,
|
||||
},
|
||||
{
|
||||
width: 300,
|
||||
height: 140,
|
||||
scale: 1,
|
||||
translateX: -25,
|
||||
translateY: 0,
|
||||
zIndex: 1,
|
||||
},
|
||||
];
|
||||
} else if (state.currentIndex == 2) {
|
||||
state.items = [
|
||||
{
|
||||
width: 300,
|
||||
height: 160,
|
||||
scale: 1,
|
||||
translateX: 25,
|
||||
translateY: 0,
|
||||
zIndex: 0,
|
||||
},
|
||||
{
|
||||
width: 300,
|
||||
height: 160,
|
||||
scale: 1,
|
||||
translateX: -25,
|
||||
translateY: 0,
|
||||
zIndex: 1,
|
||||
},
|
||||
{
|
||||
width: 300,
|
||||
height: 160,
|
||||
scale: 1,
|
||||
translateX: 0,
|
||||
translateY: 0,
|
||||
zIndex: 2,
|
||||
},
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
nextTick(() => {
|
||||
// props.list;
|
||||
// var mySwiper = document.querySelector('.swiper');
|
||||
// debugger
|
||||
|
||||
// var mySwiper = new Swiper('.swiper', {
|
||||
// autoplay: true,//可选选项,自动滑动
|
||||
// });
|
||||
|
||||
var swiper = new Swiper('.swiper-container', {
|
||||
slidesPerView: 3,
|
||||
centeredSlides: true,
|
||||
loop: true,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.adv_swiper {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
//width: 165px;
|
||||
}
|
||||
|
||||
//.swiper-container {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
//}
|
||||
.swiper-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.swiper-slide {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
background: #fff;
|
||||
|
||||
/* Center slide text vertically */
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
-webkit-justify-content: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
transition: 300ms;
|
||||
transform: scale(0.8);
|
||||
|
||||
.cover{
|
||||
width: 240px;
|
||||
height: 120px;
|
||||
border-right: 12px;
|
||||
|
||||
:deep(.animationImg){
|
||||
border-right: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.swiper-slide-active,.swiper-slide-duplicate-active{
|
||||
z-index: 1;
|
||||
transform: scale(2);
|
||||
}
|
||||
|
||||
//.swiper-slide-active{
|
||||
// width: 320px !important;
|
||||
// height: 160px;
|
||||
// flex-shrink: 0;
|
||||
// left: 29px;
|
||||
//}
|
||||
//
|
||||
//.swiper-slide-prev{
|
||||
// width: 262.5px;
|
||||
// height: 140px;
|
||||
// flex-shrink: 0;
|
||||
// //left: 0;
|
||||
//}
|
||||
//
|
||||
//.swiper-slide-duplicate-next{
|
||||
// width: 262.5px;
|
||||
// height: 140px;
|
||||
// flex-shrink: 0;
|
||||
// //right: 0;
|
||||
//}
|
||||
|
||||
//.swiper-slide{
|
||||
// width: 320px;
|
||||
// height: 160px;
|
||||
//}
|
||||
//
|
||||
//:deep(.swiper-slide-active){
|
||||
// width: 320px;
|
||||
// height: 160px;
|
||||
//}
|
||||
//:deep(.van-swipe__indicator--active) {
|
||||
// width: 17px;
|
||||
// height: 4px;
|
||||
// border-radius: 2px;
|
||||
//}
|
||||
//:deep(.van-swipe__indicators) {
|
||||
// left: 85%;
|
||||
//}
|
||||
//.adv_swiper {
|
||||
// overflow: hidden;
|
||||
//
|
||||
// .swiperBox {
|
||||
// height: 180px;
|
||||
// padding: 0px 16px;
|
||||
// .carousel {
|
||||
// position: relative;
|
||||
// width: 100%;
|
||||
// height: 160px;
|
||||
// }
|
||||
// .bgIMage {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// width: 100%;
|
||||
// height: 210px;
|
||||
// background-repeat: no-repeat;
|
||||
// background-size: cover;
|
||||
// }
|
||||
// .bgIMage::before {
|
||||
// content: '';
|
||||
// position: absolute;
|
||||
// bottom: 0;
|
||||
// left: 0;
|
||||
// width: 100%;
|
||||
// height: 210px;
|
||||
// background: linear-gradient(180deg, rgba(26, 26, 26, 0) 0%, #1b1b1b 80%);
|
||||
// background-repeat: no-repeat;
|
||||
// background-size: cover;
|
||||
// }
|
||||
// .carousel-item {
|
||||
// position: absolute;
|
||||
// // width: 100% !important;
|
||||
// height: 100%;
|
||||
// bottom: 0;
|
||||
// left: 6px;
|
||||
// border-radius: 8px;
|
||||
// transition: transform 1s, width 1s, height 1s;
|
||||
// :deep(.van-image__img) {
|
||||
// border-radius: 8px;
|
||||
// }
|
||||
// :deep(.img-decypt) {
|
||||
// z-index: 99999 !important;
|
||||
// }
|
||||
// }
|
||||
// .carousel-item::after {
|
||||
// content: '';
|
||||
// position: absolute;
|
||||
// top: 50%;
|
||||
// left: 50%;
|
||||
// transform: translate(-50%, -50%);
|
||||
// width: 40px;
|
||||
// height: 40px;
|
||||
// //background-image: url('~@/assets/png/originalPlay.png');
|
||||
// background-repeat: no-repeat;
|
||||
// background-size: 100% 100%;
|
||||
// }
|
||||
// .carousel-indicators {
|
||||
// position: absolute;
|
||||
// left: 0;
|
||||
// bottom: -40px;
|
||||
// width: 100%;
|
||||
// text-align: center;
|
||||
// }
|
||||
// .carousel-indicators span {
|
||||
// display: inline-block;
|
||||
// width: 5px;
|
||||
// height: 5px;
|
||||
// margin: 0 5px;
|
||||
// background: #94d6da;
|
||||
// opacity: 0.5;
|
||||
// border-radius: 50%;
|
||||
// }
|
||||
// .carousel-indicators span.active {
|
||||
// width: 38px;
|
||||
// border-radius: 20px;
|
||||
// background: #94d6da;
|
||||
// opacity: 1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// .adv-container {
|
||||
// width: 100%;
|
||||
// overflow: hidden;
|
||||
// .adv-swiper-slide {
|
||||
// width: 100%;
|
||||
// border-radius: 6px;
|
||||
// overflow: hidden;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
</style>
|
||||
@@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<div class="adv_swiper">
|
||||
<div class="adv-container" v-if="props.list.length > 0">
|
||||
<van-swipe class="my-swipe" :show-indicators="isShowIndicators" :autoplay="autoplay" indicator-color="white">
|
||||
<van-swipe-item
|
||||
@click="jumpAdv(item, 1)"
|
||||
v-for="item in props.list"
|
||||
:key="item.id"
|
||||
:style="{ height: height }"
|
||||
class="adv-swiper-slide"
|
||||
>
|
||||
<DecryptImg v-if="item.cover" :src="item.cover" />
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
list: Types.App.AdsInfoListItem[];
|
||||
height?: string;
|
||||
isShowIndicators?: boolean;
|
||||
autoplay?: number;
|
||||
}>(),
|
||||
{
|
||||
list: () => [],
|
||||
height: '156px',
|
||||
isShowIndicators: false,
|
||||
autoplay: 5000,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.van-swipe__indicator--active) {
|
||||
width: 17px;
|
||||
height: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
:deep(.van-swipe__indicators) {
|
||||
left: 85%;
|
||||
}
|
||||
.adv_swiper {
|
||||
overflow: hidden;
|
||||
.adv-container {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
.adv-swiper-slide {
|
||||
width: 100%;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,116 +0,0 @@
|
||||
<template>
|
||||
<van-overlay :show="isShow" z-index="2001" @click="emit('close')">
|
||||
<div class="wrapper">
|
||||
<div class="content">
|
||||
<div class="title">解锁会员</div>
|
||||
<h2>免费次数不足~</h2>
|
||||
<p>
|
||||
充值
|
||||
<span>VIP</span>
|
||||
{{ state.tip }}
|
||||
</p>
|
||||
<div class="btn-box flex-center-between">
|
||||
<div class="btn share" @click.stop="$router.push('/promotionCode')">分享邀请</div>
|
||||
<div class="btn" @click.stop="joinMembership">立即充值</div>
|
||||
</div>
|
||||
</div>
|
||||
<SvgIcon name="close" class="close" @click="emit('close')" />
|
||||
</div>
|
||||
</van-overlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const props = defineProps<{
|
||||
videoInfo?: Types.Video.VInfosItem;
|
||||
isOpen: boolean;
|
||||
tip?: string;
|
||||
}>();
|
||||
const emit = defineEmits(['close']);
|
||||
const isShow = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
tip: props.tip || '获取脱衣次数',
|
||||
});
|
||||
/**
|
||||
* @description 开通会员
|
||||
*/
|
||||
const joinMembership = () => {
|
||||
router.push({
|
||||
path: '/recharge',
|
||||
query: {
|
||||
name: 'member',
|
||||
id: props.videoInfo?.id,
|
||||
title: props.videoInfo?.title || '无标题',
|
||||
},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.content {
|
||||
height: 187px;
|
||||
width: 312px;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding-top: 19px;
|
||||
box-sizing: border-box;
|
||||
.title {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
margin-bottom: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
h2 {
|
||||
font-size: 14px;
|
||||
color: rgb(153, 153, 153);
|
||||
}
|
||||
p {
|
||||
font-size: 14px;
|
||||
color: rgb(38, 38, 38);
|
||||
line-height: 26px;
|
||||
margin-top: 10px;
|
||||
span {
|
||||
color: rgb(255, 160, 1);
|
||||
}
|
||||
}
|
||||
.btn-box {
|
||||
padding: 0 22px;
|
||||
.btn {
|
||||
height: 38px;
|
||||
width: 129px;
|
||||
text-align: center;
|
||||
line-height: 38px;
|
||||
border-radius: 10px;
|
||||
font-size: 14px;
|
||||
background-color: $themeColor;
|
||||
color: white;
|
||||
margin-top: 26px;
|
||||
}
|
||||
.share {
|
||||
border: 1.5px solid rgb(153, 153, 153);
|
||||
background-color: unset;
|
||||
color: rgb(153, 153, 153);
|
||||
}
|
||||
}
|
||||
}
|
||||
.close {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,117 +0,0 @@
|
||||
<template>
|
||||
<div class="announcementPopup">
|
||||
<div v-for="(item, index) in state.announList" :key="item.id">
|
||||
<van-overlay :show="item.type == 0" z-index="2001" @click="close(index)">
|
||||
<div class="wrapper">
|
||||
<div class="title">APP公告</div>
|
||||
<div class="content">
|
||||
<p>
|
||||
{{ item.content }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="btn">确认</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
<van-overlay :show="item.type == 1" z-index="2001" @click="close(index)">
|
||||
<div class="imgWrapper">
|
||||
<lazyImg @click.stop="jumpAdv(item)" class="imgBox" :src="item.cover" />
|
||||
<div class="close"></div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
announList: Types.App.AnnounListItem[];
|
||||
}>(),
|
||||
{
|
||||
announList: () => [],
|
||||
},
|
||||
);
|
||||
const emit = defineEmits(['close']);
|
||||
const state = reactive({
|
||||
announList: <Array<Types.App.AnnounListItem>>props.announList,
|
||||
});
|
||||
const close = (index: number) => {
|
||||
if (index == 0) {
|
||||
emit('close');
|
||||
}
|
||||
state.announList.pop();
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.van-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
.announcementPopup {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
.wrapper {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
height: 265px;
|
||||
width: 308px;
|
||||
border-radius: 8px;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
box-sizing: border-box;
|
||||
padding-top: 16px;
|
||||
.title {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.content {
|
||||
padding: 0 24px 0;
|
||||
height: 150px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
p {
|
||||
font-size: 12px;
|
||||
color: rgb(153, 153, 153);
|
||||
line-height: 20px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
height: 38px;
|
||||
width: 227px;
|
||||
background-color: rgb(255, 160, 1);
|
||||
text-align: center;
|
||||
line-height: 38px;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
border-radius: 10px;
|
||||
margin: 20px auto 0;
|
||||
}
|
||||
}
|
||||
.imgWrapper {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
.imgBox {
|
||||
height: 380px;
|
||||
width: 285px;
|
||||
}
|
||||
.close {
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
background: url('./../../assets/images/png/closeDialog.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
margin: 10px auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,124 +0,0 @@
|
||||
<template>
|
||||
<div class="ApplicationPop">
|
||||
<van-popup
|
||||
v-model:show="state.showApplication"
|
||||
round
|
||||
position="bottom"
|
||||
:style="{ height: '50%', backgroundColor: 'rgb(0, 0, 0)' }"
|
||||
>
|
||||
<div class="popupBox flex-center-center">
|
||||
<div class="logoBox">
|
||||
<img src="@/assets/images/png/homeLogo.png" />
|
||||
</div>
|
||||
<div class="topSite">
|
||||
<div class="line"></div>
|
||||
<h1>官方中文站</h1>
|
||||
<div class="line"></div>
|
||||
</div>
|
||||
<div class="qrCode flex-center-center">
|
||||
<div class="qrCodeBox flex-center-center">
|
||||
<qrcode-vue id="qrCode" class="qrCodeImg" v-if="state.qrUrl" :value="state.qrUrl" level="L" />
|
||||
<van-loading size="50px" type="spinner" color="#c0c9ea" v-else />
|
||||
</div>
|
||||
</div>
|
||||
<div class="tipText">扫码进行APP下载获取极致观影体验</div>
|
||||
<div class="tipText">官方域名:{{ state.url }}</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, nextTick } from 'vue';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
import UserApi from '@/service/user';
|
||||
import { getDevType } from '@/utils';
|
||||
|
||||
const configStore = useConfigStore();
|
||||
const state = reactive({
|
||||
showApplication: false,
|
||||
url: configStore.sourceInfo.LAND,
|
||||
qrUrl: <string>'',
|
||||
showIos: false,
|
||||
});
|
||||
|
||||
nextTick(async () => {
|
||||
/**
|
||||
* 获取落地页链接
|
||||
*/
|
||||
if (getDevType() == 'ios') {
|
||||
let ret: any = await UserApi.queryCertificate();
|
||||
state.qrUrl = ret.content;
|
||||
} else {
|
||||
let ret: any = await UserApi.queryCertificate();
|
||||
state.qrUrl = ret.content;
|
||||
}
|
||||
});
|
||||
|
||||
const openPop = () => {
|
||||
state.showApplication = true;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
openPop,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.ApplicationPop {
|
||||
.popupBox {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: $titleColor;
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
.topSite {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
h1 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin: 0 6px;
|
||||
}
|
||||
.line {
|
||||
width: 32px;
|
||||
height: 2px;
|
||||
background-color: $titleColor;
|
||||
}
|
||||
}
|
||||
.logoBox {
|
||||
width: 130px;
|
||||
height: 45px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 4px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.qrCode {
|
||||
width: 165px;
|
||||
height: 165px;
|
||||
border: 3px solid $themeColor;
|
||||
border-radius: 8.92px;
|
||||
margin: 12px 0;
|
||||
.qrCodeBox {
|
||||
background-color: white;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border-radius: 10px;
|
||||
.qrCodeImg {
|
||||
width: 140px !important;
|
||||
height: 140px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tipText {
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,318 +0,0 @@
|
||||
<template>
|
||||
<van-popup v-model:show="isShow" position="bottom" z-index="2001" @close="emit('close')">
|
||||
<div class="wrapper">
|
||||
<div class="header flex-center-between">
|
||||
<div class="left">
|
||||
<div class="title"></div>
|
||||
<div class="total">{{ videoInfo.commentCount }}条评论</div>
|
||||
</div>
|
||||
<div class="close" @click="emit('close')"></div>
|
||||
</div>
|
||||
<div class="main overflow-y-auto">
|
||||
<PullRefresh :params="moreParams" @onLoad="onLoad" @onRefresh="onRefresh">
|
||||
<div class="commentBox flex-center-between" v-for="item in state.list" :key="item.id">
|
||||
<div class="commentInfo">
|
||||
<lazyImg class="avatar" round :src="item.userPortrait" />
|
||||
<div class="info">
|
||||
<div class="name">
|
||||
{{ item.userName }}
|
||||
<SvgIcon class="vipIcon" name="vip" v-if="item.level" />
|
||||
<SvgIcon class="genderIcon" name="male" v-if="item.gender == 'male'" />
|
||||
<SvgIcon class="genderIcon" name="female" v-else />
|
||||
</div>
|
||||
<div class="text">{{ item.content }}</div>
|
||||
<div class="address">{{ item.city }}•{{ moment(item.createdAt).format('YYYY-MM-DD') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="zanBox">
|
||||
<svg-icon name="zan" class="zanIcon" v-if="item.isLike" @click="clickZan(item)" />
|
||||
<svg-icon name="unzan" class="zanIcon" v-else @click="clickZan(item)" />
|
||||
<div class="zanNumber">{{ item.likeCount }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</PullRefresh>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="addComment flex-center-center">
|
||||
<van-field
|
||||
v-model="state.content"
|
||||
autosize
|
||||
rows="1"
|
||||
type="textarea"
|
||||
placeholder="留下你的精彩评论吧~"
|
||||
class="commentInputBox"
|
||||
></van-field>
|
||||
<SvgIcon name="commentIcon" class="commentIcon" @click="submintComment" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive } from 'vue';
|
||||
import CommunityApi from '@/service/community';
|
||||
import { showToast } from 'vant';
|
||||
import moment from 'moment';
|
||||
|
||||
const props = defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
isOpen: boolean;
|
||||
}>();
|
||||
const state = reactive({
|
||||
content: '',
|
||||
pageNumber: 1, // 一级评论页码
|
||||
pageSize: 30, // 一级评论一页的数量
|
||||
list: <Array<Types.Community.CommentItem>>[], // 一级评论列表
|
||||
});
|
||||
// 上拉加载及下拉刷新参数
|
||||
const moreParams = reactive({
|
||||
loading: true,
|
||||
refreshing: false,
|
||||
finished: false,
|
||||
isNoData: false,
|
||||
error: false,
|
||||
isHigehtMax: false,
|
||||
});
|
||||
const emit = defineEmits(['addComment', 'close']);
|
||||
const isShow = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
|
||||
// 获取评论数据
|
||||
const getFirstList = async (type: string) => {
|
||||
try {
|
||||
let req = {
|
||||
objID: String(props.videoInfo.id),
|
||||
curTime: new Date().toISOString(),
|
||||
pageNumber: String(state.pageNumber),
|
||||
pageSize: String(state.pageSize),
|
||||
};
|
||||
let res: any = await CommunityApi.getCommentList(req);
|
||||
moreParams.loading = false;
|
||||
moreParams.refreshing = false;
|
||||
let list = res.list || [];
|
||||
if (type === 'refresh') {
|
||||
state.list = list;
|
||||
} else {
|
||||
state.list = state.list.concat(list);
|
||||
}
|
||||
if (state.pageNumber == 1 && state.list.length == 0) {
|
||||
moreParams.isNoData = true;
|
||||
}
|
||||
if (!res.hasNext) {
|
||||
moreParams.finished = true;
|
||||
}
|
||||
} catch (e) {
|
||||
moreParams.loading = false;
|
||||
moreParams.error = true;
|
||||
}
|
||||
};
|
||||
// 点赞
|
||||
const clickZan = async (item: Types.Community.CommentItem) => {
|
||||
try {
|
||||
let req = {
|
||||
type: 'comment',
|
||||
objID: item.id,
|
||||
};
|
||||
if (!item.isLike) {
|
||||
await CommunityApi.zan(req);
|
||||
item.isLike = true;
|
||||
item.likeCount++;
|
||||
showToast('点赞成功');
|
||||
} else {
|
||||
await CommunityApi.cancleZan(req);
|
||||
item.isLike = false;
|
||||
item.likeCount--;
|
||||
showToast('取消成功');
|
||||
}
|
||||
} catch (e) {
|
||||
showToast(`${item.isLike ? '取消失败' : '点赞失败'}`);
|
||||
}
|
||||
};
|
||||
// 确认提交评论
|
||||
const submintComment = async () => {
|
||||
try {
|
||||
let req = {};
|
||||
req = {
|
||||
objID: props.videoInfo.id,
|
||||
level: 1,
|
||||
content: state.content,
|
||||
};
|
||||
let res: any = await CommunityApi.sendComment(req);
|
||||
state.content = ''; // 评论输入框内容清空
|
||||
state.list.unshift(res);
|
||||
emit('addComment');
|
||||
showToast('评论成功');
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
const onLoad = () => {
|
||||
moreParams.loading = true;
|
||||
state.pageNumber++;
|
||||
getFirstList('');
|
||||
};
|
||||
const onRefresh = () => {
|
||||
state.pageNumber = 1;
|
||||
moreParams.refreshing = true;
|
||||
moreParams.finished = false;
|
||||
getFirstList('refresh');
|
||||
};
|
||||
const getList = () => {
|
||||
state.pageNumber = 1;
|
||||
moreParams.loading = false;
|
||||
moreParams.finished = false;
|
||||
state.list = <Array<Types.Community.CommentItem>>[];
|
||||
getFirstList('');
|
||||
};
|
||||
defineExpose({
|
||||
getList,
|
||||
moreParams,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.van-popup) {
|
||||
background: transparent !important;
|
||||
}
|
||||
:deep(.van-cell) {
|
||||
border: 1px solid rgb(112, 112, 112);
|
||||
border-radius: 5px;
|
||||
padding: unset;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
.van-field__body {
|
||||
padding-left: 10px;
|
||||
.van-field__control {
|
||||
color: $titleColor;
|
||||
font-weight: 500;
|
||||
}
|
||||
::placeholder {
|
||||
color: $titleColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.van-pull-refresh) {
|
||||
.van-pull-refresh__track {
|
||||
min-height: 300px;
|
||||
}
|
||||
}
|
||||
:deep(.lazy_img) {
|
||||
.laz_com {
|
||||
.animationImg {
|
||||
background: linear-gradient(to right, rgba(253, 191, 80, 0.4), rgba(255, 224, 167, 0.4));
|
||||
border-radius: 50%;
|
||||
.loading {
|
||||
background-size: 20px 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.wrapper {
|
||||
padding: 20px 14px 15px;
|
||||
height: 480px;
|
||||
background: url('./../../assets/images/png/commentBg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.header {
|
||||
.left {
|
||||
padding-left: 10px;
|
||||
.title {
|
||||
width: 58px;
|
||||
height: 22px;
|
||||
background: url('./../../assets/images/png/commentTitle.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.total {
|
||||
font-size: 12px;
|
||||
color: rgb(153, 153, 153);
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
.close {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
.main {
|
||||
height: 320px;
|
||||
margin-top: 40px;
|
||||
.commentBox {
|
||||
margin-bottom: 15px;
|
||||
.commentInfo {
|
||||
display: flex;
|
||||
.avatar {
|
||||
height: 33px;
|
||||
width: 33px;
|
||||
border-radius: 50%;
|
||||
margin-right: 12px;
|
||||
}
|
||||
.info {
|
||||
color: rgb(102, 102, 102);
|
||||
.name {
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
.vipIcon {
|
||||
height: 13.4px;
|
||||
width: 24.4px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.genderIcon {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.text {
|
||||
font-size: 12px;
|
||||
margin: 7px 0 7px;
|
||||
}
|
||||
.address {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.zanBox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.zanIcon {
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.zanNumber {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer {
|
||||
.addComment {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
.commentInputBox {
|
||||
height: 34px;
|
||||
width: 290px;
|
||||
background-color: rgb(244, 244, 248);
|
||||
border: unset;
|
||||
border-radius: 34px;
|
||||
:deep(.van-field__body) {
|
||||
padding-top: 5px;
|
||||
padding-left: 20px;
|
||||
::placeholder {
|
||||
color: rgb(184, 184, 209);
|
||||
}
|
||||
}
|
||||
}
|
||||
.commentIcon {
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
margin-left: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@/service/entertainment
|
||||
@@ -1,986 +0,0 @@
|
||||
<template>
|
||||
<van-popup
|
||||
v-if="props.renderType === 'popup'"
|
||||
v-model:show="isShow"
|
||||
position="bottom"
|
||||
z-index="2001"
|
||||
teleport="body"
|
||||
@close="emits('close')"
|
||||
>
|
||||
<div ref="CommentBox" class="comment-wrap"></div>
|
||||
</van-popup>
|
||||
<div v-else ref="CommentBox" class="comment-wrap"></div>
|
||||
|
||||
<Teleport v-if="CommentBox" :to="CommentBox">
|
||||
<div class="wrapper" :class="[props.renderType || '', { blackBackground }]">
|
||||
<div class="headerBox">
|
||||
<div class="horizontalLineBlock"></div>
|
||||
<div class="title">评论({{ state.lfCount }})</div>
|
||||
</div>
|
||||
<div class="main overflow-y-auto">
|
||||
<PullRefresh :params="moreParams" @onLoad="onLoad" @onRefresh="onRefresh">
|
||||
<div class="qiuckSearchBox flex-vcenter" v-if="state.quickSearchObj.title">
|
||||
<span>大家都在搜索:</span>
|
||||
<van-notice-bar
|
||||
v-if="state.quickSearchObj.title"
|
||||
@click.stop="jumpAdv(state.quickSearchObj)"
|
||||
color="#f25477"
|
||||
background="transparent"
|
||||
scrollable
|
||||
:text="state.quickSearchObj.title"
|
||||
/>
|
||||
<!-- <div class="qiuckText" @click.stop="jumpAdv(state.quickSearchObj)">-->
|
||||
<!-- {{ state.quickSearchObj.title }}-->
|
||||
<!-- <SvgIcon name="qiuckSearchIcon" />-->
|
||||
<!-- </div>-->
|
||||
<!-- <SvgIcon name="qiuckSearchIcon" class="qiuckSearchIcon" />-->
|
||||
</div>
|
||||
<div class="commentBox" v-for="item in state.list" :key="item.id">
|
||||
<div v-if="item.isGodComment" class="goldComment"></div>
|
||||
<div class="pinToTopComment" v-if="item.pinToTop"></div>
|
||||
<LazyImg
|
||||
:src="item.userPortrait"
|
||||
class="avatar"
|
||||
:key="item.userPortrait"
|
||||
@click="toUser(item, item.isOfficial)"
|
||||
/>
|
||||
<div class="commentInfoBox">
|
||||
<div class="name flex-vcenter">
|
||||
<span class="ellipsis">
|
||||
{{ item.userName || '未知用户' }}
|
||||
</span>
|
||||
<SvgIcon v-if="[1, 2].includes(item.vipLevel)" name="cmVip" />
|
||||
<SvgIcon v-else-if="item.vipLevel === 3" name="cmSvip" />
|
||||
</div>
|
||||
<div class="content" v-html="rearrangeText(item.content)"></div>
|
||||
<div class="commentInfo flex-center-between" v-if="!item.isOfficial && !item.pinToTop">
|
||||
<div class="time">{{ moment(item.createdAt).format('YYYY-MM-DD HH:mm:ss') }}</div>
|
||||
<div class="optBox flex-vcenter">
|
||||
<img class="icon" src="@/assets/images/png/msgIcon.png" @click="reply(item, undefined, undefined)" />
|
||||
<div class="zanBox">
|
||||
<!-- <SvgIcon @click="clickLike(item)" v-if="item.isLike" name="movieZan" />-->
|
||||
<!-- <SvgIcon @click="clickLike(item)" v-else name="movieUnZan" />-->
|
||||
<img
|
||||
class="icon"
|
||||
@click="clickLike(item)"
|
||||
v-if="item.isLike"
|
||||
src="@/assets/images/png/movieZan.png"
|
||||
/>
|
||||
<img class="icon" @click="clickLike(item)" v-else src="@/assets/images/png/movieUnZan.png" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 子评论区域 -->
|
||||
<div class="subCommentArea">
|
||||
<div class="subShow" v-if="item.Info && item.Info.length">
|
||||
<div class="subCommentBox" v-for="subItem in item.Info" :key="subItem.id">
|
||||
<LazyImg :src="subItem.userPortrait" class="avatar" :key="subItem.userPortrait" />
|
||||
<div class="commentInfoBox">
|
||||
<div class="nameBox flex-vcenter">
|
||||
<div class="name">{{ subItem.userName || '未知用户' }}</div>
|
||||
<SvgIcon name="replyArrow" v-if="subItem.toUserName" />
|
||||
<div class="name">{{ subItem.toUserName }}</div>
|
||||
</div>
|
||||
<div class="content" v-html="rearrangeText(subItem.content)"></div>
|
||||
<div class="commentInfo flex-center-between">
|
||||
<div class="time">{{ moment(subItem.createdAt).format('YYYY-MM-DD HH:mm:ss') }}</div>
|
||||
<div class="optBox flex-vcenter">
|
||||
<img
|
||||
class="icon"
|
||||
src="@/assets/images/png/msgIcon.png"
|
||||
@click="reply(subItem, subItem.userID, item.id)"
|
||||
/>
|
||||
<div class="zanBox">
|
||||
<!-- <SvgIcon @click="clickLike(subItem)" v-if="subItem.isLike" name="movieZan" />-->
|
||||
<!-- <SvgIcon @click="clickLike(subItem)" v-else name="movieUnZan" />-->
|
||||
<img
|
||||
class="icon"
|
||||
@click="clickLike(subItem)"
|
||||
v-if="subItem.isLike"
|
||||
src="@/assets/images/png/movieZan.png"
|
||||
/>
|
||||
<img
|
||||
class="icon"
|
||||
@click="clickLike(subItem)"
|
||||
v-else
|
||||
src="@/assets/images/png/movieUnZan.png"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="subShow pdunset" v-if="item.subShow">
|
||||
<div class="subCommentBox" v-for="subItem in item.subList" :key="subItem.id">
|
||||
<LazyImg
|
||||
:src="subItem.userPortrait"
|
||||
class="avatar"
|
||||
:key="subItem.userPortrait"
|
||||
@click="toUser(subItem, subItem.isOfficial)"
|
||||
/>
|
||||
<div class="commentInfoBox">
|
||||
<div class="nameBox flex-vcenter">
|
||||
<div class="name">{{ subItem.userName || '未知用户' }}</div>
|
||||
<SvgIcon name="replyArrow" v-if="subItem.toUserName" />
|
||||
<div class="name">{{ subItem.toUserName }}</div>
|
||||
</div>
|
||||
<div class="content" v-html="rearrangeText(subItem.content)"></div>
|
||||
<div class="commentInfo flex-center-between">
|
||||
<div class="time">{{ moment(subItem.createdAt).format('YYYY-MM-DD HH:mm:ss') }}</div>
|
||||
<div class="optBox flex-vcenter">
|
||||
<!-- <SvgIcon-->
|
||||
<!-- name="msg"-->
|
||||
<!-- @click="reply(subItem, subItem.userID, item.id)"-->
|
||||
<!-- :color="blackBackground ? '#fff' : '#000'"-->
|
||||
<!-- />-->
|
||||
<img
|
||||
class="icon"
|
||||
@click="reply(subItem, subItem.userID, item.id)"
|
||||
src="@/assets/images/png/msgIcon.png"
|
||||
/>
|
||||
<div class="zanBox">
|
||||
<img
|
||||
class="icon"
|
||||
@click="clickLike(subItem)"
|
||||
v-if="subItem.isLike"
|
||||
src="@/assets/images/png/movieZan.png"
|
||||
/>
|
||||
<img
|
||||
class="icon"
|
||||
@click="clickLike(subItem)"
|
||||
v-else
|
||||
src="@/assets/images/png/movieUnZan.png"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Loading v-if="item.subLoading" />
|
||||
</div>
|
||||
<div class="expandBox flex-vcenter" v-if="item.commCount - 1 > 0">
|
||||
<div
|
||||
class="expandMore flex-vcenter"
|
||||
@click="expandComment(item)"
|
||||
v-if="!(item.subList && item.subList.length) && !item.subHasNext"
|
||||
>
|
||||
<div class="flex-vcenter">
|
||||
—— 展开{{ item.commCount - 1 }}条回复
|
||||
<SvgIcon name="packDown" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="expandMore flex-vcenter" @click="loadMore(item)" v-if="item.subHasNext">
|
||||
<div class="flex-vcenter">查看更多></div>
|
||||
</div>
|
||||
<div class="closeBox" @click="expandComment(item)" v-if="item.subList && item.subList.length">
|
||||
<div class="close flex-center-center">
|
||||
收起
|
||||
<SvgIcon name="packUp" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PullRefresh>
|
||||
</div>
|
||||
<div class="mask" v-if="state.childrenCommentObj" @click="cancelReply"></div>
|
||||
<!-- 评论 -->
|
||||
<div class="bottomBox">
|
||||
<div class="commentBtnBox flex-center-between">
|
||||
<div class="commentInput flex-vcenter">
|
||||
<van-field
|
||||
ref="contentRef"
|
||||
v-model="state.content"
|
||||
:placeholder="state.placeholder"
|
||||
input-align="left"
|
||||
:clearable="false"
|
||||
:border="false"
|
||||
@blur="blur"
|
||||
/>
|
||||
</div>
|
||||
<div class="commentBtn" @click.stop="sendBtn"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
|
||||
<!-- 会员提示框 -->
|
||||
<VipTipPopup ref="vipTipPopupRef" :isCancelReturn="true" />
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'commentBox',
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive, ref, PropType, nextTick } from 'vue';
|
||||
import { showToast } from 'vant';
|
||||
import { useGlobalStore } from '@/stores/global';
|
||||
import { addVideoHistory } from '@/utils';
|
||||
import { HistoryVideoType } from '@/enums/app';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import moment from 'moment';
|
||||
import CommunityApi from '@/service/community';
|
||||
import VideoApi from '@/service/video';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const CommentBox = ref();
|
||||
const vipTipPopupRef = ref();
|
||||
const userStore = useUserStore();
|
||||
const props = defineProps({
|
||||
isOpen: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
objType: {
|
||||
type: String,
|
||||
default: 'video',
|
||||
},
|
||||
blackBackground: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
renderType: {
|
||||
type: String as PropType<'popup' | 'normal'>, //popup弹窗形式,normal正常布局流
|
||||
default: 'popup',
|
||||
},
|
||||
});
|
||||
const { openLoading, closeLoading } = useLoading();
|
||||
const isShow = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
const globalStore = useGlobalStore();
|
||||
const emits = defineEmits(['addComment', 'close']);
|
||||
const contentRef = ref<HTMLElement>();
|
||||
|
||||
const state = reactive({
|
||||
content: '',
|
||||
list: <Array<any>>[], // 评论列表
|
||||
pageNumber: 1, // 评论页码
|
||||
pageSize: 15, // 评论一页的数量
|
||||
subPageNumber: 1, // 子评论页码
|
||||
subPageSize: 15, // 子评论一页的数量
|
||||
videoInfo: <any>{},
|
||||
lfCount: 0,
|
||||
placeholder: '请输入评论内容',
|
||||
childrenCommentObj: <any>null,
|
||||
quickSearchObj: <any>{}, // 大家都在搜对象
|
||||
});
|
||||
// 上拉加载及下拉刷新参数
|
||||
const moreParams = reactive({
|
||||
loading: true,
|
||||
refreshing: false,
|
||||
finished: false,
|
||||
isNoData: false,
|
||||
error: false,
|
||||
isHigehtMax: false,
|
||||
});
|
||||
// 获取评论数据
|
||||
const getList = async (type: string) => {
|
||||
try {
|
||||
let req = {
|
||||
objID: String(state.videoInfo.id),
|
||||
objType: props.objType,
|
||||
curTime: new Date().toISOString(),
|
||||
pageNumber: String(state.pageNumber),
|
||||
pageSize: String(state.pageSize),
|
||||
};
|
||||
let res: any = await CommunityApi.getCommentList(req);
|
||||
state.lfCount = res.total || 0;
|
||||
moreParams.loading = false;
|
||||
moreParams.refreshing = false;
|
||||
let list = res.list || [];
|
||||
if (type === 'refresh') {
|
||||
state.list = list;
|
||||
} else {
|
||||
state.list = state.list.concat(list);
|
||||
}
|
||||
if (state.pageNumber == 1 && res.quickSearchList && res.quickSearchList.length) {
|
||||
res.quickSearchList.map((item: any) => {
|
||||
if (item.type == 2) {
|
||||
state.quickSearchObj = item;
|
||||
} else {
|
||||
// 评论对象
|
||||
const _reg = new RegExp(item.searchKeyword, 'g');
|
||||
let obj = {
|
||||
id: item.id,
|
||||
content: item.title.replace(
|
||||
_reg,
|
||||
`<span style="color:rgba(11, 153, 255, 1)" onclick="jumpKeywords('${item.link},${item.id}')">${item.searchKeyword}</span>`,
|
||||
),
|
||||
userName: item.userName,
|
||||
userID: item.userID,
|
||||
Info: [],
|
||||
userPortrait: item.userPortrait,
|
||||
pinToTop: true,
|
||||
};
|
||||
state.list.splice(1, 0, obj);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (state.pageNumber == 1 && state.list.length == 0) {
|
||||
moreParams.isNoData = true;
|
||||
}
|
||||
if (!res.hasNext) {
|
||||
moreParams.finished = true;
|
||||
}
|
||||
} catch (e) {
|
||||
moreParams.loading = false;
|
||||
moreParams.error = true;
|
||||
}
|
||||
};
|
||||
const rearrangeText = (content: string) => {
|
||||
if (content && content.indexOf('#') != -1) {
|
||||
let startIndex = content.indexOf('#');
|
||||
let endIndex = content.indexOf('#', startIndex + 1);
|
||||
let jsonText = content.substring(startIndex, endIndex + 1);
|
||||
const _reg = new RegExp(jsonText, 'g');
|
||||
return content.replace(
|
||||
_reg,
|
||||
`<span style="color:#f25477" onclick="jumpSerialNoVideo('${jsonText.substr(
|
||||
1,
|
||||
jsonText.length - 2,
|
||||
)}')">${jsonText}</span>`,
|
||||
);
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
};
|
||||
// // 番号跳转视频
|
||||
// const jumpSerialNoVideo = async (serialNo: any) => {
|
||||
// if (!serialNo) return showToast('番号数据不存在');
|
||||
// try {
|
||||
// let req = {
|
||||
// seedId: serialNo,
|
||||
// };
|
||||
// let res: any = await CommunityApi.getCheckInfo(req);
|
||||
// if (res && res.id) {
|
||||
// router.push({
|
||||
// path: '/movieDetails',
|
||||
// query: {
|
||||
// vid: res.vidInfo.id,
|
||||
// uid: res.vidInfo.publisher?.uid,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// } catch (e) {
|
||||
// console.log(e);
|
||||
// }
|
||||
// };
|
||||
// 内链跳转
|
||||
const jumpKeywords = (str: any) => {
|
||||
const strArr = str.split(',');
|
||||
const link = strArr[0];
|
||||
const id = strArr[1];
|
||||
let obj = {
|
||||
link: link,
|
||||
id: id,
|
||||
};
|
||||
jumpAdv(obj);
|
||||
};
|
||||
|
||||
const toUser = (item: any, isOfficial: boolean) => {
|
||||
if(!isOfficial){
|
||||
router.push({ path: '/userInfo', query: { uid: item.userID } });
|
||||
}
|
||||
};
|
||||
// window.jumpKeywords = jumpKeywords;
|
||||
// window.jumpSerialNoVideo = jumpSerialNoVideo;
|
||||
const onLoad = () => {
|
||||
moreParams.loading = true;
|
||||
state.pageNumber++;
|
||||
getList('');
|
||||
};
|
||||
const onRefresh = () => {
|
||||
state.pageNumber = 1;
|
||||
moreParams.refreshing = true;
|
||||
moreParams.finished = false;
|
||||
moreParams.isNoData = false;
|
||||
getList('refresh');
|
||||
};
|
||||
// 评论成功后增加评论数据
|
||||
const addComment = (res: any, childrenCommentObj: any) => {
|
||||
moreParams.isNoData = false;
|
||||
if (childrenCommentObj) {
|
||||
state.list.map((comment: any) => {
|
||||
if (comment.id == childrenCommentObj.id) {
|
||||
if (!comment.subList) {
|
||||
comment.subLoading = false;
|
||||
comment.subList = [];
|
||||
comment.subHasNext = true;
|
||||
comment.subShow = true;
|
||||
}
|
||||
comment.Info.unshift(res);
|
||||
}
|
||||
return comment;
|
||||
});
|
||||
} else {
|
||||
state.list.unshift(res);
|
||||
}
|
||||
};
|
||||
// 点赞
|
||||
const clickLike = async (comment: any) => {
|
||||
try {
|
||||
let req = {
|
||||
type: 'comment',
|
||||
objID: comment.id,
|
||||
};
|
||||
if (!comment.isLike) {
|
||||
await CommunityApi.zan(req);
|
||||
comment.isLike = true;
|
||||
comment.likeCount++;
|
||||
showToast('点赞成功');
|
||||
} else {
|
||||
await CommunityApi.cancleZan(req);
|
||||
comment.isLike = false;
|
||||
comment.likeCount--;
|
||||
showToast('取消成功');
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
// 回复二级评论
|
||||
const reply = (comment: any, toUserID: any, parentId: any) => {
|
||||
comment.toUserID = toUserID ? toUserID : undefined;
|
||||
comment.rid = toUserID ? comment.id : undefined;
|
||||
comment.id = toUserID ? parentId : comment.id;
|
||||
state.childrenCommentObj = comment;
|
||||
state.placeholder = `回复@${comment.userName}`;
|
||||
nextTick(() => {
|
||||
contentRef.value?.focus();
|
||||
});
|
||||
};
|
||||
// 展开评论
|
||||
const expandComment = async (comment: any) => {
|
||||
if (!comment.subShow) {
|
||||
comment.subShow = true;
|
||||
comment.subHasNext = true; // 子评论是否还有下一页数据
|
||||
comment.subList = []; // 子评论列表
|
||||
comment.subLoading = true; // 子评论加载loading
|
||||
state.subPageNumber = 1;
|
||||
const resObj: any = await getSubList(comment);
|
||||
comment.subLoading = false;
|
||||
comment.subHasNext = resObj.subHasNext;
|
||||
if (resObj.list.length) {
|
||||
if (!comment.subList) {
|
||||
comment.subList = [];
|
||||
}
|
||||
comment.subList = comment.subList.concat(resObj.list);
|
||||
}
|
||||
} else {
|
||||
comment.subLoading = false;
|
||||
comment.subList = []; // 清空子评论列表
|
||||
comment.subHasNext = false; // 子评论是否还有下一页数据
|
||||
comment.subShow = false;
|
||||
}
|
||||
};
|
||||
// 获取更多评论
|
||||
const loadMore = async (comment: any) => {
|
||||
comment.subLoading = true;
|
||||
state.subPageNumber++;
|
||||
const resObj: any = await getSubList(comment);
|
||||
comment.subLoading = false;
|
||||
comment.subList = comment.subList.concat(resObj.list);
|
||||
comment.subHasNext = resObj.subHasNext;
|
||||
};
|
||||
// 获取二级评论
|
||||
const getSubList = async (comment: any) => {
|
||||
let resObj = {
|
||||
subHasNext: true,
|
||||
list: <any>[],
|
||||
};
|
||||
let req = {
|
||||
objID: comment.objID,
|
||||
cmtId: comment.id,
|
||||
fstID: comment.Info[0].id, // 第一条评论的ID
|
||||
curTime: new Date().toISOString(),
|
||||
pageNumber: state.subPageNumber,
|
||||
pageSize: state.subPageSize,
|
||||
};
|
||||
let res: any = await CommunityApi.getSecCommentList(req);
|
||||
if (res.list && res.list.length > 0) {
|
||||
resObj.list = res.list;
|
||||
}
|
||||
if (!res.hasNext) {
|
||||
resObj.subHasNext = false;
|
||||
}
|
||||
return resObj;
|
||||
};
|
||||
const sendBtn = async () => {
|
||||
if (!userStore.isVip) {
|
||||
vipTipPopupRef.value?.openPop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.content) {
|
||||
showToast('请输入评论内容');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let req: any = {};
|
||||
if (!state.childrenCommentObj) {
|
||||
req = {
|
||||
objID: state.videoInfo.id,
|
||||
objType: props.objType,
|
||||
level: 1,
|
||||
content: state.content,
|
||||
};
|
||||
} else {
|
||||
// 二级评论参数
|
||||
req = {
|
||||
objID: state.videoInfo.id,
|
||||
objType: props.objType,
|
||||
// objType: state.videoInfo.newsType,
|
||||
level: 2,
|
||||
content: state.content,
|
||||
cid: state.childrenCommentObj.id,
|
||||
// userID: state.childrenCommentObj.userID,
|
||||
userID: userStore.userInfo.uid,
|
||||
rid: state.childrenCommentObj.toUserID ? state.childrenCommentObj.rid : undefined,
|
||||
toUserID: state.childrenCommentObj.toUserID,
|
||||
};
|
||||
}
|
||||
// if (req.objType == 'POST' || req.objType == 'SP' || req.objType == 'SHARE_POST' || req.objType == 'SHOP_POST') {
|
||||
// req.objType = 'video';
|
||||
// }
|
||||
openLoading();
|
||||
let res: any = await CommunityApi.sendComment(req);
|
||||
state.content = ''; // 评论输入框内容清空
|
||||
if (res != 'success') {
|
||||
state.lfCount++;
|
||||
addComment(res, state.childrenCommentObj);
|
||||
}
|
||||
cancelReply();
|
||||
showToast('评论成功 请耐心等待审核');
|
||||
emits('addComment');
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
closeLoading();
|
||||
}
|
||||
};
|
||||
// 回复一级评论
|
||||
const cancelReply = () => {
|
||||
state.childrenCommentObj = <any>null;
|
||||
state.placeholder = '请输入评论内容';
|
||||
state.content = '';
|
||||
};
|
||||
const getCommentList = () => {
|
||||
state.pageNumber = 1;
|
||||
moreParams.loading = false;
|
||||
moreParams.finished = false;
|
||||
state.list = <Array<Types.Video.CommentItem>>[];
|
||||
getList('');
|
||||
};
|
||||
const blur = () => {
|
||||
window.scrollTo(0, 0);
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
getCommentList,
|
||||
moreParams,
|
||||
state,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/styles/mixins.scss';
|
||||
|
||||
:deep(.van-popup) {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
height: 70vh;
|
||||
font-weight: 400 !important;
|
||||
.headerBox {
|
||||
//height: 66px;
|
||||
background: #f5f5f5;
|
||||
border-radius: 20px 20px 0 0;
|
||||
//padding-top: 18px;
|
||||
margin-bottom: 18px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
|
||||
.horizontalLineBlock {
|
||||
height: 5px;
|
||||
width: 36px;
|
||||
background: rgba(51, 51, 51, 1);
|
||||
border-radius: 5px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
//padding-left: 20px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
height: 55vh;
|
||||
//padding: 15px;
|
||||
background: #f5f5f5;
|
||||
.qiuckSearchBox {
|
||||
color: #333333;
|
||||
font-size: 14px;
|
||||
margin: 3px 0 15px;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
|
||||
:deep(.van-notice-bar__content) {
|
||||
color: #f25477 !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
:deep(.van-notice-bar) {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.qiuckSearchIcon {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
top: 2px;
|
||||
}
|
||||
.qiuckText {
|
||||
color: #f25477;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
> svg {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
top: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.commentBox {
|
||||
display: flex;
|
||||
//margin-bottom: 14px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.02);
|
||||
position: relative;
|
||||
|
||||
.goldComment {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
right: -10px;
|
||||
height: 69.25px;
|
||||
width: 76px;
|
||||
background: url('@/assets/images/png/goldComment.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.pinToTopComment {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
right: -10px;
|
||||
height: 69.25px;
|
||||
width: 76px;
|
||||
background: url('@/assets/images/png/pinToTopComment.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.avatar {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
transform: translateZ(0px);
|
||||
|
||||
:deep(.loading) {
|
||||
background-size: 18px 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.commentInfoBox {
|
||||
flex: 1;
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
|
||||
.name {
|
||||
color: #666666;
|
||||
font-weight: 500;
|
||||
flex: 1;
|
||||
|
||||
span {
|
||||
max-width: 240px;
|
||||
}
|
||||
|
||||
> svg {
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 10px;
|
||||
line-height: 20px;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.commentInfo {
|
||||
margin-top: 8px;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
|
||||
.time {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.optBox {
|
||||
color: rgba(51, 51, 51, 1);
|
||||
|
||||
svg {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.zanBox {
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.subCommentArea {
|
||||
margin-top: 11px;
|
||||
|
||||
.subShow {
|
||||
// padding: 4px 12px;
|
||||
.subCommentBox {
|
||||
display: flex;
|
||||
margin: 10px 0 0;
|
||||
|
||||
.avatar {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
transform: translateZ(0px);
|
||||
|
||||
:deep(.loading) {
|
||||
background-size: 13px 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.commentInfoBox {
|
||||
flex: 1;
|
||||
margin-left: 10px;
|
||||
font-size: 12px;
|
||||
|
||||
.nameBox {
|
||||
.name {
|
||||
height: 24px;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
flex: unset;
|
||||
}
|
||||
|
||||
> svg {
|
||||
margin: 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 3px;
|
||||
line-height: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.commentInfo {
|
||||
margin-top: 8px;
|
||||
|
||||
.time {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pdunset {
|
||||
padding-top: unset;
|
||||
}
|
||||
|
||||
.expandBox {
|
||||
color: #989898;
|
||||
font-size: 12px;
|
||||
flex: 1;
|
||||
padding: 11px 12px 12px;
|
||||
|
||||
svg {
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.closeBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mask {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 88;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.bottomBox {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
height: 92px;
|
||||
background-color: #000000;
|
||||
padding: 14px 16px 0px 16px;
|
||||
|
||||
.commentBtnBox {
|
||||
//height: 92px;
|
||||
width: 100%;
|
||||
// @include SafeArea('padding', 'bottom', 20px);
|
||||
box-shadow: 0px -1px 4px rgba(0, 0, 0, 0.1);
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.commentInput {
|
||||
border-radius: 16px;
|
||||
//border: 1px solid #e6e6e6;
|
||||
width: 255px;
|
||||
height: 32px;
|
||||
position: relative;
|
||||
flex: 1;
|
||||
padding: 0 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #999;
|
||||
background: #191919;
|
||||
|
||||
:deep(.van-cell) {
|
||||
padding: 10px 0;
|
||||
height: 44px;
|
||||
background-color: unset;
|
||||
border-radius: 12px;
|
||||
|
||||
::placeholder {
|
||||
font-size: 14px;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.van-field__control {
|
||||
font-size: 14px;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .linkBtn {
|
||||
// height: 40px;
|
||||
// width: 40px;
|
||||
// background: url('@/assets/images/png/home/linkBtn.png') no-repeat;
|
||||
// background-size: 100% 100%;
|
||||
// margin-left: 12px;
|
||||
// }
|
||||
.commentBtn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: url('@/assets/images/png/commit_send.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
margin-left: 11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.normal {
|
||||
height: unset;
|
||||
|
||||
.headerBox {
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
border-bottom: 0;
|
||||
|
||||
.horizontalLineBlock {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: $titleColor;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
background: transparent;
|
||||
height: unset;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bottomBox {
|
||||
position: fixed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.blackBackground {
|
||||
.main .commentBox .commentInfoBox .name {
|
||||
color: #f1f1f1;
|
||||
}
|
||||
|
||||
.headerBox .title {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.main .commentBox .commentInfoBox .content {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.main .commentBox .commentInfoBox .commentInfo .optBox,
|
||||
.main .commentBox .subCommentArea .subShow .subCommentBox .commentInfoBox .nameBox .name {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.main .commentBox .commentInfoBox .commentInfo .time,
|
||||
.main .commentBox .subCommentArea .subShow .subCommentBox .commentInfoBox .commentInfo .time {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
::deep(.van-list__finished-text) {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<div class="officialPopup">
|
||||
<van-popup v-model:show="state.isRewardShow" :style="{ backgroundColor: 'rgba(0, 0, 0, 0)' }">
|
||||
<div class="popupBox">
|
||||
<div class="listbox">
|
||||
<p class="flex-center-center">您还没有绑定邮箱</p>
|
||||
</div>
|
||||
<div class="btnBox flex-center-center">
|
||||
<div class="btn" @click="state.isRewardShow = false">取消</div>
|
||||
<div class="btn BindBtn" @click="$router.push('/bindEmail')">去绑定</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
|
||||
const configStore = useConfigStore();
|
||||
const state = reactive({
|
||||
isRewardShow: false,
|
||||
});
|
||||
|
||||
const openPop = () => {
|
||||
state.isRewardShow = true;
|
||||
};
|
||||
defineExpose({
|
||||
openPop,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.officialPopup {
|
||||
background-color: rgba(255, 255, 255);
|
||||
.popupBox {
|
||||
background: rgba(255, 255, 255);
|
||||
border-radius: 6px;
|
||||
height: 136px;
|
||||
width: 311px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
.listbox {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 22px;
|
||||
position: relative;
|
||||
p {
|
||||
padding-top: 35px;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
color: #000;
|
||||
font-size: 16px;
|
||||
}
|
||||
.btn {
|
||||
position: absolute;
|
||||
width: 85px;
|
||||
height: 35px;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
line-height: 35px;
|
||||
color: white;
|
||||
right: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btnBox {
|
||||
margin: 0 auto;
|
||||
.btn {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
line-height: 48px;
|
||||
border-top: 0.5px solid rgba(231, 231, 231, 1);
|
||||
}
|
||||
.BindBtn {
|
||||
color: $themeColor;
|
||||
border-left: 0.5px solid rgba(231, 231, 231, 1);
|
||||
}
|
||||
}
|
||||
:deep(.van-popup) {
|
||||
border-radius: 12px;
|
||||
}
|
||||
:deep(.van-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,38 +0,0 @@
|
||||
<template>
|
||||
<div class="empty_warp">
|
||||
<div class="empty_box">
|
||||
<div class="noDataIcon"></div>
|
||||
<div class="noData">暂无数据</div>
|
||||
<p>请稍后再试~</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.empty_warp {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 60px;
|
||||
padding-bottom: 120px;
|
||||
.noDataIcon {
|
||||
height: 140px;
|
||||
width: 247px;
|
||||
background: url('./../../assets/images/png/nodata2.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.noData {
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
padding-top: 14px;
|
||||
color: rgb(102, 102, 102);
|
||||
}
|
||||
p {
|
||||
padding-top: 8px;
|
||||
text-align: center;
|
||||
color: rgb(153, 153, 153);
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,105 +0,0 @@
|
||||
<template>
|
||||
<van-overlay :show="isShow">
|
||||
<div class="warp">
|
||||
<div class="content_warp">
|
||||
<div class="content">
|
||||
<div class="announcement_text">
|
||||
<h1>系统提示</h1>
|
||||
<h2>APP线路检测失败</h2>
|
||||
<h3>解决方案:</h3>
|
||||
<p>1.请检测您的网络是否正常,手机是否开了VPN或10分钟后再尝试访问。</p>
|
||||
<p>2.前往官网地址 jhs99.cc 下载最新版。</p>
|
||||
<p>3.前往Potato鉴黄师官方交流群。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn" @click="toPotato">前往群聊</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
const isShow = ref(true);
|
||||
const toPotato = () => {
|
||||
window.location.href = 'https://pzcp.org/jianhuangshigfq';
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.warp {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.content_warp {
|
||||
width: 312px;
|
||||
height: 301;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
padding-bottom: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
border-radius: 10px;
|
||||
.content {
|
||||
height: 230px;
|
||||
font-size: 14px;
|
||||
.announcement_text {
|
||||
padding: 16px 16px 0;
|
||||
height: 200px;
|
||||
white-space: pre-wrap;
|
||||
line-height: 22px;
|
||||
font-size: 13px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
h2 {
|
||||
margin-top: 20px;
|
||||
padding: 6px 0;
|
||||
font-size: 16px;
|
||||
color: rgb(234, 83, 55);
|
||||
}
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
color: rgb(38, 38, 38);
|
||||
font-weight: bold;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
p {
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
color: rgb(38, 38, 38);
|
||||
}
|
||||
}
|
||||
|
||||
.tip {
|
||||
padding: 0 16px;
|
||||
color: #ffc069;
|
||||
font-size: 12px;
|
||||
line-height: 22px;
|
||||
p {
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
height: 38px;
|
||||
width: 231px;
|
||||
background-color: $themeColor;
|
||||
color: white;
|
||||
border-radius: 10px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
line-height: 38px;
|
||||
margin: 0 auto 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,149 +0,0 @@
|
||||
<template>
|
||||
<!-- 浮窗 -->
|
||||
<div
|
||||
class="square"
|
||||
id="moveDiv"
|
||||
:class="{ closeSquare: isClose }"
|
||||
@mousedown="down()"
|
||||
@touchstart="down()"
|
||||
@mousemove.prevent.stop="move()"
|
||||
@touchmove.prevent.stop="move()"
|
||||
@mouseup="end()"
|
||||
@touchend="end()"
|
||||
@click="jumpUrl()"
|
||||
v-if="advObj"
|
||||
>
|
||||
<LazyImg class="squareImg" :src="advObj?.cover" />
|
||||
<div class="close" @click.stop="close" v-if="!isClose"></div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue';
|
||||
// import { AdType, getAdItem } from '@/utils/getConfig';
|
||||
import { AdType } from '@/enums/app';
|
||||
import { getAdItem } from '@/utils/getConfig';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
// 悬浮
|
||||
let flags = ref(false);
|
||||
let position = reactive({
|
||||
x: 0,
|
||||
y: 0,
|
||||
});
|
||||
let nx = ref();
|
||||
let ny = ref();
|
||||
let dx = ref();
|
||||
let dy = ref();
|
||||
let xPum = ref();
|
||||
let yPum = ref();
|
||||
let advObj = ref(); // 广告
|
||||
let isClose = ref(false);
|
||||
// 初始化广告
|
||||
init();
|
||||
function init() {
|
||||
advObj.value = getAdItem(AdType.SHORTVIDEOADV)[0];
|
||||
// console.log(getAdItem(AdType.SHORTVIDEOADV)[0].cover, '-------------');
|
||||
// console.log(advObj.value);
|
||||
}
|
||||
// 实现移动端拖拽
|
||||
function down() {
|
||||
flags.value = true;
|
||||
let touch;
|
||||
if ((event as any).touches) {
|
||||
touch = (event as any).touches[0];
|
||||
} else {
|
||||
touch = event;
|
||||
}
|
||||
position.x = touch.clientX;
|
||||
position.y = touch.clientY;
|
||||
dx.value = (document.getElementById('moveDiv') as HTMLElement).offsetLeft;
|
||||
dy.value = (document.getElementById('moveDiv') as HTMLElement).offsetTop;
|
||||
}
|
||||
function move() {
|
||||
if (flags.value) {
|
||||
let touch;
|
||||
if ((event as any).touches) {
|
||||
touch = (event as any).touches[0];
|
||||
} else {
|
||||
touch = event;
|
||||
}
|
||||
nx.value = touch.clientX - position.x;
|
||||
ny.value = touch.clientY - position.y;
|
||||
xPum.value = dx.value + nx.value;
|
||||
yPum.value = dy.value + ny.value;
|
||||
//添加限制:只允许在屏幕内拖动
|
||||
const maxWidth = document.body.clientWidth - 90; //屏幕宽度减去悬浮框宽高
|
||||
const maxHeight = document.body.clientHeight - 90;
|
||||
if (xPum.value < 0) {
|
||||
//屏幕x限制
|
||||
xPum.value = 0;
|
||||
} else if (xPum.value > maxWidth) {
|
||||
xPum.value = maxWidth;
|
||||
}
|
||||
if (yPum.value < 65) {
|
||||
//屏幕y限制
|
||||
yPum.value = 65;
|
||||
} else if (yPum.value > maxHeight) {
|
||||
yPum.value = maxHeight;
|
||||
}
|
||||
(document.getElementById('moveDiv') as HTMLElement).style.left = xPum.value + 'px';
|
||||
(document.getElementById('moveDiv') as HTMLElement).style.top = yPum.value + 'px';
|
||||
//阻止页面的滑动默认事件
|
||||
// document.addEventListener(
|
||||
// "touchmove",
|
||||
// function () {
|
||||
// // 1.2 如果碰到滑动问题,请注意是否获取到 touchmove
|
||||
// (event as any).preventDefault(); //jq 阻止冒泡事件
|
||||
// // event.stopPropagation(); // 如果没有引入jq 就用 stopPropagation()
|
||||
// },
|
||||
// { passive: true }
|
||||
// );
|
||||
}
|
||||
}
|
||||
//鼠标释放时候的函数
|
||||
function end() {
|
||||
flags.value = false;
|
||||
}
|
||||
function close() {
|
||||
isClose.value = true;
|
||||
}
|
||||
function jumpUrl() {
|
||||
if (isClose.value) return (isClose.value = false);
|
||||
jumpAdv(advObj.value);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.square {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
top: 60px;
|
||||
left: 5px;
|
||||
border-radius: 10px;
|
||||
// overflow: hidden;
|
||||
:deep(img) {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.squareImg {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
}
|
||||
.close {
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
top: -10px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
border-radius: 50%;
|
||||
background: url('../../assets/images/png/appsClose.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
.closeSquare {
|
||||
width: 20px;
|
||||
border-radius: 20px;
|
||||
.squareImg {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,87 +0,0 @@
|
||||
<template>
|
||||
<div class="fullScreenGallery">
|
||||
<van-swipe
|
||||
ref="swipeRef"
|
||||
class="my-swipe"
|
||||
indicator-color="white"
|
||||
:loop="isLoop"
|
||||
:autoplay="autoTime"
|
||||
:lazy-render="true"
|
||||
@change="change"
|
||||
>
|
||||
<van-swipe-item class="my-swier-item" v-for="url in videoInfo.seriesCover" :key="url">
|
||||
<div class="fullScreen_item" @touchstart="touchstart" @touchmove="touchmove">
|
||||
<AnimationImg :src="url" />
|
||||
</div>
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { SwipeInstance } from 'vant';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
}>();
|
||||
|
||||
const autoTime = ref(2000);
|
||||
const isLoop = ref(true);
|
||||
|
||||
const swipeRef = ref<SwipeInstance>();
|
||||
|
||||
function change(index: number) {
|
||||
console.log(index);
|
||||
}
|
||||
const startX = ref();
|
||||
const startY = ref();
|
||||
function touchstart(e: any) {
|
||||
// 如果你要阻止点击事件,请反注释下一行代码
|
||||
// e.preventDefault()
|
||||
startX.value = e.touches[0].clientX;
|
||||
startY.value = e.touches[0].clientY;
|
||||
}
|
||||
function touchmove(e: any) {
|
||||
// e.preventDefault()
|
||||
let moveX = e.touches[0].clientX;
|
||||
if (startX.value - moveX != 0) {
|
||||
// 右滑触发
|
||||
// do something
|
||||
isLoop.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.van-swipe__indicator) {
|
||||
width: 28px;
|
||||
height: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
:deep(.van-swipe__indicators) {
|
||||
bottom: 1%;
|
||||
}
|
||||
.fullScreenGallery {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.my-swipe,
|
||||
.van-swipe-item,
|
||||
.my-swier-item {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.fullScreen_item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
:deep(.van-image) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #000000 !important;
|
||||
}
|
||||
:deep(img) {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<div class="accountCredentialsPop">
|
||||
<!-- 账号凭证弹窗 -->
|
||||
<van-overlay v-model:show="isOpenRecharge" z-index="2001">
|
||||
<div class="wrapper">
|
||||
<div class="actTipBox">
|
||||
<div class="infoboxs">
|
||||
<div class="info">免费送金币啦!</div>
|
||||
<div class="infomessage">金币月卡赠送金币已到账</div>
|
||||
</div>
|
||||
<div class="actTipBtn">
|
||||
<div class="btn" @click="getCoin">请领取</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, computed } from 'vue';
|
||||
import { useAppStore } from '@/stores/app';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import MineApi from '@/service/mine';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const userStore = useUserStore();
|
||||
const props = defineProps<{
|
||||
isOpen: boolean;
|
||||
}>();
|
||||
const emits = defineEmits(['closeFree']);
|
||||
const isOpenRecharge = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
// 领取
|
||||
const getCoin = async () => {
|
||||
try {
|
||||
let res: any = await MineApi.getCoin();
|
||||
showToast('领取成功');
|
||||
emits('closeFree');
|
||||
} catch (e) {
|
||||
emits('closeFree');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.accountCredentialsPop {
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
.actTipBox {
|
||||
width: 292px;
|
||||
height: 152px;
|
||||
position: relative;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 6px;
|
||||
.infoboxs {
|
||||
height: calc(100% - 50px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
color: #333333;
|
||||
}
|
||||
.info {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.infomessage {
|
||||
font-size: 14px;
|
||||
}
|
||||
.actTipBtn {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
color: #ffa641;
|
||||
border-top: solid 1px #eaeaea;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,212 +0,0 @@
|
||||
<template>
|
||||
<van-overlay :show="isShow" z-index="2001" @click="emit('close')">
|
||||
<div class="wrapper_gold">
|
||||
<div class="content">
|
||||
<div class="title">购买解锁</div>
|
||||
<div class="subTitle">—— unlock ——</div>
|
||||
<div class="amount_box" @click.stop>
|
||||
<div class="amount_item" :class="{ active: userInfo.isVip }">
|
||||
<img class="transactionGoldIcon" src="@/assets/images/png/goldIcon.png" />
|
||||
<span>{{ videoInfo.coins }}</span>
|
||||
<div class="subscript">会员优惠</div>
|
||||
</div>
|
||||
<div class="amount_item" :class="{ active: !userInfo.isVip }">
|
||||
<img class="transactionGoldIcon" src="@/assets/images/png/goldIcon.png" />
|
||||
<span>{{ videoInfo.originCoins }}</span>
|
||||
<div class="subscript">非会员</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="couponBox" v-if="userInfo.goldVideoCoupon">
|
||||
<div class="couponItem flex-center-between" v-for="(item, index) in userInfo.goldVideoCoupon" :key="index">
|
||||
<div class="couponName">
|
||||
观影券({{ item.gold }}金币):
|
||||
<span>{{ item.count }}张</span>
|
||||
</div>
|
||||
<div class="useCouponBtn" @click.stop="selectCoupon(item)">立即使用</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="unlock_now" @click.stop="unlockNow(0)">立即解锁</div>
|
||||
</div>
|
||||
<div class="close" @click="emit('close')">
|
||||
<SvgIcon name="close" />
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import useLoading from '@/hooks/loading';
|
||||
import VideoApi from '@/service/video';
|
||||
import { computed } from 'vue';
|
||||
import { ProductType } from '@/enums/app';
|
||||
import { showToast } from 'vant';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const props = defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
isOpen: boolean;
|
||||
}>();
|
||||
const userInfo = useUserStore().userInfo;
|
||||
const router = useRouter();
|
||||
const { openLoading, closeLoading } = useLoading();
|
||||
const emit = defineEmits(['close', 'buySuccess']);
|
||||
const isShow = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
|
||||
const selectCoupon = (item: any) => {
|
||||
let money = userInfo.isVip ? props.videoInfo.coins : props.videoInfo.originCoins;
|
||||
if (item.gold < money) {
|
||||
showToast('观影券面值过小,请选择其他支付方式');
|
||||
} else {
|
||||
unlockNow(item.gold);
|
||||
}
|
||||
};
|
||||
|
||||
const unlockNow = (money: any) => {
|
||||
try {
|
||||
openLoading();
|
||||
let productID = props.videoInfo.id;
|
||||
if (!productID) {
|
||||
showToast('购买出错~');
|
||||
return;
|
||||
}
|
||||
VideoApi.videoBuying({ productType: ProductType.VIDEO, productID: productID, goldVideoCouponNum: money || 0 })
|
||||
.then(() => {
|
||||
showToast('购买成功');
|
||||
if (money) {
|
||||
for (let i = 0; i < userInfo.goldVideoCoupon.length; i++) {
|
||||
if (money == userInfo.goldVideoCoupon[i].gold) {
|
||||
if (userInfo.goldVideoCoupon[i].count > 1) {
|
||||
userInfo.goldVideoCoupon[i].count--;
|
||||
} else {
|
||||
userInfo.goldVideoCoupon.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
useUserStore().updateWallet();
|
||||
emit('buySuccess');
|
||||
})
|
||||
.catch((e) => {
|
||||
if (e.toString().indexOf('8000') != -1) {
|
||||
router.push('/welfareCenter');
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
closeLoading();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.wrapper_gold {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
.content {
|
||||
width: 312px;
|
||||
height: 254px;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
border-radius: 8px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
padding-top: 15px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
.title {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
font-weight: bold;
|
||||
}
|
||||
.subTitle {
|
||||
font-size: 12px;
|
||||
color: rgb(153, 153, 153);
|
||||
margin: 7px 0 36px;
|
||||
}
|
||||
.amount_box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.amount_item {
|
||||
width: 110px;
|
||||
height: 67px;
|
||||
border-radius: 10px;
|
||||
margin: 0px 10px 0;
|
||||
font-size: 20px;
|
||||
color: #ff7510;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
background-color: rgb(247, 247, 247);
|
||||
border: solid 1px rgb(191,191,191);
|
||||
padding-top: 10px;
|
||||
> img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.subscript {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 49px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
background: rgb(255, 135, 16);
|
||||
font-size: 10px;
|
||||
color: rgb(255, 255, 255);
|
||||
letter-spacing: 0.2px;
|
||||
border-radius: 8px 0 8px 0px;
|
||||
}
|
||||
}
|
||||
.active {
|
||||
border: solid 1px rgb(255,135,16);
|
||||
background-color: rgb(255, 227, 180);
|
||||
}
|
||||
}
|
||||
.couponBox {
|
||||
max-height: 100px;
|
||||
margin-top: 14px;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
.couponItem {
|
||||
padding: 0 30px;
|
||||
font-size: 14px;
|
||||
margin: 5px 0;
|
||||
.couponName {
|
||||
color: rgb(102, 102, 102);
|
||||
span {
|
||||
color: rgb(255, 13, 44);
|
||||
}
|
||||
}
|
||||
.useCouponBtn {
|
||||
color: rgb(255, 13, 44);
|
||||
}
|
||||
}
|
||||
}
|
||||
.unlock_now {
|
||||
width: 227px;
|
||||
height: 38px;
|
||||
background: rgb(255, 160, 1);
|
||||
border-radius: 10px;
|
||||
margin: 28px auto 20px;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.close {
|
||||
padding-top: 16px;
|
||||
svg {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,359 +0,0 @@
|
||||
<template>
|
||||
<van-overlay :show="isShow" z-index="2001" @click="emit('close')">
|
||||
<div class="wrapper_gold">
|
||||
<!-- <div class="content">
|
||||
<div class="title">温馨提示</div>
|
||||
<div class="subTitle">—— 需要花费{{ videoInfo.originCoins }}金币解锁观看 ——</div>
|
||||
<div class="amount_box" @click.stop>
|
||||
<img class="transactionGoldIcon" src="@/assets/images/png/goldIcon.png" />
|
||||
<span>{{ videoInfo.originCoins }}</span>
|
||||
金币
|
||||
</div>
|
||||
<div class="unlock_now" @click.stop="unlockNow(0)">确认</div>
|
||||
</div>
|
||||
<div class="close" @click="emit('close')">
|
||||
<SvgIcon name="close" />
|
||||
</div> -->
|
||||
<!-- <div class="content">-->
|
||||
<!-- <div class="title">购买当前影片</div>-->
|
||||
<!-- <div class="title-right" @click="emit('close')">关闭</div>-->
|
||||
<!-- <div class="goldContent">-->
|
||||
<!-- <div class="goldLeft">-->
|
||||
<!-- <div class="originalPrice">原价</div>-->
|
||||
<!-- <div class="ordinaryUser">普通用户</div>-->
|
||||
<!-- <div class="golds">-->
|
||||
<!-- <SvgIcon name="goldNew" class="goldNew" />-->
|
||||
<!-- <span>{{ videoInfo.originCoins }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="goldLeft">-->
|
||||
<!-- <div class="originalPrice isVip">会员</div>-->
|
||||
<!-- <div class="ordinaryUser">会员用户</div>-->
|
||||
<!-- <div class="golds">-->
|
||||
<!-- <SvgIcon name="goldNew" class="goldNew" />-->
|
||||
<!-- <span>{{ videoInfo.coins }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="goldBtn">-->
|
||||
<!-- <div class="cancle" @click="$router.push('aiUndress')">AI换脸</div>-->
|
||||
<!-- <div-->
|
||||
<!-- class="buyGold"-->
|
||||
<!-- v-if="walletInfo.amount < videoInfo.originCoins"-->
|
||||
<!-- @click="$router.push({ path: '/recharge', query: { name: 'wallet' } })"-->
|
||||
<!-- >-->
|
||||
<!-- 购买金币-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="buyGold" v-else @click.stop="unlockNow(0)">购买视频</div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div v-if="userInfo.goldVideoCoupon">-->
|
||||
<!-- <div class="movie" v-for="(item, index) in userInfo.goldVideoCoupon" :key="index">-->
|
||||
<!-- <span>观影次数*{{ item.count }}</span>-->
|
||||
<!-- <span @click.stop="selectCoupon(item)">使用次数购买</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<div class="content">
|
||||
<div class="title">购买当前影片</div>
|
||||
<div class="title-right" @click="emit('close')">
|
||||
<SvgIcon name="closeNew" class="goldNew" />
|
||||
</div>
|
||||
<div class="goldBox flex-vcenter">
|
||||
<div class="goldLeft">
|
||||
<div class="originalPri">原价:</div>
|
||||
<span>金币 {{ videoInfo.originCoins }}</span>
|
||||
</div>
|
||||
<div class="goldLeft">
|
||||
<div class="originalPri isVip">您的购买价格:</div>
|
||||
<span>金币 {{ videoInfo.coins }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goldBtn">
|
||||
<div class="buyGold cancle" v-if="isVip" @click="emit('close')">稍后再说</div>
|
||||
<!-- <div-->
|
||||
<!-- class="buyGold"-->
|
||||
<!-- v-if="walletInfo.amount < videoInfo.originCoins"-->
|
||||
<!-- @click="$router.push({ path: '/recharge', query: { name: 'wallet' } })"-->
|
||||
<!-- >-->
|
||||
<!-- 开通会员-->
|
||||
<!-- </div>-->
|
||||
<div class="buyGold cancle" v-else @click.stop="unlockNow(0)">原价购买</div>
|
||||
<div class="buyGold" v-if="isVip" @click.stop="unlockNow(0)">立即支付</div>
|
||||
<div class="buyGold" v-else @click="$router.push({ path: '/recharge', query: { name: 'member' } })">
|
||||
开通会员
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="userInfo.goldVideoCoupon">
|
||||
<div class="movie" v-for="(item, index) in userInfo.goldVideoCoupon" :key="index">
|
||||
<span>观影次数*{{ item.count }}</span>
|
||||
<span @click.stop="selectCoupon(item)">使用次数购买</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import useLoading from '@/hooks/loading';
|
||||
import VideoApi from '@/service/video';
|
||||
import { computed } from 'vue';
|
||||
import { ProductType } from '@/enums/app';
|
||||
import { showToast } from 'vant';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const props = defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
isOpen: boolean;
|
||||
}>();
|
||||
const { isVip, freeVideo30, userInfo, walletInfo } = useUserStore();
|
||||
const router = useRouter();
|
||||
const { openLoading, closeLoading } = useLoading();
|
||||
const emit = defineEmits(['close', 'buySuccess']);
|
||||
const isShow = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
const selectCoupon = (item: any) => {
|
||||
let money = userInfo.isVip ? props.videoInfo.coins : props.videoInfo.originCoins;
|
||||
if (item.gold < money) {
|
||||
showToast('观影券面值过小,请选择其他支付方式');
|
||||
} else {
|
||||
unlockNow(item.gold);
|
||||
}
|
||||
};
|
||||
|
||||
const unlockNow = (money: any) => {
|
||||
try {
|
||||
openLoading();
|
||||
let productID = props.videoInfo.id;
|
||||
if (!productID) {
|
||||
showToast('购买出错~');
|
||||
return;
|
||||
}
|
||||
VideoApi.videoBuying({ productType: ProductType.VIDEO, productID: productID, goldVideoCouponNum: money || 0 })
|
||||
.then(() => {
|
||||
showToast('购买成功');
|
||||
if (money) {
|
||||
for (let i = 0; i < userInfo.goldVideoCoupon.length; i++) {
|
||||
if (money == userInfo.goldVideoCoupon[i].gold) {
|
||||
if (userInfo.goldVideoCoupon[i].count > 1) {
|
||||
userInfo.goldVideoCoupon[i].count--;
|
||||
} else {
|
||||
userInfo.goldVideoCoupon.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
useUserStore().updateWallet();
|
||||
emit('buySuccess');
|
||||
})
|
||||
.catch((e) => {
|
||||
if (e.toString().indexOf('8000') != -1) {
|
||||
// router.push('/welfareCenter');
|
||||
router.push('/recharge?name=wallet');
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
closeLoading();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.wrapper_gold {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
.content {
|
||||
width: 311px;
|
||||
height: auto;
|
||||
// background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
// background-size: 100% 123px;
|
||||
border-radius: 12px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
// padding-top: 15px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
padding-bottom: 16px;
|
||||
.title {
|
||||
padding: 16px 24px;
|
||||
font-size: 18px;
|
||||
color: $titleColor;
|
||||
font-weight: bolder;
|
||||
background-color: $themeColor;
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
}
|
||||
|
||||
.title-right {
|
||||
font-size: 15px;
|
||||
color: rgba(255, 255, 255);
|
||||
font-weight: 600;
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 16px;
|
||||
}
|
||||
.goldBox {
|
||||
padding-top: 16px;
|
||||
flex-direction: column;
|
||||
.goldLeft {
|
||||
padding-bottom: 16px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 19.6px;
|
||||
text-align: center;
|
||||
color: #999999;
|
||||
span {
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.goldContent {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px 8px;
|
||||
.goldLeft {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
width: 141.5px;
|
||||
height: 150px;
|
||||
border: 1px solid $themeColor;
|
||||
border-radius: 12px;
|
||||
background: rgba(255, 214, 128, 0.35);
|
||||
position: relative;
|
||||
.originalPrice {
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: 0px;
|
||||
padding: 10px 16px;
|
||||
border-radius: 16px;
|
||||
border-bottom-left-radius: 0;
|
||||
background: rgba(247, 63, 2, 1);
|
||||
color: #ffffff;
|
||||
}
|
||||
.isVip {
|
||||
background: $themeColor;
|
||||
}
|
||||
.ordinaryUser {
|
||||
margin-bottom: 12px;
|
||||
font-size: 16px;
|
||||
color: $themeColor;
|
||||
}
|
||||
.golds {
|
||||
display: inline-block;
|
||||
.goldNew {
|
||||
margin-right: 4px;
|
||||
vertical-align: bottom;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
span {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.goldBtn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
.cancle {
|
||||
background: #F1A10099 !important;
|
||||
margin-right: 12px;
|
||||
}
|
||||
.buyGold {
|
||||
width: 139.5px;
|
||||
height: 40px;
|
||||
line-height: 10px;
|
||||
background: $themeColor;
|
||||
padding: 16px 10px;
|
||||
border-radius: 100px;
|
||||
}
|
||||
}
|
||||
.movie {
|
||||
padding-top: 16px;
|
||||
span:first-child {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
span:last-child {
|
||||
color: #f1a100;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
.subTitle {
|
||||
font-size: 12px;
|
||||
color: rgb(153, 153, 153);
|
||||
margin: 7px 0 36px;
|
||||
}
|
||||
.amount_box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: rgb(255, 135, 16);
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
.couponBox {
|
||||
max-height: 100px;
|
||||
margin-top: 14px;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
.couponItem {
|
||||
padding: 0 30px;
|
||||
font-size: 14px;
|
||||
margin: 5px 0;
|
||||
.couponName {
|
||||
color: rgb(102, 102, 102);
|
||||
span {
|
||||
color: rgb(255, 13, 44);
|
||||
}
|
||||
}
|
||||
.useCouponBtn {
|
||||
color: rgb(255, 13, 44);
|
||||
}
|
||||
}
|
||||
}
|
||||
.unlock_now {
|
||||
width: 227px;
|
||||
height: 38px;
|
||||
background: rgb(255, 160, 1);
|
||||
border-radius: 10px;
|
||||
margin: 28px auto 20px;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.close {
|
||||
padding-top: 16px;
|
||||
svg {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,91 +0,0 @@
|
||||
<template>
|
||||
<div class="header flex-center-between">
|
||||
<div class="back flex-center-center" @click="$router.go(-1)">
|
||||
<img class="backIcon" src="@/assets/images/png/navBarIcon.png" />
|
||||
</div>
|
||||
<div :class="isBlod ? 'title bloder' : 'title'">{{ title }}</div>
|
||||
<div class="right-btn" @click="rightBtn">
|
||||
<SvgIcon class="rightIcon" :name="rightIcon" v-if="rightIcon" />
|
||||
<div v-if="rightTitle">{{ rightTitle }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { useRouter } from 'vue-router';
|
||||
const router = useRouter();
|
||||
const props: any = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
default() {
|
||||
return '标题';
|
||||
},
|
||||
},
|
||||
rightTitle: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
rightIcon: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
path: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
isIcon: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default() {
|
||||
return false;
|
||||
},
|
||||
},
|
||||
isBlod: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default() {
|
||||
return false;
|
||||
},
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['rightFuc']);
|
||||
const rightBtn = () => {
|
||||
if (props.path) {
|
||||
router.push(props.path);
|
||||
} else {
|
||||
emit('rightFuc');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
height: 44px;
|
||||
padding: 0 16px;
|
||||
.back {
|
||||
.backIcon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
// color: white;
|
||||
color: $titleColor;
|
||||
font-size: 16px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
.bloder {
|
||||
font-weight: bolder;
|
||||
}
|
||||
.right-btn {
|
||||
color: rgb(128, 128, 128);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.rightIcon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,193 +0,0 @@
|
||||
<template>
|
||||
<div class="horizontaImgGroupBox" @click="openVideo">
|
||||
<div class="photoBox">
|
||||
<lazyImg class="cover" :src="state.videoInfo?.cover">
|
||||
<div class="subscriptInfo" v-if="!state.videoInfo?.type">
|
||||
<div class="label freeLabel" v-if="state.videoInfo?.coins == 0">免费</div>
|
||||
<!-- <div class="label" v-if="state.videoInfo?.originCoins == 0 && !state.videoInfo?.freeArea">
|
||||
<img src="./../../assets/images/png/vip.png" />
|
||||
VIP
|
||||
</div> -->
|
||||
<div class="goldCoinLabel flex-center-center" v-if="state.videoInfo?.coins != 0">
|
||||
<img src="@/assets/images/png/icon.png" />
|
||||
<span>{{ state.videoInfo?.originCoins }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="photoInfo flex-center-between">
|
||||
<div class="watchCountInfo flex-vcenter">
|
||||
<SvgIcon name="viewIcon" />
|
||||
<span>{{ watchCount(state.videoInfo?.playCount) }}</span>
|
||||
</div>
|
||||
<div class="photoQuantityInfo flex-vcenter">
|
||||
<SvgIcon name="album" />
|
||||
<span>{{ watchCount(state.videoInfo?.seriesCover ? state.videoInfo?.seriesCover.length : 0) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</lazyImg>
|
||||
<div class="title ellipsis">{{ state.videoInfo?.title }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { watchCount, videoTime } from '@/utils/index';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useVideoStore } from '@/stores/video';
|
||||
import { useDataStore } from '@/stores/game';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
|
||||
const router = useRouter();
|
||||
const videoStore = useVideoStore();
|
||||
const dataStore = useDataStore();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
videoList: Types.Video.VInfosItem[];
|
||||
isMovie?: boolean;
|
||||
queryPath?: string;
|
||||
isOneLine?: boolean;
|
||||
userInfo?: boolean;
|
||||
}>(),
|
||||
{
|
||||
videoInfo: () => <Types.Video.VInfosItem>{},
|
||||
videoList: () => [],
|
||||
isMovie: () => false,
|
||||
queryPath: () => '',
|
||||
isOneLine: () => false,
|
||||
userInfo: () => true,
|
||||
},
|
||||
);
|
||||
const emit = defineEmits(['changeVideo']);
|
||||
const state = {
|
||||
videoInfo: props.videoInfo,
|
||||
videoList: props.videoList,
|
||||
isMovie: props.isMovie,
|
||||
queryPath: props.queryPath,
|
||||
isOneLine: props.isOneLine,
|
||||
};
|
||||
const openVideo = () => {
|
||||
if (state.videoInfo.type) {
|
||||
jumpAdv(state.videoInfo);
|
||||
return;
|
||||
}
|
||||
if (state.isMovie) {
|
||||
emit('changeVideo', state.videoInfo);
|
||||
} else {
|
||||
dataStore.setAData(state.videoInfo);
|
||||
router.push({
|
||||
path: '/imagePage',
|
||||
// query: {
|
||||
// id: state.videoInfo.id,
|
||||
// },
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.horizontaImgGroupBox {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
.photoBox {
|
||||
width: 111px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
transform: translateZ(0px);
|
||||
.cover {
|
||||
height: 150px;
|
||||
.subscriptInfo {
|
||||
transform: translateZ(0px);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
.label {
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
height: 18px;
|
||||
min-width: 34px;
|
||||
// background-image:linear-gradient(to right,#ffe247 ,#ffd4a3,#ffd4a3) ;
|
||||
// color: #c87426;
|
||||
border-radius: 0 0 6px 0;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
line-height: 18px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
}
|
||||
.goldCoinLabel {
|
||||
padding: 0 4px;
|
||||
box-sizing: border-box;
|
||||
// background: rgba(0, 0, 0, 0.6);
|
||||
//border: 0.5px solid #ffad00;
|
||||
background: linear-gradient(0deg, #ff0000, #ff0000);
|
||||
height: 18px;
|
||||
min-width: 27px;
|
||||
border-radius: 0 6px 0 6px;
|
||||
//border-radius: 2px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
margin-right: 3.3px;
|
||||
}
|
||||
span {
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.freeLabel {
|
||||
font-size: 10px;
|
||||
border-radius: 0 6px 0 6px;
|
||||
color: #ffffff;
|
||||
background-color: #1dcf00;
|
||||
}
|
||||
}
|
||||
.photoInfo {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
padding: 0 3px;
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, black 100%);
|
||||
transform: translateZ(0px);
|
||||
.watchCountInfo {
|
||||
color: white;
|
||||
> svg {
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
span {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
.photoQuantityInfo {
|
||||
padding: 2px 4px;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
border-radius: 4px;
|
||||
transform: translateZ(0px);
|
||||
color: white;
|
||||
> svg {
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
span {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.title {
|
||||
width: 100%;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,224 +0,0 @@
|
||||
<template>
|
||||
<div class="horizontalVideoBox" @click="openVideo">
|
||||
<div class="coverBox">
|
||||
<lazyImg class="cover" v-if="!state.videoInfo.type" :src="state.videoInfo?.verticalCover" />
|
||||
<lazyImg class="cover" v-else :src="state.videoInfo?.cover" />
|
||||
<div class="subscriptInfo" v-if="!state.videoInfo.type && state.videoInfo.tagNames.length > 0">
|
||||
<div class="goldCoinLabel flex-center-center" v-if="state.videoInfo?.coins != 0">
|
||||
<span>{{ state.videoInfo.tagNames[0] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="state.isOneLine ? 'videoTitle1' : 'videoTitle'">
|
||||
<div class="title">
|
||||
{{ state.videoInfo?.title ? state.videoInfo?.title : '无标题' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="bloggerBox" v-if="state.videoInfo.publisher">
|
||||
<div class="bloggerInfo">
|
||||
<lazyImg round class="bloggerAvatar" :src="state.videoInfo?.publisher?.portrait" />
|
||||
<span>{{ state.videoInfo.publisher?.name }}</span>
|
||||
</div>
|
||||
<div class="likeBox" v-if="state.videoInfo.publisher?.officialCert">
|
||||
<SvgIcon name="isVip" class="like" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { watchCount, videoTime } from '@/utils/index';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useVideoStore } from '@/stores/video';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
|
||||
const router = useRouter();
|
||||
const videoStore = useVideoStore();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
videoList: Types.Video.VInfosItem[];
|
||||
isMovie?: boolean;
|
||||
queryPath?: string;
|
||||
isOneLine?: boolean;
|
||||
}>(),
|
||||
{
|
||||
videoInfo: () => <Types.Video.VInfosItem>{},
|
||||
videoList: () => [],
|
||||
isMovie: () => false,
|
||||
queryPath: () => '',
|
||||
isOneLine: () => false,
|
||||
},
|
||||
);
|
||||
const emit = defineEmits(['changeVideo']);
|
||||
const state = {
|
||||
videoInfo: props.videoInfo,
|
||||
videoList: props.videoList,
|
||||
isMovie: props.isMovie,
|
||||
queryPath: props.queryPath,
|
||||
isOneLine: props.isOneLine,
|
||||
};
|
||||
const openVideo = () => {
|
||||
if (state.videoInfo.type) {
|
||||
jumpAdv(state.videoInfo);
|
||||
return;
|
||||
}
|
||||
router.push({
|
||||
path: '/portrayPage',
|
||||
query: {
|
||||
id: state.videoInfo.id,
|
||||
},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.horizontalVideoBox {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
.coverBox {
|
||||
height: 94px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
transform: translateZ(0px);
|
||||
position: relative;
|
||||
.videoInfo {
|
||||
height: 24px;
|
||||
width: 100%;
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.6));
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 0 10px 0 12px;
|
||||
transform: translateZ(0px);
|
||||
.playCount {
|
||||
.icon {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
.count {
|
||||
font-size: 10px;
|
||||
color: rgb(248, 248, 248);
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.playDuration {
|
||||
font-size: 11px;
|
||||
color: rgb(248, 248, 248);
|
||||
}
|
||||
}
|
||||
.subscriptInfo {
|
||||
transform: translateZ(0px);
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 0px;
|
||||
z-index: 1;
|
||||
.label {
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
height: 18px;
|
||||
min-width: 34px;
|
||||
// background-image:linear-gradient(to right,#ffe247 ,#ffd4a3,#ffd4a3) ;
|
||||
// color: #c87426;
|
||||
// border-radius: 2px 2px 0 0;
|
||||
font-size: 8px;
|
||||
text-align: center;
|
||||
line-height: 18px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
}
|
||||
.goldCoinLabel {
|
||||
padding: 0 4px;
|
||||
box-sizing: border-box;
|
||||
// background: rgba(0, 0, 0, 0.6);
|
||||
//border: 0.5px solid #ffad00;
|
||||
background: linear-gradient(0deg, #ff0000, #ff0000);
|
||||
height: 16px;
|
||||
min-width: 27px;
|
||||
// border-radius: 0 0 6px 0;
|
||||
border-radius: 2px 0 0 2px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
margin-right: 3.3px;
|
||||
}
|
||||
span {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: rgb(248, 248, 248);
|
||||
}
|
||||
}
|
||||
.freeLabel {
|
||||
color: #598300;
|
||||
background-color: #d8ffa6;
|
||||
}
|
||||
}
|
||||
}
|
||||
.videoTitle {
|
||||
padding: 2px 0px 8px;
|
||||
box-sizing: border-box;
|
||||
height: 26px;
|
||||
margin-top: 8px;
|
||||
.title {
|
||||
font-size: 12px;
|
||||
// color: rgba(248, 248, 248, 0.8);
|
||||
color: #ffffff;
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.videoTitle1 {
|
||||
padding: 2px 0px 8px;
|
||||
box-sizing: border-box;
|
||||
height: 30px;
|
||||
margin-top: 8px;
|
||||
.title {
|
||||
font-size: 14px;
|
||||
// color: rgba(248, 248, 248, 0.8);
|
||||
color: rgb(38, 38, 38);
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.bloggerBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: rgba(166, 166, 166, 1);
|
||||
.likeBox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: $themeColor;
|
||||
width: 16px;
|
||||
height: 10px;
|
||||
border-radius: 2px;
|
||||
margin-left: 8px;
|
||||
.like {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
.bloggerInfo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bloggerAvatar {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,294 +0,0 @@
|
||||
<template>
|
||||
<div class="horizontalVideoBox" @click="openVideo">
|
||||
<div class="coverBox">
|
||||
<lazyImg class="cover" v-if="!state.videoInfo.type" :src="state.videoInfo?.verticalCover" />
|
||||
<lazyImg class="cover" v-else :src="state.videoInfo?.cover" />
|
||||
<!-- <div class="videoInfo flex-center-between" v-if="!state.videoInfo.type">-->
|
||||
<!-- <div class="playCount flex-center-center">-->
|
||||
<!-- <SvgIcon class="icon" name="playIcon" />-->
|
||||
<!-- <div class="count">{{ watchCount(state.videoInfo?.playCount) }}</div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="playDuration">{{ videoTime(state.videoInfo?.playTime) }}</div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="subscriptInfo" v-if="!state.videoInfo.type">-->
|
||||
<!-- <!– <div class="label freeLabel" v-if="state.videoInfo?.coins == 0">免费</div> –>-->
|
||||
<!-- <!– <div class="label" v-if="state.videoInfo?.originCoins == 0 && !state.videoInfo?.freeArea">-->
|
||||
<!-- <img src="./../../assets/images/png/vip.png" />-->
|
||||
<!-- VIP-->
|
||||
<!-- </div> –>-->
|
||||
<!-- <div class="goldCoinLabel flex-center-center" v-if="state.videoInfo?.coins != 0">-->
|
||||
<!-- <img src="./../../assets/images/png/icon.png" />-->
|
||||
<!-- <span>{{ state.videoInfo?.originCoins }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<div class="subscriptInfo" v-if="!state.videoInfo.type && state.videoInfo.tagNames.length > 0">
|
||||
<!-- <div class="label freeLabel" v-if="state.videoInfo?.coins == 0">免费</div> -->
|
||||
<!-- <div class="label" v-if="state.videoInfo?.originCoins == 0 && !state.videoInfo?.freeArea">
|
||||
<img src="./../../assets/images/png/vip.png" />
|
||||
VIP
|
||||
</div> -->
|
||||
<!-- <div class="goldCoinLabel flex-center-center" v-if="state.videoInfo?.coins != 0">-->
|
||||
<!-- <img src="./../../assets/images/png/icon.png" />-->
|
||||
<!-- <span>{{ state.videoInfo?.originCoins }}</span>-->
|
||||
<!-- </div>-->
|
||||
<div class="goldCoinLabel flex-center-center" v-if="state.videoInfo?.coins != 0">
|
||||
<span>{{ state.videoInfo.tagNames[0] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="state.isOneLine ? 'videoTitle1' : 'videoTitle'">
|
||||
<div class="title">
|
||||
{{ state.videoInfo?.title ? state.videoInfo?.title : '无标题' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="bloggerBox" v-if="state.videoInfo.publisher">
|
||||
<div class="bloggerInfo">
|
||||
<lazyImg round class="bloggerAvatar" :src="state.videoInfo?.publisher?.portrait" />
|
||||
<span>{{ state.videoInfo.publisher?.name }}</span>
|
||||
</div>
|
||||
<div class="likeBox" v-if="state.videoInfo.publisher?.officialCert">
|
||||
<SvgIcon name="isVip" class="like" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { watchCount, videoTime } from '@/utils/index';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useVideoStore } from '@/stores/video';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
|
||||
const router = useRouter();
|
||||
const videoStore = useVideoStore();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
videoList: Types.Video.VInfosItem[];
|
||||
isMovie?: boolean;
|
||||
queryPath?: string;
|
||||
isOneLine?: boolean;
|
||||
}>(),
|
||||
{
|
||||
videoInfo: () => <Types.Video.VInfosItem>{},
|
||||
videoList: () => [],
|
||||
isMovie: () => false,
|
||||
queryPath: () => '',
|
||||
isOneLine: () => false,
|
||||
},
|
||||
);
|
||||
const emit = defineEmits(['changeVideo']);
|
||||
const state = {
|
||||
videoInfo: props.videoInfo,
|
||||
videoList: props.videoList,
|
||||
isMovie: props.isMovie,
|
||||
queryPath: props.queryPath,
|
||||
isOneLine: props.isOneLine,
|
||||
};
|
||||
const openVideo = () => {
|
||||
if (state.videoInfo.type) {
|
||||
jumpAdv(state.videoInfo);
|
||||
return;
|
||||
}
|
||||
router.push({
|
||||
path: '/novelDetailsPage',
|
||||
query: {
|
||||
id: state.videoInfo.id,
|
||||
// uid: state.videoInfo.publisher?.uid,
|
||||
// queryPath: state.queryPath,
|
||||
},
|
||||
});
|
||||
|
||||
// if (state.isMovie) {
|
||||
// emit('changeVideo', state.videoInfo);
|
||||
// } else {
|
||||
// router.push({
|
||||
// path: '/movieDetails',
|
||||
// query: {
|
||||
// vid: state.videoInfo.id,
|
||||
// uid: state.videoInfo.publisher?.uid,
|
||||
// queryPath: state.queryPath,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// if (state.videoInfo.newsType == 'COVER') {
|
||||
// // router.push({
|
||||
// // path: '/postDetails',
|
||||
// // query: {
|
||||
// // postId: state.videoInfo.id,
|
||||
// // },
|
||||
// // });
|
||||
// } else {
|
||||
// if (state.videoInfo.playTime > 300) {
|
||||
// if (state.isMovie) {
|
||||
// emit('changeVideo', state.videoInfo);
|
||||
// } else {
|
||||
// router.push({
|
||||
// path: '/movieDetails',
|
||||
// query: {
|
||||
// vid: state.videoInfo.id,
|
||||
// uid: state.videoInfo.publisher?.uid,
|
||||
// queryPath: state.queryPath,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// return;
|
||||
// } else {
|
||||
// videoStore.deleteVideoList();
|
||||
// videoStore.saveVideoList(state.videoList, state.videoInfo);
|
||||
// router.push('/shortVideoDetails');
|
||||
// }
|
||||
// }
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.horizontalVideoBox {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
.coverBox {
|
||||
height: 94px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
transform: translateZ(0px);
|
||||
position: relative;
|
||||
.videoInfo {
|
||||
height: 24px;
|
||||
width: 100%;
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.6));
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 0 10px 0 12px;
|
||||
transform: translateZ(0px);
|
||||
.playCount {
|
||||
.icon {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
.count {
|
||||
font-size: 10px;
|
||||
color: rgb(248, 248, 248);
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.playDuration {
|
||||
font-size: 11px;
|
||||
color: rgb(248, 248, 248);
|
||||
}
|
||||
}
|
||||
.subscriptInfo {
|
||||
transform: translateZ(0px);
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 0px;
|
||||
z-index: 1;
|
||||
.label {
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
height: 18px;
|
||||
min-width: 34px;
|
||||
// background-image:linear-gradient(to right,#ffe247 ,#ffd4a3,#ffd4a3) ;
|
||||
// color: #c87426;
|
||||
// border-radius: 2px 2px 0 0;
|
||||
font-size: 8px;
|
||||
text-align: center;
|
||||
line-height: 18px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
}
|
||||
.goldCoinLabel {
|
||||
padding: 0 4px;
|
||||
box-sizing: border-box;
|
||||
// background: rgba(0, 0, 0, 0.6);
|
||||
//border: 0.5px solid #ffad00;
|
||||
background: linear-gradient(0deg, #ff0000, #ff0000);
|
||||
height: 16px;
|
||||
min-width: 27px;
|
||||
// border-radius: 0 0 6px 0;
|
||||
border-radius: 2px 0 0 2px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
margin-right: 3.3px;
|
||||
}
|
||||
span {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: rgb(248, 248, 248);
|
||||
}
|
||||
}
|
||||
.freeLabel {
|
||||
color: #598300;
|
||||
background-color: #d8ffa6;
|
||||
}
|
||||
}
|
||||
}
|
||||
.videoTitle {
|
||||
padding: 2px 0px 8px;
|
||||
box-sizing: border-box;
|
||||
height: 26px;
|
||||
margin-top: 8px;
|
||||
.title {
|
||||
font-size: 12px;
|
||||
// color: rgba(248, 248, 248, 0.8);
|
||||
color: #ffffff;
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.videoTitle1 {
|
||||
padding: 2px 0px 8px;
|
||||
box-sizing: border-box;
|
||||
height: 30px;
|
||||
margin-top: 8px;
|
||||
.title {
|
||||
font-size: 14px;
|
||||
// color: rgba(248, 248, 248, 0.8);
|
||||
color: rgb(38, 38, 38);
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.bloggerBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: rgba(166, 166, 166, 1);
|
||||
.likeBox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: $themeColor;
|
||||
width: 16px;
|
||||
height: 10px;
|
||||
border-radius: 2px;
|
||||
margin-left: 8px;
|
||||
.like {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
.bloggerInfo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bloggerAvatar {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,249 +0,0 @@
|
||||
<template>
|
||||
<div class="horizontalVideoBox" @click="openVideo">
|
||||
<div class="coverBox">
|
||||
<lazyImg class="cover" :src="state.videoInfo?.cover" />
|
||||
<div class="videoInfo flex-center-between" v-if="!state.videoInfo.type">
|
||||
<div class="playCount flex-center-center">
|
||||
<SvgIcon class="icon" name="playIcon" />
|
||||
<div class="count">{{ watchCount(state.videoInfo?.playCount) }}</div>
|
||||
</div>
|
||||
<div class="playDuration">{{ videoTime(state.videoInfo?.playTime) }}</div>
|
||||
</div>
|
||||
<div class="subscriptInfo" v-if="!state.videoInfo.type">
|
||||
<div class="label freeLabel" v-if="state.videoInfo?.coins == 0">免费</div>
|
||||
<!-- <div class="label" v-if="state.videoInfo?.originCoins == 0 && !state.videoInfo?.freeArea">
|
||||
<img src="./../../assets/images/png/vip.png" />
|
||||
VIP
|
||||
</div> -->
|
||||
<div class="goldCoinLabel flex-center-center" v-if="state.videoInfo?.coins != 0">
|
||||
<img src="./../../assets/images/png/icon.png" />
|
||||
<span>{{ state.videoInfo?.originCoins }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="videoTitle">
|
||||
<div class="title">
|
||||
{{ state.videoInfo?.title ? state.videoInfo?.title : '无标题' }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bloggerBox"
|
||||
v-if="state.videoInfo.publisher && userInfo"
|
||||
@click.stop="
|
||||
$router.push({
|
||||
path: '/personal',
|
||||
query: {
|
||||
uid: state.videoInfo.publisher.uid,
|
||||
hasFollowed: state.videoInfo.publisher.hasFollowed.toString(),
|
||||
cover: state.videoInfo.publisher.portrait,
|
||||
},
|
||||
})
|
||||
"
|
||||
>
|
||||
<div class="bloggerInfo">
|
||||
<lazyImg round class="bloggerAvatar" :src="state.videoInfo?.publisher?.portrait" />
|
||||
<span>{{ state.videoInfo.publisher?.name }}</span>
|
||||
</div>
|
||||
<div class="likeBox" v-if="state.videoInfo.publisher?.officialCert">
|
||||
<SvgIcon name="isVip" class="like" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { watchCount, videoTime } from '@/utils/index';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useVideoStore } from '@/stores/video';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
|
||||
const router = useRouter();
|
||||
const videoStore = useVideoStore();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
videoList: Types.Video.VInfosItem[];
|
||||
isMovie?: boolean;
|
||||
userInfo?: boolean;
|
||||
}>(),
|
||||
{
|
||||
videoInfo: () => <Types.Video.VInfosItem>{},
|
||||
videoList: () => [],
|
||||
isMovie: () => false,
|
||||
userInfo: () => true,
|
||||
},
|
||||
);
|
||||
const emit = defineEmits(['changeVideo']);
|
||||
const state = {
|
||||
videoInfo: props.videoInfo,
|
||||
videoList: props.videoList,
|
||||
isMovie: props.isMovie,
|
||||
};
|
||||
const openVideo = () => {
|
||||
if (state.videoInfo.type) {
|
||||
jumpAdv(state.videoInfo);
|
||||
return;
|
||||
}
|
||||
if (state.videoInfo.newsType == 'COVER') {
|
||||
// router.push({
|
||||
// path: '/postDetails',
|
||||
// query: {
|
||||
// postId: state.videoInfo.id,
|
||||
// },
|
||||
// });
|
||||
} else {
|
||||
if (state.videoInfo.playTime > 300) {
|
||||
if (state.isMovie) {
|
||||
emit('changeVideo', state.videoInfo);
|
||||
} else {
|
||||
router.push({
|
||||
path: '/movieDetails',
|
||||
query: {
|
||||
vid: state.videoInfo.id,
|
||||
uid: state.videoInfo.publisher?.uid,
|
||||
},
|
||||
});
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
videoStore.deleteVideoList();
|
||||
videoStore.saveVideoList(state.videoList, state.videoInfo);
|
||||
router.push('/shortVideoDetails');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.horizontalVideoBox {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
.coverBox {
|
||||
height: 94px;
|
||||
border-radius: 10px 10px 0 0;
|
||||
overflow: hidden;
|
||||
transform: translateZ(0px);
|
||||
position: relative;
|
||||
background: linear-gradient(to right, rgba(253, 191, 80, 0.7), rgba(255, 224, 167, 0.7));
|
||||
.videoInfo {
|
||||
height: 24px;
|
||||
width: 100%;
|
||||
background: linear-gradient(to bottom, rgba(184, 184, 209, 0), rgba(159, 159, 178, 0.52));
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 0 4px 0 4px;
|
||||
transform: translateZ(0px);
|
||||
.playCount {
|
||||
.icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
color: #fff;
|
||||
}
|
||||
.count {
|
||||
font-size: 11px;
|
||||
color: white;
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
.playDuration {
|
||||
font-size: 11px;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
.subscriptInfo {
|
||||
transform: translateZ(0px);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
.label {
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
height: 18px;
|
||||
min-width: 34px;
|
||||
border-radius: 0 0 6px 0;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
line-height: 18px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
}
|
||||
.goldCoinLabel {
|
||||
padding: 0 4px;
|
||||
box-sizing: border-box;
|
||||
// background: rgba(0, 0, 0, 0.6);
|
||||
//border: 0.5px solid #ffad00;
|
||||
background: linear-gradient(0deg, #ff0000, #ff0000);
|
||||
height: 18px;
|
||||
min-width: 27px;
|
||||
border-radius: 0 8px 0 6px;
|
||||
//border-radius: 2px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
margin-right: 3.3px;
|
||||
}
|
||||
span {
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.freeLabel {
|
||||
font-size: 10px;
|
||||
border-radius: 0 8px 0 6px;
|
||||
color: #ffffff;
|
||||
background-color: #1dcf00;
|
||||
}
|
||||
}
|
||||
}
|
||||
.videoTitle {
|
||||
//background-color: rgb(255, 255, 251);
|
||||
//border-radius: 0 0 10px 10px;
|
||||
padding: 4px 0;
|
||||
box-sizing: border-box;
|
||||
.title {
|
||||
font-size: 12px;
|
||||
color: #ffffff;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
.bloggerBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: rgba(166, 166, 166, 1);
|
||||
.likeBox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: $themeColor;
|
||||
width: 16px;
|
||||
height: 10px;
|
||||
border-radius: 2px;
|
||||
margin-left: 8px;
|
||||
.like {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
.bloggerInfo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bloggerAvatar {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,307 +0,0 @@
|
||||
<template>
|
||||
<div class="horizontalVideoBox" @click="openVideo">
|
||||
<div class="coverBox">
|
||||
<lazyImg class="cover" :src="state.videoInfo?.cover" />
|
||||
<div class="videoInfo flex-center-between" v-if="!state.videoInfo.type">
|
||||
<div class="playCount flex-center-center">
|
||||
<SvgIcon class="icon" name="playIcon" />
|
||||
<div class="count">{{ watchCount(state.videoInfo?.playCount) }}</div>
|
||||
</div>
|
||||
<div class="playDuration">{{ videoTime(state.videoInfo?.playTime) }}</div>
|
||||
</div>
|
||||
<div class="subscriptInfo" v-if="!state.videoInfo.type">
|
||||
<div class="label freeLabel" v-if="state.videoInfo?.coins == 0">免费</div>
|
||||
<!-- <div class="label" v-if="state.videoInfo?.originCoins == 0 && !state.videoInfo?.freeArea">
|
||||
<img src="./../../assets/images/png/vip.png" />
|
||||
VIP
|
||||
</div> -->
|
||||
<div class="goldCoinLabel flex-center-center" v-if="state.videoInfo?.coins != 0">
|
||||
<img src="./../../assets/images/png/icon.png" />
|
||||
<span>{{ state.videoInfo?.originCoins }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="subscriptInfoAdv" v-else>广告</div>-->
|
||||
</div>
|
||||
<div :class="state.isOneLine ? 'videoTitle1' : 'videoTitle'">
|
||||
<div class="title">
|
||||
{{ state.videoInfo?.title ? state.videoInfo?.title : '无标题' }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bloggerBox"
|
||||
v-if="state.videoInfo.publisher && userInfo"
|
||||
@click.stop="
|
||||
$router.push({
|
||||
path: '/personal',
|
||||
query: {
|
||||
uid: state.videoInfo.publisher.uid,
|
||||
// hasFollowed: state.videoInfo.publisher.hasFollowed.toString(),
|
||||
// cover: state.videoInfo.publisher.portrait,
|
||||
},
|
||||
})
|
||||
"
|
||||
>
|
||||
<div class="bloggerInfo">
|
||||
<lazyImg round class="bloggerAvatar" :src="state.videoInfo?.publisher?.portrait" />
|
||||
<span>{{ state.videoInfo.publisher?.name }}</span>
|
||||
</div>
|
||||
<div class="likeBox" v-if="state.videoInfo.publisher?.officialCert">
|
||||
<SvgIcon name="isVip" class="like" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { watchCount, videoTime } from '@/utils/index';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useVideoStore } from '@/stores/video';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
|
||||
const router = useRouter();
|
||||
const videoStore = useVideoStore();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
videoList: Types.Video.VInfosItem[];
|
||||
isMovie?: boolean;
|
||||
queryPath?: string;
|
||||
isOneLine?: boolean;
|
||||
userInfo?: boolean;
|
||||
}>(),
|
||||
{
|
||||
videoInfo: () => <Types.Video.VInfosItem>{},
|
||||
videoList: () => [],
|
||||
isMovie: () => false,
|
||||
queryPath: () => '',
|
||||
isOneLine: () => false,
|
||||
userInfo: () => true,
|
||||
},
|
||||
);
|
||||
const emit = defineEmits(['changeVideo']);
|
||||
const state = {
|
||||
videoInfo: props.videoInfo,
|
||||
videoList: props.videoList,
|
||||
isMovie: props.isMovie,
|
||||
queryPath: props.queryPath,
|
||||
isOneLine: props.isOneLine,
|
||||
};
|
||||
const openVideo = () => {
|
||||
if (state.videoInfo.type) {
|
||||
jumpAdv(state.videoInfo);
|
||||
return;
|
||||
}
|
||||
if (state.isMovie) {
|
||||
emit('changeVideo', state.videoInfo);
|
||||
} else {
|
||||
router.push({
|
||||
path: '/movieDetails',
|
||||
query: {
|
||||
vid: state.videoInfo.id,
|
||||
uid: state.videoInfo.publisher?.uid,
|
||||
queryPath: state.queryPath,
|
||||
},
|
||||
});
|
||||
}
|
||||
// if (state.videoInfo.newsType == 'COVER') {
|
||||
// // router.push({
|
||||
// // path: '/postDetails',
|
||||
// // query: {
|
||||
// // postId: state.videoInfo.id,
|
||||
// // },
|
||||
// // });
|
||||
// } else {
|
||||
// if (state.videoInfo.playTime > 300) {
|
||||
// if (state.isMovie) {
|
||||
// emit('changeVideo', state.videoInfo);
|
||||
// } else {
|
||||
// router.push({
|
||||
// path: '/movieDetails',
|
||||
// query: {
|
||||
// vid: state.videoInfo.id,
|
||||
// uid: state.videoInfo.publisher?.uid,
|
||||
// queryPath: state.queryPath,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// return;
|
||||
// } else {
|
||||
// videoStore.deleteVideoList();
|
||||
// videoStore.saveVideoList(state.videoList, state.videoInfo);
|
||||
// router.push('/shortVideoDetails');
|
||||
// }
|
||||
// }
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.horizontalVideoBox {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
.coverBox {
|
||||
height: 94px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
transform: translateZ(0px);
|
||||
position: relative;
|
||||
.videoInfo {
|
||||
height: 24px;
|
||||
width: 100%;
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.6));
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 0 4px 0 4px;
|
||||
transform: translateZ(0px);
|
||||
.playCount {
|
||||
.icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
color: #ffffff;
|
||||
}
|
||||
.count {
|
||||
font-size: 10px;
|
||||
color: rgb(248, 248, 248);
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
.playDuration {
|
||||
font-size: 11px;
|
||||
color: rgb(248, 248, 248);
|
||||
}
|
||||
}
|
||||
.subscriptInfo {
|
||||
transform: translateZ(0px);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
font-family: PingFang SC, serif;
|
||||
.label {
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
height: 18px;
|
||||
min-width: 34px;
|
||||
// background-image:linear-gradient(to right,#ffe247 ,#ffd4a3,#ffd4a3) ;
|
||||
// color: #c87426;
|
||||
border-radius: 0 0 6px 0;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
line-height: 18px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
}
|
||||
.goldCoinLabel {
|
||||
padding: 0 4px;
|
||||
box-sizing: border-box;
|
||||
// background: rgba(0, 0, 0, 0.6);
|
||||
//border: 0.5px solid #ffad00;
|
||||
background: linear-gradient(0deg, #ff0000, #ff0000);
|
||||
height: 18px;
|
||||
min-width: 27px;
|
||||
border-radius: 0 6px 0 6px;
|
||||
//border-radius: 2px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
margin-right: 3.3px;
|
||||
}
|
||||
span {
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.freeLabel {
|
||||
font-size: 10px;
|
||||
border-radius: 0 6px 0 6px;
|
||||
color: #ffffff;
|
||||
font-weight: 400;
|
||||
background-color: #1dcf00;
|
||||
}
|
||||
}
|
||||
.subscriptInfoAdv {
|
||||
transform: translateZ(0px);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
height: 16px;
|
||||
width: 34px;
|
||||
border-radius: 0 0 4px 0;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: rgb(0, 0, 0);
|
||||
background-color: $themeColor;
|
||||
text-align: center;
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
.videoTitle {
|
||||
padding: 2px 0 8px;
|
||||
box-sizing: border-box;
|
||||
height: 22px;
|
||||
margin-top: 2px;
|
||||
.title {
|
||||
font-size: 12px;
|
||||
// color: rgba(248, 248, 248, 0.8);
|
||||
color: #ffffff;
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.videoTitle1 {
|
||||
padding: 2px 0px 8px;
|
||||
box-sizing: border-box;
|
||||
height: 22px;
|
||||
margin-top: 2px;
|
||||
.title {
|
||||
font-size: 14px;
|
||||
// color: rgba(248, 248, 248, 0.8);
|
||||
color: rgb(38, 38, 38);
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.bloggerBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: rgba(166, 166, 166, 1);
|
||||
.likeBox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: $themeColor;
|
||||
width: 16px;
|
||||
height: 10px;
|
||||
border-radius: 2px;
|
||||
margin-left: 8px;
|
||||
.like {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
.bloggerInfo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bloggerAvatar {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,265 +0,0 @@
|
||||
<template>
|
||||
<div class="horizontalVideoBox">
|
||||
<HorizontalVideo
|
||||
:videoInfo="videoInfo"
|
||||
@goldBuyShow="goldBuyShow"
|
||||
@showPreviewTime="showPreviewTime"
|
||||
ref="verticalVideoRef"
|
||||
class="videoBox"
|
||||
/>
|
||||
<!-- <HorizontalVideo
|
||||
:videoInfo="videoInfo"
|
||||
@getFreeCount="getFreeCount"
|
||||
@goldBuyShow="goldBuyShow"
|
||||
@showPreviewTime="showPreviewTime"
|
||||
ref="verticalVideoRef"
|
||||
class="videoBox"
|
||||
/> -->
|
||||
<!-- <div class="tipBox" v-if="!userInfo.isVip && userFreeCount.watchCount > 0 && videoInfo.originCoins == 0">
|
||||
免费观影数: {{ userFreeCount.watchCount }}次
|
||||
</div>
|
||||
<div class="tipBox" v-else-if="freeVideo30 && videoInfo.originCoins < 30 && videoInfo.originCoins > 0">
|
||||
已享免费特权
|
||||
</div> -->
|
||||
<div class="tipBox" v-if="videoInfo.vidStatus.hasPaid">已购买完整版</div>
|
||||
<!-- <div class="tipBox" v-else-if="!isVip && !userFreeCount.isCan && videoInfo.originCoins == 0">
|
||||
预览
|
||||
<span>{{ isPreview ? previewTime : videoInfo.freeTime }}S</span>
|
||||
,充值会员观看完整版
|
||||
</div> -->
|
||||
<div class="tipBox" v-else-if="videoInfo.originCoins > 0 && !videoInfo.vidStatus.hasPaid">
|
||||
预览
|
||||
<span>{{ isPreview ? previewTime : videoInfo.freeTime }}S</span>
|
||||
,购买解锁观看完整版
|
||||
</div>
|
||||
|
||||
<!-- 金币不足做任务提示 -->
|
||||
<div class="goldBox" v-if="isGoldCoinPurchase">
|
||||
<!-- <p>金币不足快去做任务吧~</p> -->
|
||||
<p>观看完整版需要</p>
|
||||
<!-- <h6>观看完整版需开通会员</h6> -->
|
||||
<h5>
|
||||
<span>{{ isVip ? videoInfo.coins : videoInfo.originCoins }}</span>
|
||||
<img class="transactionGoldIcon" src="@/assets/images/png/icon.png" />
|
||||
</h5>
|
||||
<div class="unlock_now">
|
||||
<div class="button_normal" @click="isShowBuyDialog = true">金币解锁</div>
|
||||
<div class="button" @click="$router.push({ path: '/recharge', query: { name: 'wallet' } })">购买金币</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 金币弹窗 -->
|
||||
<GoldPopupNew
|
||||
:is-open="isShowBuyDialog"
|
||||
:video-info="videoInfo"
|
||||
@close="isShowBuyDialog = false"
|
||||
@buy-success="buySuccess"
|
||||
/>
|
||||
<!-- 会员弹窗 -->
|
||||
<!-- <MemberPopup :videoInfo="videoInfo" :is-open="isJoinMerbershipShow" @close="isJoinMerbershipShow = false" /> -->
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { Ref, ref } from 'vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { showToast } from 'vant';
|
||||
import VideoApi from '@/service/video';
|
||||
import { ProductType } from '@/enums/app';
|
||||
|
||||
const verticalVideoRef = ref();
|
||||
// let isJoinMerbershipShow = ref(false); //会员购买
|
||||
let isGoldCoinPurchase = ref(false); //金币购买
|
||||
let isShowBuyDialog = ref(false);
|
||||
let isPreview = ref(false); // 是否预览视频
|
||||
let previewTime = ref(0); // 预览视频时间
|
||||
const props = defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
}>();
|
||||
const { isVip, freeVideo30, userInfo, walletInfo } = useUserStore();
|
||||
let userFreeCount: Ref<Types.Video.UserFreeCount> = ref({
|
||||
isCan: false,
|
||||
watchCount: 0,
|
||||
});
|
||||
const { openLoading, closeLoading } = useLoading();
|
||||
/**
|
||||
* @description 判断是否预览视频
|
||||
*/
|
||||
const checkPreview = () => {
|
||||
if (
|
||||
!props.videoInfo.vidStatus.hasPaid &&
|
||||
!(freeVideo30 && props.videoInfo.originCoins < 30 && props.videoInfo.originCoins != 0) &&
|
||||
!(props.videoInfo.originCoins === 0 && isVip) &&
|
||||
!(userInfo.uid === props.videoInfo.publisher.uid) &&
|
||||
// !(userFreeCount.value.isCan === true && props.videoInfo.originCoins === 0) &&
|
||||
// props.videoInfo.previewURL
|
||||
// )
|
||||
props.videoInfo.previewURL
|
||||
) {
|
||||
// console.log('1-------------------');
|
||||
isPreview.value = true;
|
||||
} else {
|
||||
// console.log('2-------------------');
|
||||
isPreview.value = false;
|
||||
}
|
||||
};
|
||||
const unlockNow = (money: any) => {
|
||||
try {
|
||||
openLoading();
|
||||
let productID = props.videoInfo.id;
|
||||
if (!productID) {
|
||||
showToast('购买出错~');
|
||||
return;
|
||||
}
|
||||
VideoApi.videoBuying({ productType: ProductType.VIDEO, productID: productID, goldVideoCouponNum: money || 0 })
|
||||
.then(() => {
|
||||
showToast('购买成功');
|
||||
useUserStore().updateWallet();
|
||||
verticalVideoRef.value.success();
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
});
|
||||
} finally {
|
||||
closeLoading();
|
||||
}
|
||||
};
|
||||
// 获取观影券--看是有有可以使用的
|
||||
const selectCoupon = () => {
|
||||
if (userInfo?.goldVideoCoupon && props.videoInfo.coins != 0) {
|
||||
//如果有观影券--判断是否符合面值 && 是金币视频
|
||||
let money = userInfo.isVip ? props.videoInfo.coins : props.videoInfo.originCoins;
|
||||
let goldVideoCoupon = userInfo.goldVideoCoupon;
|
||||
let buy = '';
|
||||
goldVideoCoupon.forEach((item: any) => {
|
||||
if (item.gold >= money) {
|
||||
buy = item.gold;
|
||||
}
|
||||
});
|
||||
if (buy) {
|
||||
//如果有符合面值的观影券--则购买
|
||||
unlockNow(buy);
|
||||
} else {
|
||||
checkPreview();
|
||||
}
|
||||
} else {
|
||||
checkPreview();
|
||||
}
|
||||
};
|
||||
// selectCoupon();
|
||||
//免费观看视频次数
|
||||
const getFreeCount = (userCount: Types.Video.UserFreeCount) => {
|
||||
userFreeCount.value = userCount;
|
||||
};
|
||||
const showPreviewTime = (time: number) => {
|
||||
previewTime.value = parseInt(time.toString());
|
||||
};
|
||||
//会员购买弹窗
|
||||
// const vipBuyShow = () => {
|
||||
// isJoinMerbershipShow.value = true;
|
||||
// };
|
||||
//金币购买弹窗
|
||||
const goldBuyShow = () => {
|
||||
// 如果用户余额小于观看视频的金币数 --- 弹出做任务
|
||||
// if (walletInfo.amount < props.videoInfo.originCoins) {
|
||||
// // isGoldCoinPurchase.value = true;
|
||||
// } else {
|
||||
// // 弹出购买弹框
|
||||
// isShowBuyDialog.value = true;
|
||||
// }
|
||||
isShowBuyDialog.value = true;
|
||||
};
|
||||
/**
|
||||
* @description 视频购买成功
|
||||
*/
|
||||
const buySuccess = () => {
|
||||
isShowBuyDialog.value = false;
|
||||
verticalVideoRef.value.success();
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.horizontalVideoBox {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
.videoBox {
|
||||
height: 212px;
|
||||
}
|
||||
.tipBox {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
top: 11px;
|
||||
right: 14px;
|
||||
background-color: rgba(6, 15, 33, 0.3);
|
||||
font-size: 11px;
|
||||
color: rgb(242, 242, 242);
|
||||
padding: 6px 20px;
|
||||
border-radius: 20px;
|
||||
span {
|
||||
color: rgb(255, 13, 44);
|
||||
}
|
||||
}
|
||||
.goldBox {
|
||||
width: 100%;
|
||||
height: 212px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
background: rgb(0, 0, 0, 0.5);
|
||||
padding: 40px 0 0 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
line-height: 25px;
|
||||
h6 {
|
||||
font-size: 14px;
|
||||
}
|
||||
h5 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 5px 0 10px 0;
|
||||
span {
|
||||
font-size: 16px;
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
.unlock_now {
|
||||
display: flex;
|
||||
div {
|
||||
width: 84px;
|
||||
height: 32px;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
line-height: 32px;
|
||||
}
|
||||
.button {
|
||||
background: #ffd9a4;
|
||||
color: #dd6a00;
|
||||
}
|
||||
.button_normal {
|
||||
border: solid 2px #fff;
|
||||
margin: 0 20px 0 0;
|
||||
}
|
||||
// width: 107px;
|
||||
// height: 38px;
|
||||
// background: rgb(255, 160, 1);
|
||||
// border-radius: 20px;
|
||||
// font-size: 16px;
|
||||
// color: #ffffff;
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,296 +0,0 @@
|
||||
<template>
|
||||
<div class="horizontalVideoBox" @click="openVideo">
|
||||
<div class="coverBox">
|
||||
<lazyImg class="cover" v-if="!state.videoInfo.type" :src="state.videoInfo?.verticalCover" />
|
||||
<lazyImg class="cover" v-else :src="state.videoInfo?.cover" />
|
||||
<!-- <div class="videoInfo flex-center-between" v-if="!state.videoInfo.type">-->
|
||||
<!-- <div class="playCount flex-center-center">-->
|
||||
<!-- <SvgIcon class="icon" name="playIcon" />-->
|
||||
<!-- <div class="count">{{ watchCount(state.videoInfo?.playCount) }}</div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="playDuration">{{ videoTime(state.videoInfo?.playTime) }}</div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="subscriptInfo" v-if="!state.videoInfo.type">-->
|
||||
<!-- <!– <div class="label freeLabel" v-if="state.videoInfo?.coins == 0">免费</div> –>-->
|
||||
<!-- <!– <div class="label" v-if="state.videoInfo?.originCoins == 0 && !state.videoInfo?.freeArea">-->
|
||||
<!-- <img src="./../../assets/images/png/vip.png" />-->
|
||||
<!-- VIP-->
|
||||
<!-- </div> –>-->
|
||||
<!-- <div class="goldCoinLabel flex-center-center" v-if="state.videoInfo?.coins != 0">-->
|
||||
<!-- <img src="./../../assets/images/png/icon.png" />-->
|
||||
<!-- <span>{{ state.videoInfo?.originCoins }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<div class="subscriptInfo" v-if="!state.videoInfo.type && state.videoInfo.tagNames.length > 0">
|
||||
<!-- <div class="label freeLabel" v-if="state.videoInfo?.coins == 0">免费</div> -->
|
||||
<!-- <div class="label" v-if="state.videoInfo?.originCoins == 0 && !state.videoInfo?.freeArea">
|
||||
<img src="./../../assets/images/png/vip.png" />
|
||||
VIP
|
||||
</div> -->
|
||||
<!-- <div class="goldCoinLabel flex-center-center" v-if="state.videoInfo?.coins != 0">-->
|
||||
<!-- <img src="./../../assets/images/png/icon.png" />-->
|
||||
<!-- <span>{{ state.videoInfo?.originCoins }}</span>-->
|
||||
<!-- </div>-->
|
||||
<div class="goldCoinLabel flex-center-center" v-if="state.videoInfo?.coins != 0">
|
||||
<span>{{ state.videoInfo.tagNames[0] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="state.isOneLine ? 'videoTitle1' : 'videoTitle'">
|
||||
<div class="title">
|
||||
{{ state.videoInfo?.title ? state.videoInfo?.title : '无标题' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="bloggerBox" v-if="state.videoInfo.publisher">
|
||||
<div class="bloggerInfo">
|
||||
<lazyImg round class="bloggerAvatar" :src="state.videoInfo?.publisher?.portrait" />
|
||||
<span>{{ state.videoInfo.publisher?.name }}</span>
|
||||
</div>
|
||||
<div class="likeBox" v-if="state.videoInfo.publisher?.officialCert">
|
||||
<SvgIcon name="isVip" class="like" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { watchCount, videoTime, addVideoHistory } from '@/utils/index';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useVideoStore } from '@/stores/video';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
import { HistoryVideoType } from '@/enums/app';
|
||||
|
||||
const router = useRouter();
|
||||
const videoStore = useVideoStore();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
videoList: Types.Video.VInfosItem[];
|
||||
isMovie?: boolean;
|
||||
queryPath?: string;
|
||||
isOneLine?: boolean;
|
||||
}>(),
|
||||
{
|
||||
videoInfo: () => <Types.Video.VInfosItem>{},
|
||||
videoList: () => [],
|
||||
isMovie: () => false,
|
||||
queryPath: () => '',
|
||||
isOneLine: () => false,
|
||||
},
|
||||
);
|
||||
const emit = defineEmits(['changeVideo']);
|
||||
const state = {
|
||||
videoInfo: props.videoInfo,
|
||||
videoList: props.videoList,
|
||||
isMovie: props.isMovie,
|
||||
queryPath: props.queryPath,
|
||||
isOneLine: props.isOneLine,
|
||||
};
|
||||
const openVideo = () => {
|
||||
if (state.videoInfo.type) {
|
||||
jumpAdv(state.videoInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
router.push({
|
||||
path: '/novelDetailsPage',
|
||||
query: {
|
||||
id: state.videoInfo.id,
|
||||
// uid: state.videoInfo.publisher?.uid,
|
||||
// queryPath: state.queryPath,
|
||||
},
|
||||
});
|
||||
// if (state.isMovie) {
|
||||
// emit('changeVideo', state.videoInfo);
|
||||
// } else {
|
||||
// router.push({
|
||||
// path: '/movieDetails',
|
||||
// query: {
|
||||
// vid: state.videoInfo.id,
|
||||
// uid: state.videoInfo.publisher?.uid,
|
||||
// queryPath: state.queryPath,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// if (state.videoInfo.newsType == 'COVER') {
|
||||
// // router.push({
|
||||
// // path: '/postDetails',
|
||||
// // query: {
|
||||
// // postId: state.videoInfo.id,
|
||||
// // },
|
||||
// // });
|
||||
// } else {
|
||||
// if (state.videoInfo.playTime > 300) {
|
||||
// if (state.isMovie) {
|
||||
// emit('changeVideo', state.videoInfo);
|
||||
// } else {
|
||||
// router.push({
|
||||
// path: '/movieDetails',
|
||||
// query: {
|
||||
// vid: state.videoInfo.id,
|
||||
// uid: state.videoInfo.publisher?.uid,
|
||||
// queryPath: state.queryPath,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// return;
|
||||
// } else {
|
||||
// videoStore.deleteVideoList();
|
||||
// videoStore.saveVideoList(state.videoList, state.videoInfo);
|
||||
// router.push('/shortVideoDetails');
|
||||
// }
|
||||
// }
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.horizontalVideoBox {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
.coverBox {
|
||||
height: 94px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
transform: translateZ(0px);
|
||||
position: relative;
|
||||
.videoInfo {
|
||||
height: 24px;
|
||||
width: 100%;
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.6));
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 0 10px 0 12px;
|
||||
transform: translateZ(0px);
|
||||
.playCount {
|
||||
.icon {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
.count {
|
||||
font-size: 10px;
|
||||
color: rgb(248, 248, 248);
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.playDuration {
|
||||
font-size: 11px;
|
||||
color: rgb(248, 248, 248);
|
||||
}
|
||||
}
|
||||
.subscriptInfo {
|
||||
transform: translateZ(0px);
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 0px;
|
||||
z-index: 1;
|
||||
.label {
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
height: 18px;
|
||||
min-width: 34px;
|
||||
// background-image:linear-gradient(to right,#ffe247 ,#ffd4a3,#ffd4a3) ;
|
||||
// color: #c87426;
|
||||
// border-radius: 2px 2px 0 0;
|
||||
font-size: 8px;
|
||||
text-align: center;
|
||||
line-height: 18px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
}
|
||||
.goldCoinLabel {
|
||||
padding: 0 4px;
|
||||
box-sizing: border-box;
|
||||
// background: rgba(0, 0, 0, 0.6);
|
||||
//border: 0.5px solid #ffad00;
|
||||
background: linear-gradient(0deg, #ff0000, #ff0000);
|
||||
height: 16px;
|
||||
min-width: 27px;
|
||||
// border-radius: 0 0 6px 0;
|
||||
border-radius: 2px 0 0 2px;
|
||||
> img {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
margin-right: 3.3px;
|
||||
}
|
||||
span {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: rgb(248, 248, 248);
|
||||
}
|
||||
}
|
||||
.freeLabel {
|
||||
color: #598300;
|
||||
background-color: #d8ffa6;
|
||||
}
|
||||
}
|
||||
}
|
||||
.videoTitle {
|
||||
padding: 2px 0px 8px;
|
||||
box-sizing: border-box;
|
||||
height: 26px;
|
||||
margin-top: 8px;
|
||||
.title {
|
||||
font-size: 12px;
|
||||
// color: rgba(248, 248, 248, 0.8);
|
||||
color: #ffffff;
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.videoTitle1 {
|
||||
padding: 2px 0px 8px;
|
||||
box-sizing: border-box;
|
||||
height: 30px;
|
||||
margin-top: 8px;
|
||||
.title {
|
||||
font-size: 14px;
|
||||
// color: rgba(248, 248, 248, 0.8);
|
||||
color: rgb(38, 38, 38);
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.bloggerBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: rgba(166, 166, 166, 1);
|
||||
.likeBox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: $themeColor;
|
||||
width: 16px;
|
||||
height: 10px;
|
||||
border-radius: 2px;
|
||||
margin-left: 8px;
|
||||
.like {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
.bloggerInfo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bloggerAvatar {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,209 +0,0 @@
|
||||
<template>
|
||||
<div class="InformationPopup">
|
||||
<van-popup v-model:show="state.isRewardShow" :style="{ backgroundColor: 'rgba(0, 0, 0, 0)' }">
|
||||
<div class="popupBox">
|
||||
<div class="listbox">
|
||||
<p class="flex-center-center">我的地址</p>
|
||||
</div>
|
||||
<div class="contentBox flex-center-center">
|
||||
<div class="provinces flex-center-between">
|
||||
<div class="text">省份:</div>
|
||||
<input
|
||||
type="text"
|
||||
:value="state.selectedProvince"
|
||||
@click.stop="state.showDropdown = !state.showDropdown"
|
||||
readonly
|
||||
/>
|
||||
<SvgIcon
|
||||
name="informationTel"
|
||||
@click="state.showDropdown = !state.showDropdown"
|
||||
class="informationTel"
|
||||
></SvgIcon>
|
||||
<div v-if="state.showDropdown" class="provincesPop overflow-y-auto">
|
||||
<div v-for="province in provinces" :key="province" @click="selectProvince(province)">
|
||||
{{ province }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="provinces flex-center-between">
|
||||
<div class="text">城市:</div>
|
||||
<input
|
||||
type="text"
|
||||
:value="state.selectedCity"
|
||||
:disabled="state.isDisabled"
|
||||
@click="state.showCity = !state.showCity"
|
||||
readonly
|
||||
/>
|
||||
<SvgIcon
|
||||
v-if="!state.isDisabled"
|
||||
name="informationTel"
|
||||
@click="state.showCity = !state.showCity"
|
||||
class="informationTel"
|
||||
></SvgIcon>
|
||||
<div v-if="state.showCity" class="provincesPop overflow-y-auto">
|
||||
<div v-for="city in citys" :key="city" @click="selectProvince(city)">
|
||||
{{ city }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="provinces flex-center-between">
|
||||
<div class="text">暗号:</div>
|
||||
<input type="text" :value="state.signal" />
|
||||
</div>
|
||||
<div class="provinces flex-center-between">
|
||||
<div class="text">联系方式:</div>
|
||||
<input type="tel" :value="state.information" />
|
||||
</div>
|
||||
<div class="tips">温馨提示:请填写准确信息,方便联系安排</div>
|
||||
<!-- <div class="btn" @click="state.isRewardShow = false">取消</div> -->
|
||||
<div class="BindBtn" @click="confirm">确认</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, watchEffect } from 'vue';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
|
||||
const configStore = useConfigStore();
|
||||
const state = reactive({
|
||||
isRewardShow: false,
|
||||
showDropdown: false,
|
||||
selectedProvince: '',
|
||||
selectedCity: '',
|
||||
signal: '',
|
||||
information: '',
|
||||
isDisabled: true,
|
||||
showCity: false,
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
state.isDisabled = state.selectedProvince.trim() === '';
|
||||
});
|
||||
|
||||
const provinces = ['广东省', '湖南省', '湖北省', '河南省', '山东省'];
|
||||
const citys = ['广东视', '广东视'];
|
||||
const selectProvince = (province: string) => {
|
||||
// console.log(province);
|
||||
state.selectedProvince = province;
|
||||
state.showDropdown = false;
|
||||
};
|
||||
|
||||
const openPop = () => {
|
||||
state.isRewardShow = true;
|
||||
};
|
||||
defineExpose({
|
||||
openPop,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.InformationPopup {
|
||||
.popupBox {
|
||||
width: 313px;
|
||||
height: 405px;
|
||||
background-image: url('@/assets/images/png/informationPopBg.png');
|
||||
background-size: 100% 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
.listbox {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
p {
|
||||
padding-top: 20px;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.contentBox {
|
||||
margin: 0 auto;
|
||||
width: 280px;
|
||||
height: 318px;
|
||||
border: 1px solid rgba(255, 173, 0, 1);
|
||||
border-radius: 12px;
|
||||
flex-direction: column;
|
||||
background-color: #ffffff;
|
||||
padding: 12px;
|
||||
.provinces {
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
margin: 12px;
|
||||
.text {
|
||||
white-space: nowrap;
|
||||
font-family: PingFang SC;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
color: rgba(119, 119, 119, 1);
|
||||
}
|
||||
input {
|
||||
width: 214px;
|
||||
height: 32px;
|
||||
background: rgba(255, 214, 128, 0.35);
|
||||
border: none;
|
||||
color: #000;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
padding-left: 12px;
|
||||
}
|
||||
.informationTel {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 10px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.provincesPop {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 35px;
|
||||
width: 214px;
|
||||
height: 200px;
|
||||
background-color: #ffffff;
|
||||
color: #000;
|
||||
z-index: 9999;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
> div {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
padding: 4px;
|
||||
border-bottom: 1px solid rgb(119, 119, 119);
|
||||
}
|
||||
}
|
||||
}
|
||||
.tips {
|
||||
color: rgba(255, 173, 0, 1);
|
||||
font-family: PingFang SC;
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
}
|
||||
.BindBtn {
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
color: #ffffff;
|
||||
width: 248px;
|
||||
height: 40px;
|
||||
border-radius: 100px;
|
||||
background-color: $themeColor;
|
||||
}
|
||||
}
|
||||
:deep(.van-popup) {
|
||||
// border-radius: 12px;
|
||||
}
|
||||
:deep(.van-overlay) {
|
||||
background-color: none;
|
||||
backdrop-filter: blur(0px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,20 +0,0 @@
|
||||
<template>
|
||||
<div class="loading_box">
|
||||
<img class="loading" :src="loadingSrc" rel="external nofollow" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import loadingSrc from '@/assets/gif/loading.gif';
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.loading_box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
img {
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,116 +0,0 @@
|
||||
<template>
|
||||
<van-overlay :show="isShow" z-index="2001" @click="emit('close')">
|
||||
<div class="wrapper">
|
||||
<div class="content">
|
||||
<div class="title">解锁会员</div>
|
||||
<h2>您还不是会员哟~</h2>
|
||||
<p>
|
||||
开通
|
||||
<span>VIP</span>
|
||||
{{ state.tip }}
|
||||
</p>
|
||||
<div class="btn-box flex-center-between">
|
||||
<div class="btn share" @click.stop="$router.push('/promotionCode')">分享邀请</div>
|
||||
<div class="btn" @click.stop="joinMembership">立即开通</div>
|
||||
</div>
|
||||
</div>
|
||||
<SvgIcon name="close" class="close" @click="emit('close')" />
|
||||
</div>
|
||||
</van-overlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const props = defineProps<{
|
||||
videoInfo?: Types.Video.VInfosItem;
|
||||
isOpen: boolean;
|
||||
tip?: string;
|
||||
}>();
|
||||
const emit = defineEmits(['close']);
|
||||
const isShow = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
tip: props.tip || '观看完成版视频',
|
||||
});
|
||||
/**
|
||||
* @description 开通会员
|
||||
*/
|
||||
const joinMembership = () => {
|
||||
router.push({
|
||||
path: '/recharge',
|
||||
query: {
|
||||
name: 'member',
|
||||
id: props.videoInfo?.id,
|
||||
title: props.videoInfo?.title || '无标题',
|
||||
},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.content {
|
||||
height: 187px;
|
||||
width: 312px;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding-top: 19px;
|
||||
box-sizing: border-box;
|
||||
.title {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
margin-bottom: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
h2 {
|
||||
font-size: 14px;
|
||||
color: rgb(153, 153, 153);
|
||||
}
|
||||
p {
|
||||
font-size: 14px;
|
||||
color: rgb(38, 38, 38);
|
||||
line-height: 26px;
|
||||
margin-top: 10px;
|
||||
span {
|
||||
color: rgb(255, 160, 1);
|
||||
}
|
||||
}
|
||||
.btn-box {
|
||||
padding: 0 22px;
|
||||
.btn {
|
||||
height: 38px;
|
||||
width: 129px;
|
||||
text-align: center;
|
||||
line-height: 38px;
|
||||
border-radius: 10px;
|
||||
font-size: 14px;
|
||||
background-color: $themeColor;
|
||||
color: white;
|
||||
margin-top: 26px;
|
||||
}
|
||||
.share {
|
||||
border: 1.5px solid rgb(153, 153, 153);
|
||||
background-color: unset;
|
||||
color: rgb(153, 153, 153);
|
||||
}
|
||||
}
|
||||
}
|
||||
.close {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,115 +0,0 @@
|
||||
<template>
|
||||
<div class="nineGridPopup">
|
||||
<van-overlay :show="isShow && appList.length > 0" z-index="2001" @click="emit('close')">
|
||||
<div class="wrapper">
|
||||
<!-- <AdvSwiper @click.stop class="topAdv" :isShowIndicators="true" :list="topList" v-if="topList.length > 0" />-->
|
||||
<div class="appList">
|
||||
<div v-for="(item, index) in appList.slice(0, 16)" :key="item.id">
|
||||
<div class="appItem" @click.stop="jumpAdv(item)">
|
||||
<lazyImg class="appIcon" :src="item.cover" />
|
||||
<div class="download">{{ item.title }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="close"></div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { getAdItem } from '@/utils/getConfig';
|
||||
import { AdType } from '@/enums/app';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
import { useGlobalStore } from '@/stores/global';
|
||||
|
||||
const globalStore = useGlobalStore();
|
||||
const props = defineProps<{
|
||||
isOpen: boolean;
|
||||
}>();
|
||||
const emit = defineEmits(['close']);
|
||||
const isShow = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
const appList = getAdItem(AdType.QualityApplication);
|
||||
// const topList = getAdItem(AdType.TopAdvsList);
|
||||
const init = () => {
|
||||
if (appList.length > 0) {
|
||||
globalStore.setNineGridFirst();
|
||||
}
|
||||
};
|
||||
init();
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.van-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
:deep(.adv-container) {
|
||||
height: 88px !important;
|
||||
.van-swipe-item {
|
||||
height: 88px !important;
|
||||
}
|
||||
}
|
||||
.nineGridPopup {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
.topAdv {
|
||||
width: 329px;
|
||||
height: 88px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
margin: 20px auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.appList {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
grid-row-gap: 18px;
|
||||
grid-column-gap: 12px;
|
||||
padding: 0 33px;
|
||||
.appItem {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
//height: 140px;
|
||||
.appIcon {
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.download {
|
||||
//height: 26px;
|
||||
width: 68px;
|
||||
//background-color: $themeColor;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
line-height: 26px;
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.close {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
background: url('./../../assets/images/png/closeDialog2.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
margin: 40px auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<van-overlay :show="isShow" z-index="2001" @click="emit('close')">
|
||||
<div class="wrapper">
|
||||
<div class="content">
|
||||
<div class="title">温馨提示</div>
|
||||
<div>—— 需要花费{{ audiobook.price }}解锁 ——</div>
|
||||
<div class="goldCoinBox flex-center-center">
|
||||
<div class="goldCoin"></div>
|
||||
<span>{{ audiobook.price }}</span>
|
||||
</div>
|
||||
<div class="btn-box" @click.stop="emit('buying')">立即解锁</div>
|
||||
</div>
|
||||
<SvgIcon name="close" class="close" @click.stop="emit('close')" />
|
||||
</div>
|
||||
</van-overlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
isOpen: boolean;
|
||||
audiobook: Types.Novel.ContentSetItem;
|
||||
}>();
|
||||
const emit = defineEmits(['close', 'buying']);
|
||||
const isShow = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.content {
|
||||
height: 185px;
|
||||
width: 312px;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding-top: 19px;
|
||||
box-sizing: border-box;
|
||||
.title {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
margin-bottom: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
h2 {
|
||||
font-size: 255px;
|
||||
color: rgb(153, 153, 153);
|
||||
}
|
||||
.goldCoinBox {
|
||||
margin-top: 13.5px;
|
||||
.goldCoin {
|
||||
height: 27px;
|
||||
width: 27px;
|
||||
background: url('./../../assets/images/png/goldCoin.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
margin-right: 8.6px;
|
||||
}
|
||||
span {
|
||||
font-size: 14px;
|
||||
color: rgb(255, 160, 1);
|
||||
}
|
||||
}
|
||||
.btn-box {
|
||||
height: 38px;
|
||||
width: 227px;
|
||||
background-color: $themeColor;
|
||||
font-size: 15px;
|
||||
color: white;
|
||||
line-height: 38px;
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
margin: 16px auto 0;
|
||||
}
|
||||
}
|
||||
.close {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,584 +0,0 @@
|
||||
<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>
|
||||
@@ -1,123 +0,0 @@
|
||||
<template>
|
||||
<div class="refreshing_warp">
|
||||
<van-pull-refresh
|
||||
v-model="params.refreshing"
|
||||
@refresh="onRefresh"
|
||||
:disabled="params.disabled"
|
||||
success-text="刷新成功"
|
||||
:class="[{ 'my-refresh': params.isHigehtMax, none: params.refreshing }, params.className]"
|
||||
>
|
||||
<van-list
|
||||
v-if="!params.isNoData"
|
||||
v-model:loading="loadingc"
|
||||
:finished="params.finished"
|
||||
finished-text="没有更多数据了"
|
||||
@load="onLoad"
|
||||
:offset="10"
|
||||
v-model:error="params.error"
|
||||
:immediate-check="false"
|
||||
error-text="请求失败,点击重新加载"
|
||||
>
|
||||
<slot></slot>
|
||||
</van-list>
|
||||
<Empty v-if="params.isNoData" />
|
||||
<!-- <div v-if="params.isNoData" class="dataNull">暂无数据</div> -->
|
||||
<div style="width: 100%; height: 240px"></div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, toRefs } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
params: {
|
||||
className?: string; //自定义class
|
||||
disabled?: boolean; //是否禁止下拉刷新 默认为false
|
||||
refreshing: boolean; //下拉刷新loading
|
||||
loading: boolean; //上滑刷新loading
|
||||
finished: boolean; //列表数据是否记载完毕
|
||||
isNoData: boolean; //数据是否为空
|
||||
error?: boolean; //请求错误
|
||||
/**
|
||||
* 占满父级100%
|
||||
* 组件内部 overflow-y:auto
|
||||
* 此参数设置为true的话,父级不要设置overflow-y:auto
|
||||
*/
|
||||
isHigehtMax?: boolean;
|
||||
};
|
||||
}>(),
|
||||
{},
|
||||
);
|
||||
const { params } = toRefs(props);
|
||||
|
||||
const loadingc = computed({
|
||||
get() {
|
||||
return params.value.loading;
|
||||
},
|
||||
set() {
|
||||
return params.value.loading;
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['onLoad', 'onRefresh']);
|
||||
function onLoad() {
|
||||
emit('onLoad');
|
||||
}
|
||||
function onRefresh() {
|
||||
emit('onRefresh');
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
:deep(.van-loading__circular) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.none {
|
||||
:deep(.van-list) {
|
||||
.van-loading {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.van-loading__spinner) {
|
||||
background: url('../../assets/gif/loading.gif');
|
||||
width: 25px !important;
|
||||
height: 25px !important;
|
||||
background-size: cover;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.refreshing_warp {
|
||||
height: 100%;
|
||||
.my-refresh {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding: 11px 16px;
|
||||
}
|
||||
|
||||
.loading_warp {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.loading_box {
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.loading {
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
.loading_text {
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,685 +0,0 @@
|
||||
<template>
|
||||
<div class="recharge-box">
|
||||
<div class="recharge-bg">
|
||||
<div class="payMethod">
|
||||
<span>付款方式</span>
|
||||
<!-- <span>¥</span>-->
|
||||
<!-- {{ state.discountedPrice }}-->
|
||||
</div>
|
||||
<van-radio-group v-model="state.activeItem" direction="horizontal" class="rechargeList">
|
||||
<div v-for="item in state.rechargeList" :key="item.channel" @click.stop="selectPay(item)">
|
||||
<div class="rechargeItem" v-if="item.type !== 'daichong'">
|
||||
<SvgIcon class="payIcon" :name="item.type"></SvgIcon>
|
||||
<div class="payText">{{ item.typeName }}</div>
|
||||
<van-radio checked-color="rgb(255,173,0)" icon-size="20px" :name="item.type"></van-radio>
|
||||
</div>
|
||||
<!-- 代充 -->
|
||||
<div v-if="state.dcInfo.traders && state.dcInfo.traders.length > 0 && item.type === 'daichong'">
|
||||
<div
|
||||
v-for="dcItem in state.dcInfo.traders[0].payInfos"
|
||||
:key="dcItem.payMethod"
|
||||
@click="selectDcPay(item, dcItem)"
|
||||
>
|
||||
<div class="rechargeItem" v-if="item.type == 'daichong'">
|
||||
<SvgIcon class="payIcon" :name="getSvgPayIcon(dcItem.payMethod)"></SvgIcon>
|
||||
<div class="payText">
|
||||
{{ getPayName(dcItem.payMethod) }}
|
||||
<span>(人工充值)</span>
|
||||
</div>
|
||||
<van-radio checked-color="rgb(253,191,80)" icon-size="16px" :name="'dc' + dcItem.payMethod"></van-radio>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-radio-group>
|
||||
<div class="payBtn" @click="toPay">{{ queryBtn == 'wallet' ? '去充值' : '去开通' }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 温馨提示 -->
|
||||
<van-popup class="kindTips" v-model:show="state.showKindTips">
|
||||
<div class="kindTipsBox">
|
||||
<div class="kindTitle">温馨提示</div>
|
||||
<div class="tipContent">
|
||||
本APP包含成人内容,会被误判为恶意程序,如在支付过程中遇恶意程序报毒提醒,
|
||||
<span>请「点击忽略」即可。我们有稳定的广告及赞助商收入,保证安全无毒请您放心使用!</span>
|
||||
</div>
|
||||
<div class="kindTip"></div>
|
||||
<div class="cBtn" @click="comfinPay">确认支付</div>
|
||||
</div>
|
||||
<SvgIcon class="close" name="close" @click="state.showKindTips = false"></SvgIcon>
|
||||
</van-popup>
|
||||
|
||||
<!-- 订单确认弹窗 -->
|
||||
<van-popup class="payTipPop" v-model:show="state.showPayTip">
|
||||
<div class="payTipBox">
|
||||
<div class="payTitle">订单支付确认</div>
|
||||
<div class="paySubTitle">支付确认</div>
|
||||
<div class="tipItem">
|
||||
1.支付成功后,一般会在
|
||||
<span>1~10分钟内到账</span>
|
||||
,如超时未到账,请联系在线客服为您处理。
|
||||
</div>
|
||||
<div class="tipItem">2.受特殊行业限制,如支付失败可尝试重新发起订单,系统将会自动切换备用的支付通道。</div>
|
||||
<div class="tipItem">3.本APP有隐定的广告收益,产品稳定安全,可放心充值使用。</div>
|
||||
<div class="confirmBtn">
|
||||
<!-- <router-link to="/customerService" class="btn">联系客服</router-link> -->
|
||||
<div class="btn" @click="toPotato">官方Potato</div>
|
||||
<div class="btn knowed" @click="state.showPayTip = false">我知道了</div>
|
||||
</div>
|
||||
</div>
|
||||
<SvgIcon class="close" name="close" @click="state.showPayTip = false"></SvgIcon>
|
||||
</van-popup>
|
||||
<van-popup class="payLoading" overlay-class="loadingOverlay" v-model:show="state.payLoading">
|
||||
<div class="loadingBox">
|
||||
<div class="loadingGif"></div>
|
||||
<div class="loadingText">
|
||||
{{ state.payFailed ? '订单跳转失败,请重新支付' : '正在跳转订单中,请勿重复提交' }}
|
||||
</div>
|
||||
<div class="loadingBtn" v-if="state.payFailed" @click="comfinPay">立即支付</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive } from 'vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import MineApi from '@/service/mine';
|
||||
import { Buffer } from 'buffer';
|
||||
import { showToast } from 'vant';
|
||||
import { analyticsEventRechage } from '@/utils/analyticsEvent';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
|
||||
const route = useRoute();
|
||||
const userStore = useUserStore();
|
||||
const userInfo = userStore.userInfo;
|
||||
const configStore = useConfigStore();
|
||||
const queryBtn = route.query.name;
|
||||
const emits = defineEmits(['closePay']);
|
||||
const state = reactive({
|
||||
rechargeList: <Array<Types.Recharge.RchgTypeItem>>[], // 支付方式列表
|
||||
activeItem: '', // 支付方式选中
|
||||
dcInfo: <Types.Recharge.Daichong>{}, // 代充信息
|
||||
dcType: 1, // 代充商品类型 会员-1 金币-0
|
||||
popType: 'vip', // 弹窗类型 会员卡-vip 金币-gold
|
||||
payMethodType: 'dc', // 支付方式类型 支付渠道-channel 代充-dc 金币兑换-gold
|
||||
productType: '', // 商品类型
|
||||
productID: '', // 商品ID
|
||||
buyType: '', // 商品类型
|
||||
discountedPrice: 0, // 充值金额
|
||||
payInfo: <any>{}, // 支付渠道信息
|
||||
rchgType: <any>{}, // 充值类型
|
||||
dcPayInfo: <any>{}, // 代充支付信息
|
||||
showPayTip: false, // 支付提示弹窗状态
|
||||
showKindTips: false, // 温馨提示
|
||||
isAmountPay: false, // 是否支持金币兑换
|
||||
graphicsId: '', // 埋点ID
|
||||
graphicsTitle: '', // 埋点标题
|
||||
pageNumber: 1,
|
||||
loading: false,
|
||||
finished: false,
|
||||
radioValue: '',
|
||||
curRadioValue: '', // 金币加购券
|
||||
show: false,
|
||||
payLoading: false,
|
||||
payFailed: false,
|
||||
});
|
||||
const toPotato = () => {
|
||||
if (configStore.sourceInfo.GROUP) {
|
||||
window.open(configStore.sourceInfo.GROUP);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description 显示支付方式弹窗
|
||||
* @param rechargeList - 支付方式列表
|
||||
* @param dcInfo - 代充信息
|
||||
* @param popType - 弹窗类型 会员卡-vip 金币-gold
|
||||
*/
|
||||
const changeItem = (payData: any) => {
|
||||
state.rechargeList = payData.rechargeList;
|
||||
if (payData.dcInfo) {
|
||||
state.dcInfo = payData.dcInfo;
|
||||
}
|
||||
state.popType = payData.popType;
|
||||
state.dcType = payData.dcType;
|
||||
state.productType = payData.productType;
|
||||
state.productID = payData.productID;
|
||||
state.discountedPrice = payData.discountedPrice;
|
||||
state.buyType = payData.buyType;
|
||||
state.isAmountPay = payData.isAmountPay;
|
||||
let dcArr = state.rechargeList.filter((i: any) => {
|
||||
return i.type == 'daichong';
|
||||
});
|
||||
let channel = state.rechargeList.filter((i: any) => {
|
||||
return i.type != 'daichong';
|
||||
});
|
||||
if (channel.length > 0) {
|
||||
selectPay(channel[0]);
|
||||
} else if (dcArr.length > 0 && state.dcInfo.traders.length > 0 && state.dcInfo.traders[0].payInfos.length > 0) {
|
||||
let arr = state.rechargeList.filter((i: any) => {
|
||||
return i.type == 'daichong';
|
||||
});
|
||||
selectDcPay(arr[0], state.dcInfo.traders[0].payInfos[0]);
|
||||
} else {
|
||||
selectGoldPay();
|
||||
}
|
||||
};
|
||||
// 选中支付方式
|
||||
const selectPay = (item: any) => {
|
||||
if (item.type != 'daichong') {
|
||||
state.payInfo = item;
|
||||
state.rchgType = {};
|
||||
state.dcPayInfo = {};
|
||||
state.payMethodType = 'channel';
|
||||
state.activeItem = item.type;
|
||||
}
|
||||
};
|
||||
// 选中代充支付方式
|
||||
const selectDcPay = (rchgType: any, dcPayInfo: Types.Recharge.Daichong) => {
|
||||
state.payInfo = {};
|
||||
state.rchgType = rchgType;
|
||||
state.dcPayInfo = dcPayInfo;
|
||||
state.payMethodType = 'dc';
|
||||
state.activeItem = 'dc' + state.dcPayInfo.payMethod;
|
||||
};
|
||||
// 选中金币兑换
|
||||
const selectGoldPay = () => {
|
||||
state.payInfo = { typeName: '金币' };
|
||||
state.rchgType = {};
|
||||
state.dcPayInfo = {};
|
||||
state.payMethodType = 'gold';
|
||||
state.activeItem = 'gold';
|
||||
};
|
||||
// 立即支付
|
||||
const toPay = () => {
|
||||
// if (state.payMethodType == 'gold') {
|
||||
// goldExchange();
|
||||
// return;
|
||||
// }
|
||||
state.showKindTips = true;
|
||||
};
|
||||
const comfinPay = () => {
|
||||
state.payLoading = true;
|
||||
state.payFailed = false;
|
||||
if (state.payMethodType == 'channel') {
|
||||
channelPay();
|
||||
} else if (state.payMethodType == 'dc') {
|
||||
dcToPay();
|
||||
}
|
||||
// 埋点
|
||||
const graphicsId: any = route.query.id ? route.query.id : 'user'; // 视频传:视频id 横幅传 bannerId 用户自己拉取传 user
|
||||
const graphicsTitle: any = route.query.title ? route.query.title : ''; // 标题
|
||||
const graphicsType = state.popType == 'gold' ? 1 : 2; // 充值类型
|
||||
try {
|
||||
analyticsEventRechage(graphicsId, graphicsTitle, graphicsType);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
// 金币兑换
|
||||
const goldExchange = async () => {
|
||||
let req = {
|
||||
productType: state.productType,
|
||||
productID: state.productID,
|
||||
isH5: true,
|
||||
};
|
||||
try {
|
||||
userStore.updateWallet();
|
||||
let walletInfo = userStore.walletInfo;
|
||||
let walletBalance = ((walletInfo.amount || 0) + (walletInfo.income || 0)).toFixed(2);
|
||||
if (state.discountedPrice * 10 > Number(walletBalance)) {
|
||||
showToast('金币不足请充值');
|
||||
return;
|
||||
}
|
||||
await MineApi.goldExchange(req);
|
||||
showToast('购买成功');
|
||||
emits('closePay');
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
// 支付渠道支付
|
||||
const channelPay = async () => {
|
||||
state.show = true;
|
||||
let req = {
|
||||
uid: userInfo.uid,
|
||||
rechargeType: state.payInfo.type,
|
||||
productID: state.productID,
|
||||
buyType: state.buyType,
|
||||
goldExtraID: state.curRadioValue ? state.curRadioValue : undefined,
|
||||
};
|
||||
try {
|
||||
let ret: any = await MineApi.getPay(req);
|
||||
state.show = false;
|
||||
state.payInfo = {};
|
||||
state.showPayTip = true;
|
||||
state.showKindTips = false;
|
||||
state.payLoading = false;
|
||||
// window.open( ret.payUrl, '_blank');
|
||||
window.location = ret.payUrl;
|
||||
state.curRadioValue = '';
|
||||
} catch (e) {
|
||||
state.show = false;
|
||||
state.payFailed = true;
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
// 代充
|
||||
const dcToPay = () => {
|
||||
try {
|
||||
state.show = true;
|
||||
let payMoney = state.discountedPrice;
|
||||
let dcData = JSON.parse(JSON.stringify(state.dcInfo)); // 代充信息
|
||||
let payInfoModel = JSON.parse(JSON.stringify(state.dcPayInfo)); // 代充支付类型
|
||||
let channel = state.rchgType.channel;
|
||||
let productInfo = {
|
||||
id: state.productID,
|
||||
type: state.dcType,
|
||||
version: '3.0.0',
|
||||
};
|
||||
//设置默认值
|
||||
if (dcData.limit == 0) {
|
||||
dcData.limit = 500;
|
||||
}
|
||||
if (payInfoModel.payType.includes(2) && payInfoModel.payType.includes(3)) {
|
||||
if (payMoney > dcData.limit) {
|
||||
payInfoModel.payType = [3];
|
||||
} else {
|
||||
payInfoModel.payType = [2];
|
||||
}
|
||||
}
|
||||
if (payInfoModel.payType.length >= 3) {
|
||||
if (payMoney > dcData.limit) {
|
||||
payInfoModel.payType = [1, 3];
|
||||
} else {
|
||||
payInfoModel.payType = [1, 2];
|
||||
}
|
||||
}
|
||||
dcData.traders[0].payInfos = [payInfoModel];
|
||||
dcData.productInfo = productInfo;
|
||||
dcData.chargeMoney = payMoney;
|
||||
dcData.channel = channel;
|
||||
let models = JSON.stringify(dcData);
|
||||
let payUrl = `${channel}/?data=${encodeBase64(models)}&token=${userStore.token}`;
|
||||
state.showPayTip = true;
|
||||
state.showKindTips = false;
|
||||
state.show = false;
|
||||
state.payLoading = false;
|
||||
window.location.href = payUrl;
|
||||
} catch (error) {
|
||||
state.payFailed = true;
|
||||
}
|
||||
};
|
||||
// 转base64
|
||||
const encodeBase64 = (str: any) => {
|
||||
let base64Str = Buffer.from(str, 'utf-8').toString('base64');
|
||||
return base64Str;
|
||||
};
|
||||
// 获取支付方式名称
|
||||
const getPayName = (type: any) => {
|
||||
switch (type) {
|
||||
case 'alipay':
|
||||
return '支付宝';
|
||||
case 'wechat':
|
||||
return '微信';
|
||||
case 'union':
|
||||
return '银联';
|
||||
case 101:
|
||||
return '支付宝';
|
||||
case 102:
|
||||
return '微信';
|
||||
case 103:
|
||||
return '银行卡';
|
||||
case 104:
|
||||
return '信用卡';
|
||||
case 105:
|
||||
return '花呗';
|
||||
case 106:
|
||||
return '云闪付';
|
||||
case 107:
|
||||
return 'QQ钱包';
|
||||
case 108:
|
||||
return '京东支付';
|
||||
default:
|
||||
return '金币兑换';
|
||||
}
|
||||
};
|
||||
// 获取支付方式图标
|
||||
const getSvgPayIcon = (type: any) => {
|
||||
switch (type) {
|
||||
case 'alipay':
|
||||
return 'alipay';
|
||||
case 'wechat':
|
||||
return 'wechat';
|
||||
case 'union':
|
||||
return 'bankcard';
|
||||
case 101:
|
||||
return 'alipay';
|
||||
case 102:
|
||||
return 'wechat';
|
||||
case 103:
|
||||
return 'bankcard';
|
||||
case 104:
|
||||
return 'bankcard';
|
||||
case 105:
|
||||
return 'alipay';
|
||||
case 106:
|
||||
return 'bankcard';
|
||||
case 107:
|
||||
return 'bankcard';
|
||||
case 108:
|
||||
return 'bankcard';
|
||||
default:
|
||||
return 'gold';
|
||||
}
|
||||
};
|
||||
defineExpose({
|
||||
changeItem,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.van-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
:deep(.van-popup) {
|
||||
background-color: transparent;
|
||||
}
|
||||
.recharge-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.recharge-bg {
|
||||
color: rgb(255, 255, 255);
|
||||
// background-color: rgb(0, 0, 0);
|
||||
.recharge-title {
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
color: $titleColor;
|
||||
> svg {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 14px;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.payMethod {
|
||||
font-size: 31px;
|
||||
text-align: left;
|
||||
color: $titleColor;
|
||||
padding-bottom: 15px;
|
||||
span {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.rechargeList {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding: 8px 0px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.rechargeItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 8px 0;
|
||||
.payIcon {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background: $titleColor;
|
||||
border-radius: 100px;
|
||||
}
|
||||
.payGoldIcon {
|
||||
background: url('./../../assets/images/png/goldIcon.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.payText {
|
||||
flex: 2;
|
||||
color: $titleColor;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
margin-left: 12px;
|
||||
}
|
||||
:deep(.van-radio) {
|
||||
.van-radio__icon--checked .van-icon {
|
||||
color: #000 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.couponBox {
|
||||
height: 90px;
|
||||
.couponTitle {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: $titleColor;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
// .couponList {
|
||||
// height: 60px;
|
||||
// overflow-y: auto;
|
||||
// }
|
||||
.coupon-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 5px;
|
||||
.coupon-title {
|
||||
font-size: 14px;
|
||||
color: $greyDeepColor;
|
||||
}
|
||||
.coupon-amount {
|
||||
flex: 2;
|
||||
text-align: right;
|
||||
margin: 0 10px;
|
||||
font-size: 14px;
|
||||
color: $titleColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
.subTitle {
|
||||
font-size: 14px;
|
||||
color: rgb(255, 160, 1);
|
||||
margin: 10px 0;
|
||||
}
|
||||
.payTip {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
letter-spacing: -0.34px;
|
||||
color: rgb(128, 128, 128);
|
||||
}
|
||||
|
||||
.customerService {
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
margin: 10px 0 6px;
|
||||
color: rgb(128, 128, 128);
|
||||
.contactCustomer {
|
||||
color: $themeColor;
|
||||
}
|
||||
}
|
||||
|
||||
.payBtn {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
line-height: 48px;
|
||||
width: 343px;
|
||||
height: 48px;
|
||||
font-weight: 600;
|
||||
border-radius: 100px;
|
||||
color: #2c2c2c;
|
||||
background: #f1a100;
|
||||
}
|
||||
|
||||
.sizeBox {
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.kindTips {
|
||||
border-radius: 6px;
|
||||
.kindTipsBox {
|
||||
width: 308px;
|
||||
height: 337px;
|
||||
border-radius: 6px;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
padding-top: 16px;
|
||||
.kindTitle {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
text-align: center;
|
||||
margin-bottom: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.tipContent {
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.24px;
|
||||
line-height: 22px;
|
||||
margin: 0 20px;
|
||||
color: #000;
|
||||
span {
|
||||
color: rgb(255, 160, 1);
|
||||
}
|
||||
}
|
||||
.kindTip {
|
||||
height: 86px;
|
||||
width: 251px;
|
||||
border-radius: 10px;
|
||||
background: url('./../../assets/images/png/kindTip.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
margin: 10px auto 29px;
|
||||
}
|
||||
.cBtn {
|
||||
width: 227px;
|
||||
height: 38px;
|
||||
font-size: 14px;
|
||||
border-radius: 10px;
|
||||
margin: 0px auto;
|
||||
color: white;
|
||||
background: $themeColor;
|
||||
text-align: center;
|
||||
line-height: 38px;
|
||||
}
|
||||
}
|
||||
.close {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin: 26px 0 0;
|
||||
position: relative;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
transform: translate(-50%, 0%);
|
||||
}
|
||||
}
|
||||
.payTipPop {
|
||||
border-radius: 6px;
|
||||
.payTipBox {
|
||||
height: 330px;
|
||||
width: 308px;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
padding: 16px 33.5px 0;
|
||||
border-radius: 6px;
|
||||
.payTitle {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.paySubTitle {
|
||||
font-size: 12px;
|
||||
color: rgb(38, 38, 38);
|
||||
margin: 23px 0 7px;
|
||||
}
|
||||
.tipItem {
|
||||
font-size: 12px;
|
||||
margin-bottom: 16px;
|
||||
color: #000;
|
||||
line-height: 20px;
|
||||
span {
|
||||
color: rgb(255, 125, 77);
|
||||
}
|
||||
}
|
||||
.confirmBtn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 27px;
|
||||
.btn {
|
||||
height: 38px;
|
||||
width: 113px;
|
||||
border-radius: 10px;
|
||||
line-height: 38px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: rgb(153, 153, 153);
|
||||
border: 1.5px solid rgb(153, 153, 153);
|
||||
}
|
||||
.knowed {
|
||||
border: none;
|
||||
background-color: $themeColor;
|
||||
color: white;
|
||||
margin-left: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.close {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin: 26px 0 0;
|
||||
position: relative;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
transform: translate(-50%, 0%);
|
||||
}
|
||||
}
|
||||
.payLoading {
|
||||
.loadingBox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.loadingGif {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: url('../../assets/gif/payLoading.gif');
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.loadingText {
|
||||
color: #f8c700;
|
||||
font-family: 'PingFang HK';
|
||||
font-size: 14px;
|
||||
margin: 21px 0 29px;
|
||||
text-align: center;
|
||||
}
|
||||
.loadingBtn {
|
||||
width: 227px;
|
||||
height: 38px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #ffa001;
|
||||
color: #fff;
|
||||
font-family: 'PingFang HK';
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.loadingOverlay) {
|
||||
backdrop-filter: blur(3.75px);
|
||||
}
|
||||
</style>
|
||||
@@ -1,609 +0,0 @@
|
||||
<template>
|
||||
<div class="recharge-box">
|
||||
<div class="recharge-bg">
|
||||
<div class="payMethod">
|
||||
<span>¥</span>
|
||||
{{ state.discountedPrice }}
|
||||
</div>
|
||||
<van-radio-group v-model="state.activeItem" direction="horizontal" class="rechargeList">
|
||||
<div v-for="item in state.rechargeList" :key="item.channel" @click.stop="selectPay(item)">
|
||||
<div class="rechargeItem" v-if="item.type !== 'daichong'">
|
||||
<SvgIcon class="payIcon" :name="item.type"></SvgIcon>
|
||||
<div class="payText">{{ item.typeName }}</div>
|
||||
<van-radio checked-color="rgb(253,191,80)" icon-size="16px" :name="item.type"></van-radio>
|
||||
</div>
|
||||
<!-- 代充 -->
|
||||
<div v-if="state.dcInfo.traders && state.dcInfo.traders.length > 0 && item.type === 'daichong'">
|
||||
<div
|
||||
v-for="dcItem in state.dcInfo.traders[0].payInfos"
|
||||
:key="dcItem.payMethod"
|
||||
@click="selectDcPay(item, dcItem)"
|
||||
>
|
||||
<div class="rechargeItem" v-if="item.type == 'daichong'">
|
||||
<SvgIcon class="payIcon" :name="getSvgPayIcon(dcItem.payMethod)"></SvgIcon>
|
||||
<div class="payText">
|
||||
{{ getPayName(dcItem.payMethod) }}
|
||||
<span>(人工充值)</span>
|
||||
</div>
|
||||
<van-radio checked-color="rgb(253,191,80)" icon-size="16px" :name="'dc' + dcItem.payMethod"></van-radio>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-radio-group>
|
||||
<div class="payBtn" @click="toPay">立即支付</div>
|
||||
<div class="sizeBox"></div>
|
||||
</div>
|
||||
|
||||
<!-- 温馨提示 -->
|
||||
<van-popup class="kindTips" v-model:show="state.showKindTips">
|
||||
<div class="kindTipsBox">
|
||||
<div class="kindTitle">温馨提示</div>
|
||||
<div class="tipContent">
|
||||
本APP包含成人内容,会被误判为恶意程序,如在支付过程中遇恶意程序报毒提醒,
|
||||
<span>请「点击忽略」即可。我们有稳定的广告及赞助商收入,保证安全无毒请您放心使用!</span>
|
||||
</div>
|
||||
<div class="kindTip"></div>
|
||||
<div class="cBtn" @click="comfinPay">确认支付</div>
|
||||
</div>
|
||||
<SvgIcon class="close" name="close" @click="state.showKindTips = false"></SvgIcon>
|
||||
</van-popup>
|
||||
|
||||
<!-- 订单确认弹窗 -->
|
||||
<van-popup class="payTipPop" v-model:show="state.showPayTip">
|
||||
<div class="payTipBox">
|
||||
<div class="payTitle">订单支付确认</div>
|
||||
<div class="paySubTitle">支付确认</div>
|
||||
<div class="tipItem">
|
||||
1.支付成功后,一般会在
|
||||
<span>1~10分钟内到账</span>
|
||||
,如超时未到账,请联系在线客服为您处理。
|
||||
</div>
|
||||
<div class="tipItem">2.受特殊行业限制,如支付失败可尝试重新发起订单,系统将会自动切换备用的支付通道。</div>
|
||||
<div class="tipItem">3.本APP有隐定的广告收益,产品稳定安全,可放心充值使用。</div>
|
||||
<div class="confirmBtn">
|
||||
<!-- <router-link to="/customerService" class="btn">联系客服</router-link> -->
|
||||
<div class="btn" @click="toPotato">官方Potato</div>
|
||||
<div class="btn knowed" @click="state.showPayTip = false">我知道了</div>
|
||||
</div>
|
||||
</div>
|
||||
<SvgIcon class="close" name="close" @click="state.showPayTip = false"></SvgIcon>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive } from 'vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import MineApi from '@/service/mine';
|
||||
import { Buffer } from 'buffer';
|
||||
import { showToast } from 'vant';
|
||||
import { analyticsEventRechage } from '@/utils/analyticsEvent';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
|
||||
const route = useRoute();
|
||||
const userStore = useUserStore();
|
||||
const userInfo = userStore.userInfo;
|
||||
const configStore = useConfigStore();
|
||||
const emits = defineEmits(['closePay']);
|
||||
const state = reactive({
|
||||
rechargeList: <Array<Types.Recharge.RchgTypeItem>>[], // 支付方式列表
|
||||
activeItem: '', // 支付方式选中
|
||||
dcInfo: <Types.Recharge.Daichong>{}, // 代充信息
|
||||
dcType: 1, // 代充商品类型 会员-1 金币-0
|
||||
popType: 'vip', // 弹窗类型 会员卡-vip 金币-gold
|
||||
payMethodType: 'dc', // 支付方式类型 支付渠道-channel 代充-dc 金币兑换-gold
|
||||
productType: '', // 商品类型
|
||||
productID: '', // 商品ID
|
||||
buyType: '', // 商品类型
|
||||
discountedPrice: 0, // 充值金额
|
||||
payInfo: <any>{}, // 支付渠道信息
|
||||
rchgType: <any>{}, // 充值类型
|
||||
dcPayInfo: <any>{}, // 代充支付信息
|
||||
showPayTip: false, // 支付提示弹窗状态
|
||||
showKindTips: false, // 温馨提示
|
||||
isAmountPay: false, // 是否支持金币兑换
|
||||
graphicsId: '', // 埋点ID
|
||||
graphicsTitle: '', // 埋点标题
|
||||
pageNumber: 1,
|
||||
loading: false,
|
||||
finished: false,
|
||||
radioValue: '',
|
||||
curRadioValue: '', // 金币加购券
|
||||
show: false,
|
||||
});
|
||||
const toPotato = () => {
|
||||
if (configStore.sourceInfo.GROUP) {
|
||||
window.open(configStore.sourceInfo.GROUP);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description 显示支付方式弹窗
|
||||
* @param rechargeList - 支付方式列表
|
||||
* @param dcInfo - 代充信息
|
||||
* @param popType - 弹窗类型 会员卡-vip 金币-gold
|
||||
*/
|
||||
const changeItem = (payData: any) => {
|
||||
state.rechargeList = payData.rechargeList;
|
||||
if (payData.dcInfo) {
|
||||
state.dcInfo = payData.dcInfo;
|
||||
}
|
||||
state.popType = payData.popType;
|
||||
state.dcType = payData.dcType;
|
||||
state.productType = payData.productType;
|
||||
state.productID = payData.productID;
|
||||
state.discountedPrice = payData.discountedPrice;
|
||||
state.buyType = payData.buyType;
|
||||
state.isAmountPay = payData.isAmountPay;
|
||||
let dcArr = state.rechargeList.filter((i: any) => {
|
||||
return i.type == 'daichong';
|
||||
});
|
||||
let channel = state.rechargeList.filter((i: any) => {
|
||||
return i.type != 'daichong';
|
||||
});
|
||||
if (channel.length > 0) {
|
||||
selectPay(channel[0]);
|
||||
} else if (dcArr.length > 0 && state.dcInfo.traders.length > 0 && state.dcInfo.traders[0].payInfos.length > 0) {
|
||||
let arr = state.rechargeList.filter((i: any) => {
|
||||
return i.type == 'daichong';
|
||||
});
|
||||
selectDcPay(arr[0], state.dcInfo.traders[0].payInfos[0]);
|
||||
} else {
|
||||
selectGoldPay();
|
||||
}
|
||||
};
|
||||
// 选中支付方式
|
||||
const selectPay = (item: any) => {
|
||||
if (item.type != 'daichong') {
|
||||
state.payInfo = item;
|
||||
state.rchgType = {};
|
||||
state.dcPayInfo = {};
|
||||
state.payMethodType = 'channel';
|
||||
state.activeItem = item.type;
|
||||
}
|
||||
};
|
||||
// 选中代充支付方式
|
||||
const selectDcPay = (rchgType: any, dcPayInfo: Types.Recharge.Daichong) => {
|
||||
state.payInfo = {};
|
||||
state.rchgType = rchgType;
|
||||
state.dcPayInfo = dcPayInfo;
|
||||
state.payMethodType = 'dc';
|
||||
state.activeItem = 'dc' + state.dcPayInfo.payMethod;
|
||||
};
|
||||
// 选中金币兑换
|
||||
const selectGoldPay = () => {
|
||||
state.payInfo = { typeName: '金币' };
|
||||
state.rchgType = {};
|
||||
state.dcPayInfo = {};
|
||||
state.payMethodType = 'gold';
|
||||
state.activeItem = 'gold';
|
||||
};
|
||||
// 立即支付
|
||||
const toPay = () => {
|
||||
if (state.payMethodType == 'gold') {
|
||||
goldExchange();
|
||||
return;
|
||||
}
|
||||
state.showKindTips = true;
|
||||
};
|
||||
const comfinPay = () => {
|
||||
if (state.payMethodType == 'channel') {
|
||||
channelPay();
|
||||
} else if (state.payMethodType == 'dc') {
|
||||
dcToPay();
|
||||
}
|
||||
// 埋点
|
||||
const graphicsId: any = route.query.id ? route.query.id : 'user'; // 视频传:视频id 横幅传 bannerId 用户自己拉取传 user
|
||||
const graphicsTitle: any = route.query.title ? route.query.title : ''; // 标题
|
||||
const graphicsType = state.popType == 'gold' ? 1 : 2; // 充值类型
|
||||
try {
|
||||
analyticsEventRechage(graphicsId, graphicsTitle, graphicsType);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
// 金币兑换
|
||||
const goldExchange = async () => {
|
||||
let req = {
|
||||
productType: state.productType,
|
||||
productID: state.productID,
|
||||
isH5: true,
|
||||
};
|
||||
try {
|
||||
userStore.updateWallet();
|
||||
let walletInfo = userStore.walletInfo;
|
||||
let walletBalance = ((walletInfo.amount || 0) + (walletInfo.income || 0)).toFixed(2);
|
||||
if (state.discountedPrice * 10 > Number(walletBalance)) {
|
||||
showToast('金币不足请充值');
|
||||
return;
|
||||
}
|
||||
await MineApi.goldExchange(req);
|
||||
showToast('购买成功');
|
||||
emits('closePay');
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
// 支付渠道支付
|
||||
const channelPay = async () => {
|
||||
state.show = true;
|
||||
let req = {
|
||||
uid: userInfo.uid,
|
||||
rechargeType: state.payInfo.type,
|
||||
productID: state.productID,
|
||||
buyType: state.buyType,
|
||||
goldExtraID: state.curRadioValue ? state.curRadioValue : undefined,
|
||||
};
|
||||
try {
|
||||
let ret: any = await MineApi.getPay(req);
|
||||
state.show = false;
|
||||
state.payInfo = {};
|
||||
state.showPayTip = true;
|
||||
state.showKindTips = false;
|
||||
// window.open( ret.payUrl, '_blank');
|
||||
window.location = ret.payUrl;
|
||||
state.curRadioValue = '';
|
||||
} catch (e) {
|
||||
state.show = false;
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
// 代充
|
||||
const dcToPay = () => {
|
||||
state.show = true;
|
||||
let payMoney = state.discountedPrice;
|
||||
let dcData = JSON.parse(JSON.stringify(state.dcInfo)); // 代充信息
|
||||
let payInfoModel = JSON.parse(JSON.stringify(state.dcPayInfo)); // 代充支付类型
|
||||
let channel = state.rchgType.channel;
|
||||
let productInfo = {
|
||||
id: state.productID,
|
||||
type: state.dcType,
|
||||
version: '3.0.0',
|
||||
};
|
||||
//设置默认值
|
||||
if (dcData.limit == 0) {
|
||||
dcData.limit = 500;
|
||||
}
|
||||
if (payInfoModel.payType.includes(2) && payInfoModel.payType.includes(3)) {
|
||||
if (payMoney > dcData.limit) {
|
||||
payInfoModel.payType = [3];
|
||||
} else {
|
||||
payInfoModel.payType = [2];
|
||||
}
|
||||
}
|
||||
if (payInfoModel.payType.length >= 3) {
|
||||
if (payMoney > dcData.limit) {
|
||||
payInfoModel.payType = [1, 3];
|
||||
} else {
|
||||
payInfoModel.payType = [1, 2];
|
||||
}
|
||||
}
|
||||
dcData.traders[0].payInfos = [payInfoModel];
|
||||
dcData.productInfo = productInfo;
|
||||
dcData.chargeMoney = payMoney;
|
||||
dcData.channel = channel;
|
||||
let models = JSON.stringify(dcData);
|
||||
let payUrl = `${channel}/?data=${encodeBase64(models)}&token=${userStore.token}`;
|
||||
state.showPayTip = true;
|
||||
state.showKindTips = false;
|
||||
state.show = false;
|
||||
window.location.href = payUrl;
|
||||
};
|
||||
// 转base64
|
||||
const encodeBase64 = (str: any) => {
|
||||
let base64Str = Buffer.from(str, 'utf-8').toString('base64');
|
||||
return base64Str;
|
||||
};
|
||||
// 获取支付方式名称
|
||||
const getPayName = (type: any) => {
|
||||
switch (type) {
|
||||
case 'alipay':
|
||||
return '支付宝';
|
||||
case 'wechat':
|
||||
return '微信';
|
||||
case 'union':
|
||||
return '银联';
|
||||
case 101:
|
||||
return '支付宝';
|
||||
case 102:
|
||||
return '微信';
|
||||
case 103:
|
||||
return '银行卡';
|
||||
case 104:
|
||||
return '信用卡';
|
||||
case 105:
|
||||
return '花呗';
|
||||
case 106:
|
||||
return '云闪付';
|
||||
case 107:
|
||||
return 'QQ钱包';
|
||||
case 108:
|
||||
return '京东支付';
|
||||
default:
|
||||
return '金币兑换';
|
||||
}
|
||||
};
|
||||
// 获取支付方式图标
|
||||
const getSvgPayIcon = (type: any) => {
|
||||
switch (type) {
|
||||
case 'alipay':
|
||||
return 'alipay';
|
||||
case 'wechat':
|
||||
return 'wechat';
|
||||
case 'union':
|
||||
return 'bankcard';
|
||||
case 101:
|
||||
return 'alipay';
|
||||
case 102:
|
||||
return 'wechat';
|
||||
case 103:
|
||||
return 'bankcard';
|
||||
case 104:
|
||||
return 'bankcard';
|
||||
case 105:
|
||||
return 'alipay';
|
||||
case 106:
|
||||
return 'bankcard';
|
||||
case 107:
|
||||
return 'bankcard';
|
||||
case 108:
|
||||
return 'bankcard';
|
||||
default:
|
||||
return 'gold';
|
||||
}
|
||||
};
|
||||
defineExpose({
|
||||
changeItem,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.van-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
:deep(.van-popup) {
|
||||
background-color: transparent;
|
||||
}
|
||||
.recharge-box {
|
||||
.recharge-popup {
|
||||
.recharge-bg {
|
||||
background-color: rgb(255, 255, 255);
|
||||
// background-color: rgb(0, 0, 0);
|
||||
border-radius: 12px 12px 0 0;
|
||||
padding: 0 14px;
|
||||
.recharge-title {
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
color: $titleColor;
|
||||
> svg {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 14px;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.payMethod {
|
||||
font-size: 31px;
|
||||
text-align: center;
|
||||
color: rgb(38, 38, 38);
|
||||
span {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.rechargeList {
|
||||
max-height: 310px;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding: 8px 0px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.rechargeItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 8px 0;
|
||||
.payIcon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
.payGoldIcon {
|
||||
background: url('./../../assets/images/png/goldIcon.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.payText {
|
||||
flex: 2;
|
||||
color: rgb(38, 38, 38);
|
||||
font-size: 14px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.couponBox {
|
||||
height: 90px;
|
||||
.couponTitle {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: $titleColor;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
// .couponList {
|
||||
// height: 60px;
|
||||
// overflow-y: auto;
|
||||
// }
|
||||
.coupon-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 5px;
|
||||
.coupon-title {
|
||||
font-size: 14px;
|
||||
color: $greyDeepColor;
|
||||
}
|
||||
.coupon-amount {
|
||||
flex: 2;
|
||||
text-align: right;
|
||||
margin: 0 10px;
|
||||
font-size: 14px;
|
||||
color: $titleColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
.subTitle {
|
||||
font-size: 14px;
|
||||
color: rgb(255, 160, 1);
|
||||
margin: 10px 0;
|
||||
}
|
||||
.payTip {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
letter-spacing: -0.34px;
|
||||
color: rgb(128, 128, 128);
|
||||
}
|
||||
|
||||
.customerService {
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
margin: 10px 0 6px;
|
||||
color: rgb(128, 128, 128);
|
||||
.contactCustomer {
|
||||
color: $themeColor;
|
||||
}
|
||||
}
|
||||
|
||||
.payBtn {
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
border-radius: 42px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
background: rgb(255, 160, 1);
|
||||
margin: 15px 17px 0px 17px;
|
||||
}
|
||||
|
||||
.sizeBox {
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.kindTips {
|
||||
border-radius: 6px;
|
||||
.kindTipsBox {
|
||||
width: 308px;
|
||||
height: 337px;
|
||||
border-radius: 6px;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
padding-top: 16px;
|
||||
.kindTitle {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
text-align: center;
|
||||
margin-bottom: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.tipContent {
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.24px;
|
||||
line-height: 22px;
|
||||
margin: 0 20px;
|
||||
color: rgb(38, 38, 38);
|
||||
span {
|
||||
color: rgb(255, 160, 1);
|
||||
}
|
||||
}
|
||||
.kindTip {
|
||||
height: 86px;
|
||||
width: 251px;
|
||||
border-radius: 10px;
|
||||
background: url('./../../assets/images/png/kindTip.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
margin: 10px auto 29px;
|
||||
}
|
||||
.cBtn {
|
||||
width: 227px;
|
||||
height: 38px;
|
||||
font-size: 14px;
|
||||
border-radius: 10px;
|
||||
margin: 0px auto;
|
||||
color: white;
|
||||
background: $themeColor;
|
||||
text-align: center;
|
||||
line-height: 38px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.payTipPop {
|
||||
border-radius: 6px;
|
||||
.payTipBox {
|
||||
height: 330px;
|
||||
width: 308px;
|
||||
background: url('./../../assets/images/png/popupBg.png') no-repeat;
|
||||
background-size: 100% 123px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
padding: 16px 33.5px 0;
|
||||
border-radius: 6px;
|
||||
.payTitle {
|
||||
font-size: 18px;
|
||||
color: rgb(38, 38, 38);
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.paySubTitle {
|
||||
font-size: 12px;
|
||||
color: rgb(38, 38, 38);
|
||||
margin: 23px 0 7px;
|
||||
}
|
||||
.tipItem {
|
||||
font-size: 12px;
|
||||
margin-bottom: 16px;
|
||||
color: rgb(38, 38, 38);
|
||||
line-height: 20px;
|
||||
span {
|
||||
color: rgb(255, 125, 77);
|
||||
}
|
||||
}
|
||||
.confirmBtn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 27px;
|
||||
.btn {
|
||||
height: 38px;
|
||||
width: 113px;
|
||||
border-radius: 10px;
|
||||
line-height: 38px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: rgb(153, 153, 153);
|
||||
border: 1.5px solid rgb(153, 153, 153);
|
||||
}
|
||||
.knowed {
|
||||
border: none;
|
||||
background-color: $themeColor;
|
||||
color: white;
|
||||
margin-left: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.close {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin: 26px 0 0;
|
||||
position: relative;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,150 +0,0 @@
|
||||
<template>
|
||||
<div class="reward-popup">
|
||||
<van-popup v-model:show="state.isRewardShow">
|
||||
<div class="popup-box">
|
||||
<div class="popup-title">
|
||||
打赏
|
||||
<div class="close flex-center-center" @click="close">
|
||||
<SvgIcon name="payClose" height="24px" width="24px" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="subtitle">打赏金额</div>
|
||||
<van-field v-model="state.coins" type="number" placeholder="请输入价格">
|
||||
<template #left-icon>
|
||||
<span>¥</span>
|
||||
</template>
|
||||
</van-field>
|
||||
<div class="gold-coin">
|
||||
钱包余额 :
|
||||
<!-- <span>{{ userInfo.activeValue }}</span>-->
|
||||
<span>{{ (state.userWallet.amount * 100 + state.userWallet.income * 100) / 100 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="confirm" @click="confirm">打赏</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, reactive } from 'vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import CommunityApi from '@/service/community';
|
||||
import { showToast } from 'vant';
|
||||
import { stat } from 'fs';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const walletInfo = userStore.walletInfo;
|
||||
const userInfo = userStore.userInfo;
|
||||
|
||||
nextTick(() => {
|
||||
/**
|
||||
* 获取金币钱包信息
|
||||
*/
|
||||
state.userWallet = userStore.walletInfo;
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
userWallet: <Types.User.WalletInfo>{},
|
||||
isRewardShow: false,
|
||||
vid: '',
|
||||
coins: 0,
|
||||
});
|
||||
const close = () => {
|
||||
state.vid = '';
|
||||
state.coins = 0;
|
||||
state.isRewardShow = false;
|
||||
};
|
||||
const confirm = async () => {
|
||||
if (!Number(state.coins)) return showToast('请输入金额');
|
||||
if (Number(state.coins) * 10 > walletInfo.amount && walletInfo.amount == 0) return showToast('余额不足');
|
||||
try {
|
||||
let req = {
|
||||
vid: state.vid,
|
||||
coins: state.coins,
|
||||
};
|
||||
await CommunityApi.reward(req);
|
||||
showToast('打赏成功');
|
||||
close();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
const openPop = (vid: string) => {
|
||||
state.vid = vid;
|
||||
state.isRewardShow = true;
|
||||
};
|
||||
defineExpose({
|
||||
openPop,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.reward-popup {
|
||||
.popup-box {
|
||||
height: 237px;
|
||||
width: 261px;
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
padding: 0 5.5px;
|
||||
box-sizing: border-box;
|
||||
.popup-title {
|
||||
height: 48px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: $titleColor;
|
||||
letter-spacing: 0.36px;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid rgb(242, 242, 242);
|
||||
position: relative;
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 10px;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 18px 38px 0;
|
||||
.subtitle {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: $titleColor;
|
||||
letter-spacing: 0.28px;
|
||||
}
|
||||
:deep(.van-cell) {
|
||||
border: 1px solid rgb(226, 226, 226);
|
||||
border-radius: 4px;
|
||||
margin: 9px 0 17px;
|
||||
.van-field__left-icon {
|
||||
span {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
.gold-coin {
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.24px;
|
||||
color: $greyDeepColor;
|
||||
span {
|
||||
color: $themeColor;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
.confirm {
|
||||
height: 35px;
|
||||
width: 217px;
|
||||
background-color: $themeColor;
|
||||
border-radius: 4px;
|
||||
color: $greyLightColor;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
line-height: 35px;
|
||||
margin: 15px auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@/service/entertainment
|
||||
@@ -1,76 +0,0 @@
|
||||
<template>
|
||||
<div class="vertical-scoll">
|
||||
<vertical-scroll :list="list">
|
||||
<template v-slot="{ data }">
|
||||
<span style="width: 100%; display: block; line-height: 30px">
|
||||
<div>{{ data.name }}</div>
|
||||
</span>
|
||||
</template>
|
||||
</vertical-scroll>
|
||||
</div>
|
||||
<div class="horizonta-scoll">
|
||||
<horizontal-scroll :list="list" direction="left">
|
||||
<template v-slot="{ data }">
|
||||
<div class="vertical-text">
|
||||
{{ data.name }}
|
||||
</div>
|
||||
</template>
|
||||
</horizontal-scroll>
|
||||
</div>
|
||||
<div class="vertical-scoll">
|
||||
<vue3-seamless-scroll :list="list">
|
||||
<template v-slot="{ data }">
|
||||
<span style="width: 100%; display: block; line-height: 30px">
|
||||
<div>{{ data.name }}</div>
|
||||
</span>
|
||||
</template>
|
||||
</vue3-seamless-scroll>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { Vue3SeamlessScroll, VerticalScroll, HorizontalScroll } from 'vue3-seamless-scroll';
|
||||
|
||||
const listData = Array.from({ length: 10000 }, (_, i) => ({
|
||||
id: Date.now() + i + 1,
|
||||
name: `Vue3.0无缝滚动展示数据第${i + 1}条`,
|
||||
}));
|
||||
|
||||
export default defineComponent({
|
||||
name: 'App',
|
||||
components: {
|
||||
Vue3SeamlessScroll,
|
||||
VerticalScroll,
|
||||
HorizontalScroll,
|
||||
},
|
||||
setup() {
|
||||
const list = ref(listData);
|
||||
return {
|
||||
list,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.vertical-scoll {
|
||||
overflow: hidden;
|
||||
height: 300px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.horizonta-scoll {
|
||||
overflow: hidden;
|
||||
height: 300px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.vertical-text {
|
||||
height: 300px;
|
||||
writing-mode: vertical-lr;
|
||||
text-orientation: upright;
|
||||
line-height: 30px;
|
||||
display: inline-block;
|
||||
color: #000;
|
||||
}
|
||||
</style>
|
||||
@@ -1,107 +0,0 @@
|
||||
<template>
|
||||
<div class="selectionLinePopup">
|
||||
<!-- 选择路线弹窗 -->
|
||||
<van-popup class="selectionPopup" v-model:show="isOpenSelectionLine" position="bottom" @close="emits('close')">
|
||||
<div class="selectionLineBox">
|
||||
<div class="titleBox">
|
||||
选择播放线路
|
||||
<SvgIcon name="closeBlack" class="close" @click="emits('close')"></SvgIcon>
|
||||
</div>
|
||||
<div class="lineBox">
|
||||
<div
|
||||
class="line"
|
||||
:class="{ selectedLine: item.desc == globalStore.videoRoadLine.desc }"
|
||||
@click="selectLine(item)"
|
||||
v-for="item in state.roadLines"
|
||||
:key="item.desc"
|
||||
>
|
||||
{{ item.desc }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive } from 'vue';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
import { useGlobalStore } from '@/stores/global';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
const configStore = useConfigStore();
|
||||
const globalStore = useGlobalStore();
|
||||
const props = defineProps<{
|
||||
isOpen: boolean;
|
||||
}>();
|
||||
const emits = defineEmits(['close', 'closeSelectLine']);
|
||||
const isOpenSelectionLine = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
const state = reactive({
|
||||
roadLines: <any>configStore.sourceInfo.VID,
|
||||
});
|
||||
const selectLine = (item: any) => {
|
||||
globalStore.setVideoRoadLine(item);
|
||||
showToast('切换成功');
|
||||
emits('closeSelectLine');
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.van-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
:deep(.van-popup) {
|
||||
background-color: transparent;
|
||||
}
|
||||
.selectionLinePopup {
|
||||
.selectionPopup {
|
||||
.selectionLineBox {
|
||||
background: #fff url('./../../assets/images/png/selectLineBg.png') no-repeat;
|
||||
background-size: 150%;
|
||||
background-position-y: -20px;
|
||||
padding: 10px 14px;
|
||||
height: 300px;
|
||||
border-radius: 18px 18px 0 0;
|
||||
.titleBox {
|
||||
color: black;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
height: 50px;
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
border-bottom: 1px solid #f1f3f5;
|
||||
position: relative;
|
||||
.close {
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
}
|
||||
.lineBox {
|
||||
padding: 15px 0px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-column-gap: 20px;
|
||||
grid-row-gap: 14px;
|
||||
.line {
|
||||
height: 38px;
|
||||
width: 100px;
|
||||
text-align: center;
|
||||
line-height: 38px;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
color: #424242;
|
||||
background: #f1f3f5;
|
||||
}
|
||||
.selectedLine {
|
||||
color: white;
|
||||
background: rgb(255, 166, 65);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,132 +0,0 @@
|
||||
<template>
|
||||
<div class="sharePopup">
|
||||
<van-popup v-model:show="state.isRewardShow" :style="{ backgroundColor: 'rgba(0, 0, 0, 0)' }">
|
||||
<div class="popupBox">
|
||||
<LazyImg class="cover" :src="state.videoInfo?.cover" />
|
||||
<div class="bottom"></div>
|
||||
<SvgIcon name="title2" class="title" />
|
||||
<div class="qrcode">
|
||||
<qrcode-vue :value="state.qrCodeUrl" :size="90" level="L" />
|
||||
</div>
|
||||
<div class="desc">{{ state.videoInfo?.title }}</div>
|
||||
</div>
|
||||
<div class="btnBox flex-center-between">
|
||||
<div class="btn" @click="showToast('请手动截图保存')">保存图片</div>
|
||||
<div class="btn copyBtn" @click="copyLink">复制链接</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import { showToast } from 'vant';
|
||||
import QrcodeVue from 'qrcode.vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import useClipboard from 'vue-clipboard3';
|
||||
|
||||
const { toClipboard } = useClipboard();
|
||||
const userStore = useUserStore();
|
||||
const userInfo: any = userStore.userInfo;
|
||||
const props = defineProps<{
|
||||
videoInfo?: Types.Video.VInfosItem;
|
||||
}>();
|
||||
const state = reactive({
|
||||
isRewardShow: false,
|
||||
qrCodeUrl: userInfo.promoteURL,
|
||||
promotionCode: userInfo.promotionCode,
|
||||
videoInfo: props.videoInfo,
|
||||
});
|
||||
const openPop = () => {
|
||||
state.isRewardShow = true;
|
||||
};
|
||||
const copyLink = async () => {
|
||||
try {
|
||||
if (!state.qrCodeUrl) {
|
||||
showToast('复制失败');
|
||||
return;
|
||||
}
|
||||
await toClipboard(state.qrCodeUrl); //实现复制
|
||||
showToast('复制成功');
|
||||
} catch (e: any) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
defineExpose({
|
||||
openPop,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.sharePopup {
|
||||
background-color: rgba(255,255,255);
|
||||
.popupBox {
|
||||
background: rgba(255,255,255);
|
||||
border-radius: 6px;
|
||||
height: 271px;
|
||||
width: 301px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
.cover {
|
||||
height: 191px;
|
||||
width: 100%;
|
||||
}
|
||||
.bottom {
|
||||
height: 109px;
|
||||
width: 100%;
|
||||
}
|
||||
.title {
|
||||
height: 35px;
|
||||
width: 124.6px;
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 15px;
|
||||
}
|
||||
.qrcode {
|
||||
height: 90px;
|
||||
width: 90px;
|
||||
position: absolute;
|
||||
left: 19px;
|
||||
top: 147px;
|
||||
border-radius: 6px;
|
||||
// background: rgba(238,118,47);
|
||||
// padding:0 5px 3px 0;
|
||||
}
|
||||
.desc {
|
||||
position: absolute;
|
||||
right: 17.3px;
|
||||
bottom: 29px;
|
||||
width: 157px;
|
||||
height: 37px;
|
||||
color: rgba(38, 38, 38);
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
.btnBox {
|
||||
margin: 23px auto;
|
||||
.btn {
|
||||
height: 48px;
|
||||
width: 144px;
|
||||
border-radius: 24px;
|
||||
text-align: center;
|
||||
line-height: 48px;
|
||||
background-color: white;
|
||||
}
|
||||
.copyBtn {
|
||||
color: white;
|
||||
background-color: $themeColor;
|
||||
}
|
||||
}
|
||||
:deep(.van-popup) {
|
||||
border-radius: 8px;
|
||||
}
|
||||
:deep(.van-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,146 +0,0 @@
|
||||
<template>
|
||||
<div class="vertical_video_warp">
|
||||
<div id="video">
|
||||
<div class="avoid_sliding" @click="pause"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onBeforeUnmount, onMounted } from 'vue';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import HlsJSPlayer from 'xgplayer-hls.js';
|
||||
|
||||
const props = defineProps<{
|
||||
sourceURL: string;
|
||||
}>();
|
||||
let player: any = null; //播放器实例
|
||||
onMounted(() => {
|
||||
//初始化播放器
|
||||
initVideo();
|
||||
});
|
||||
/**
|
||||
* @description 暂停
|
||||
*/
|
||||
const pause = () => {
|
||||
player.pause();
|
||||
};
|
||||
/**
|
||||
* @description 初始化播放器
|
||||
*/
|
||||
const initVideo = () => {
|
||||
player = new HlsJSPlayer({
|
||||
id: 'video',
|
||||
url: getPath(),
|
||||
fluid: true,
|
||||
playsinline: true,
|
||||
videoInit: true,
|
||||
loop: true,
|
||||
autoplay: true,
|
||||
controls: true,
|
||||
lang: 'zh-cn',
|
||||
ignores: ['i18n', 'play', 'volume', 'definition'],
|
||||
allowPlayAfterEnded: true,
|
||||
allowSeekAfterEnded: true,
|
||||
closeVideoPreventDefault: true,
|
||||
closeVideoStopPropagation: true,
|
||||
closeInactive: true,
|
||||
enableVideoDbltouch: true,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description 获取播放链接
|
||||
*/
|
||||
const getPath = () => {
|
||||
const { baseUrl } = useConfigStore();
|
||||
return `${baseUrl}/api/app/vid/h5/m3u8/${props.sourceURL}?token=${getToken()}`;
|
||||
};
|
||||
/**
|
||||
* @description 获取token
|
||||
*/
|
||||
const getToken = () => {
|
||||
const { token } = useUserStore();
|
||||
return token;
|
||||
};
|
||||
onBeforeUnmount(() => {
|
||||
if (player) {
|
||||
player.src = '';
|
||||
player.destroy(true);
|
||||
}
|
||||
player = null;
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.vertical_video_warp {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
background: #000000;
|
||||
align-items: center;
|
||||
:deep(.xgplayer-progress-played) {
|
||||
background: rgb(39, 213, 236);
|
||||
}
|
||||
:deep(.xgplayer-progress) {
|
||||
top: 10px;
|
||||
}
|
||||
:deep(.xgplayer-start),
|
||||
:deep(.xgplayer-controls) {
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
}
|
||||
:deep(.xgplayer-progress-btn) {
|
||||
display: none !important;
|
||||
}
|
||||
:deep(.xgplayer-time-current:after) {
|
||||
content: ' ';
|
||||
}
|
||||
:deep(.xgplayer-progress) {
|
||||
left: 43%;
|
||||
right: 0;
|
||||
width: 60%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
:deep(.xgplayer-time) {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
// margin-top: 10px;
|
||||
font-size: 11px;
|
||||
}
|
||||
:deep(.xgplayer-time-current)::after {
|
||||
display: none;
|
||||
}
|
||||
// :deep(.xgplayer-icon-play) {
|
||||
// > svg {
|
||||
// height: 40px;
|
||||
// width: 40px;
|
||||
// }
|
||||
// }
|
||||
// :deep(.xgplayer-skin-default .xgplayer-start) {
|
||||
// height: 40px;
|
||||
// width: 40px;
|
||||
// margin: -20px;
|
||||
// }
|
||||
#video {
|
||||
width: 100%;
|
||||
height: 100% !important;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: relative;
|
||||
:deep(.xgplayer-enter-spinner) {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
.avoid_sliding {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,146 +0,0 @@
|
||||
<template>
|
||||
<div class="tab_wrapper">
|
||||
<van-tabbar
|
||||
v-model="activeName"
|
||||
:safe-area-inset-bottom="true"
|
||||
:border="false"
|
||||
active-color="rgb(255, 173, 0)"
|
||||
inactive-color="rgb(220, 220, 220)"
|
||||
>
|
||||
<van-tabbar-item to="/frontPage" name="frontPage" replace>
|
||||
<span>导航</span>
|
||||
<template #icon="props">
|
||||
<!-- <div :class="props.active ? 'isActive' : 'unActive'"></div> -->
|
||||
<img :src="props.active ? homeIconActive : homeIconUnActive" replace />
|
||||
</template>
|
||||
</van-tabbar-item>
|
||||
<van-tabbar-item to="/home" name="home" replace>
|
||||
<span>视频</span>
|
||||
<template #icon="props">
|
||||
<!-- <div :class="props.active ? 'isActive' : 'unActive'"></div> -->
|
||||
<img :src="props.active ? shortVideoIconActive : shortVideoIconUnActive" />
|
||||
</template>
|
||||
</van-tabbar-item>
|
||||
<!-- <van-tabbar-item to="/blackMaterial" name="blackMaterial" v-if="configStore?.appConfig?.hlH5">-->
|
||||
<!-- <span>会员</span>-->
|
||||
<!-- <template #icon="props">-->
|
||||
<!-- <img :src="props.active ? blackMaterialActive : blackMaterialUnActive" replace />-->
|
||||
<!-- </template>-->
|
||||
<!-- </van-tabbar-item>-->
|
||||
<van-tabbar-item to="/community" name="community" v-if="state.isCommunityShow">
|
||||
<span>社区</span>
|
||||
<template #icon="props">
|
||||
<img :src="props.active ? communityActive : communityUnActive" replace />
|
||||
</template>
|
||||
</van-tabbar-item>
|
||||
<van-tabbar-item to="/blackMaterial" name="blackMaterial">
|
||||
<span>ACG</span>
|
||||
<template #icon="props">
|
||||
<!-- <div :class="props.active ? 'isActive' : 'unActive'"></div> -->
|
||||
<img :src="props.active ? blackMaterialActive : blackMaterialUnActive" replace />
|
||||
</template>
|
||||
</van-tabbar-item>
|
||||
<van-tabbar-item to="/mine" name="mine">
|
||||
<span>我的</span>
|
||||
<template #icon="props">
|
||||
<!-- <div :class="props.active ? 'isActive' : 'unActive'"></div> -->
|
||||
<img :src="props.active ? mineIconActive : mineIconUnActive" replace />
|
||||
</template>
|
||||
</van-tabbar-item>
|
||||
</van-tabbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {nextTick, onMounted, reactive, ref, watch} from 'vue';
|
||||
import homeIconActive from '@/assets/images/png/homeIconActive.png';
|
||||
import homeIconUnActive from '@/assets/images/png/homeIconUnActive.png';
|
||||
import shortVideoIconActive from '@/assets/images/png/shortVideoIconActive.png';
|
||||
import shortVideoIconUnActive from '@/assets/images/png/shortVideoIconUnActive.png';
|
||||
import blackMaterialActive from '@/assets/images/png/blackMaterialActive.png';
|
||||
import blackMaterialUnActive from '@/assets/images/png/blackMaterialUnActive.png';
|
||||
import loufengIconActive from '@/assets/images/png/loufengIconActive.png';
|
||||
import loufengIconUnActive from '@/assets/images/png/loufengIconUnActive.png';
|
||||
import mineIconActive from '@/assets/images/png/mineIconActive.png';
|
||||
import mineIconUnActive from '@/assets/images/png/mineIconUnActive.png';
|
||||
import communityUnActive from '@/assets/images/png/communityUnActive.png';
|
||||
import communityActive from '@/assets/images/png/communityActive.png';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
import {useGlobalStore} from "@/stores/global";
|
||||
|
||||
const configStore: any = useConfigStore();
|
||||
const route = useRoute();
|
||||
const activeName = ref('home');
|
||||
const globalStore = useGlobalStore();
|
||||
|
||||
const state = reactive({
|
||||
isCommunityShow: false,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
refreshRoute(route.name);
|
||||
|
||||
let tabObj: any = globalStore.tabObj;
|
||||
if (tabObj.community) {
|
||||
if(tabObj.community){
|
||||
state.isCommunityShow = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const refreshRoute = (name: any) => {
|
||||
activeName.value = name;
|
||||
};
|
||||
|
||||
watch(route, (newVal) => {
|
||||
refreshRoute(newVal.name);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.van-tabbar) {
|
||||
padding-bottom: $TabPaddingBottom;
|
||||
background: rgb(0, 0, 0);
|
||||
z-index: 3;
|
||||
//border-top: 1px solid rgb(75, 75, 75);
|
||||
}
|
||||
// :deep(.van-tabbar-item__icon) {
|
||||
// width: 32px;
|
||||
// height: 75px;
|
||||
// img {
|
||||
// height: 22px;
|
||||
// width: 23px;
|
||||
// position: absolute;
|
||||
// left: 50%;
|
||||
// transform: translate(-50%, 50%);
|
||||
// }
|
||||
// .unActive {
|
||||
// width: 50px;
|
||||
// left: -20%;
|
||||
// top: 1px;
|
||||
// height: 2px;
|
||||
// background-image: linear-gradient(to right, rgb(255, 255, 255), rgb(255, 255, 255), rgb(255, 255, 255));
|
||||
// }
|
||||
// }
|
||||
:deep(.van-tabbar-item__text) {
|
||||
span {
|
||||
display: block;
|
||||
// margin-top: 35px;
|
||||
}
|
||||
}
|
||||
:deep(.van-tabbar-item--active) {
|
||||
background-color: unset;
|
||||
.isActive {
|
||||
width: 50px;
|
||||
left: -20%;
|
||||
top: 1px;
|
||||
height: 2px;
|
||||
background-image: linear-gradient(to right, rgb(255, 255, 255), rgb(255, 131, 0), rgb(255, 255, 255));
|
||||
}
|
||||
}
|
||||
.blackMaterial {
|
||||
height: 62px !important;
|
||||
width: 62px !important;
|
||||
top: -65%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,211 +0,0 @@
|
||||
<template>
|
||||
<div ref="textOverflow" class="text-overflow" :style="boxStyle">
|
||||
<!-- <span ref="overEllipsis" class="overEllipsis">{{ realText }}</span> -->
|
||||
<span v-if="isTopping" class="topping">置顶</span>
|
||||
<span ref="overEllipsis" class="overEllipsis" v-html="rearrangeText(realText)"></span>
|
||||
<span class="slot-box" ref="slotRef" v-if="state.showSlotNode">
|
||||
<slot :click-toggle="toggle" :expanded="state.expanded"></slot>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
import { ref, reactive, computed, nextTick, onMounted, onUpdated, onActivated } from 'vue';
|
||||
const props = defineProps({
|
||||
text: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
maxLines: {
|
||||
type: Number,
|
||||
default: 3,
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
isTopping: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const overEllipsis = ref<HTMLElement>();
|
||||
const slotRef = ref<HTMLElement>();
|
||||
const textOverflow = ref<HTMLElement>();
|
||||
const state = reactive({
|
||||
offset: props.text.length,
|
||||
expanded: false,
|
||||
slotBoxWidth: 0,
|
||||
textBoxWidth: props.width,
|
||||
showSlotNode: false,
|
||||
isTopping: props.isTopping,
|
||||
});
|
||||
const boxStyle = computed(() => {
|
||||
if (props.width) {
|
||||
return {
|
||||
width: props.width + 'px',
|
||||
};
|
||||
}
|
||||
return '0px';
|
||||
});
|
||||
const realText = computed(() => {
|
||||
// 是否被截取
|
||||
const isCutOut = state.offset !== props.text.length;
|
||||
let realText = props.text;
|
||||
if (isCutOut && !state.expanded) {
|
||||
realText = props.text.slice(0, state.offset) + '...';
|
||||
}
|
||||
return realText;
|
||||
});
|
||||
const calculateOffset = (from: number, to: number) => {
|
||||
nextTick(() => {
|
||||
if (Math.abs(from - to) <= 1) return;
|
||||
if (isOverflow()) {
|
||||
to = state.offset;
|
||||
} else {
|
||||
from = state.offset;
|
||||
}
|
||||
state.offset = Math.floor((from + to) / 2);
|
||||
calculateOffset(from, to);
|
||||
});
|
||||
};
|
||||
const isOverflow = () => {
|
||||
const { len, lastWidth } = getLines();
|
||||
if (len < props.maxLines) {
|
||||
return false;
|
||||
}
|
||||
if (props.maxLines) {
|
||||
// 超出部分 行数 > 最大行数 或则 已经是最大行数但最后一行宽度 + 后面内容超出正常宽度
|
||||
const lastLineOver = !!(len === props.maxLines && lastWidth + state.slotBoxWidth > state.textBoxWidth);
|
||||
if (len > props.maxLines || lastLineOver) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const getLines = () => {
|
||||
const clientRects: any = overEllipsis.value?.getClientRects();
|
||||
return {
|
||||
len: clientRects.length,
|
||||
lastWidth: clientRects[clientRects.length - 1]?.width,
|
||||
};
|
||||
};
|
||||
const toggle = () => {
|
||||
state.expanded = !state.expanded;
|
||||
};
|
||||
const rearrangeText = (text: any) => {
|
||||
let originalText = '';
|
||||
if (props.text && props.text.indexOf('##') != -1) {
|
||||
let startIndex = props.text.indexOf('{');
|
||||
let endIndex = props.text.indexOf('}');
|
||||
let jsonText = props.text.substring(startIndex, endIndex + 1);
|
||||
let jsonObj = JSON.parse(jsonText);
|
||||
let texts = '##' + jsonText + '##';
|
||||
originalText = text.replace(
|
||||
texts,
|
||||
`<div onclick="jumpKeywords('${jsonObj.type}', '${jsonObj.id}')" style='color:rgb(162,203,240);display: inline-block;'>${jsonObj.txt}<div style="height: 9px;width: 9px;display: inline-block;margin-bottom: 3px;background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAYCAMAAADJYP15AAAAOVBMVEVHcEyh0fuh0fyi0f2h0fyg0Pyf1f+f0/yfz/+h0fyfz/+h0Pyg0Pyh0fyf0vyi0vyh0fyh0fyg0fw8+yy6AAAAEXRSTlMAkLBwgPAwPxDGIODfoFBgXzlWcyEAAAC6SURBVCjPbZDbEsMgCEQNarxU027+/2MLFQ3pZF9kduQA65wof7aCRmF3VqlB1fMy84ZLLU1b3JdPrh6dq6igxDVpb3oBZSCYSwtYIxCkeDPhmuM8Y5Ts7VaMqfwUIFmbgIMfHni7IQy4Njmzrr+alhTKTd24WaE7bjNp3sMXt2oGYlyfeWgcq2c6zzPMWKMkR4Ejx/os+GKSXREKMg6rSGcxEdUjeFloj3OVuzhRbA++/09J1R9///QF6MAK320wOcMAAAAASUVORK5CYII=');background-size: 100% 100%;"></div></div>`,
|
||||
);
|
||||
return originalText;
|
||||
}
|
||||
return text;
|
||||
};
|
||||
function jumpKeywords(type: any, id: any) {
|
||||
window.event.stopPropagation();
|
||||
let item = {
|
||||
href: '',
|
||||
};
|
||||
switch (type) {
|
||||
case '1':
|
||||
item.href = 'yinseinner://memberCentre';
|
||||
break;
|
||||
case '2':
|
||||
item.href = 'yinseinner://sharePromote';
|
||||
break;
|
||||
case '3':
|
||||
item.href = 'yinseinner://incomeCenter';
|
||||
break;
|
||||
case '4':
|
||||
item.href = 'yinseinner://taskHall';
|
||||
break;
|
||||
case '5':
|
||||
item.href = `yinseinner://taskDetails?id=${id}`;
|
||||
break;
|
||||
case '6':
|
||||
item.href = 'yinseinner://wishList';
|
||||
break;
|
||||
case '7':
|
||||
item.href = 'yinseinner://creationCenter';
|
||||
break;
|
||||
case '8':
|
||||
item.href = 'yinseinner://myCertification';
|
||||
break;
|
||||
case '9':
|
||||
item.href = 'yinseinner://announcement';
|
||||
break;
|
||||
case '10':
|
||||
item.href = 'yinseinner://kefu';
|
||||
break;
|
||||
case '11':
|
||||
item.href = `yinseinner://horizontalVideo?id=${id}`;
|
||||
break;
|
||||
case '12':
|
||||
item.href = `yinseinner://userHomePage?uid=${id}`;
|
||||
break;
|
||||
case '13':
|
||||
item.href = 'yinseinner://gameWallet';
|
||||
break;
|
||||
// case '14':
|
||||
// case '15':
|
||||
// item.href = `yinseinner://postDetails?id=${id}`;
|
||||
// break;
|
||||
}
|
||||
jumpAdv(item);
|
||||
}
|
||||
onMounted(() => {
|
||||
window.jumpKeywords = jumpKeywords;
|
||||
const { len } = getLines();
|
||||
if (len > props.maxLines) {
|
||||
state.showSlotNode = true;
|
||||
nextTick(() => {
|
||||
state.slotBoxWidth = <number>slotRef.value?.clientWidth;
|
||||
state.textBoxWidth = <number>textOverflow.value?.clientWidth;
|
||||
calculateOffset(0, props.text.length);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.slot-box {
|
||||
display: inline-block;
|
||||
color: #246bfd;
|
||||
}
|
||||
.overEllipsis {
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
// color: $greyDeepColor;
|
||||
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.choosen {
|
||||
font-size: 12px;
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(to right, rgb(132, 164, 249), rgb(43, 93, 222));
|
||||
display: inline-block;
|
||||
margin: 0 5px 0 0;
|
||||
}
|
||||
|
||||
.topping {
|
||||
font-size: 12px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
color: #1A1A1A;
|
||||
background: #F1A100;
|
||||
display: inline-block;
|
||||
margin: 0 5px 0 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,202 +0,0 @@
|
||||
<template>
|
||||
<div ref="textOverflow" class="text-overflow" :style="boxStyle">
|
||||
<span ref="overEllipsis" class="overEllipsis" v-html="rearrangeText(realText)"></span>
|
||||
<span class="slot-box" ref="slotRef" v-if="state.showSlotNode">
|
||||
<slot :click-toggle="toggle" :expanded="state.expanded"></slot>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
import { ref, reactive, computed, nextTick, onMounted, onUpdated, onActivated } from 'vue';
|
||||
const props = defineProps({
|
||||
text: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
maxLines: {
|
||||
type: Number,
|
||||
default: 3,
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
isChoosen: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const overEllipsis = ref<HTMLElement>();
|
||||
const slotRef = ref<HTMLElement>();
|
||||
const textOverflow = ref<HTMLElement>();
|
||||
const state = reactive({
|
||||
offset: props.text.length,
|
||||
expanded: true,
|
||||
slotBoxWidth: 0,
|
||||
textBoxWidth: props.width,
|
||||
showSlotNode: false,
|
||||
isChoosen: props.isChoosen,
|
||||
});
|
||||
const boxStyle = computed(() => {
|
||||
if (props.width) {
|
||||
return {
|
||||
width: props.width + 'px',
|
||||
};
|
||||
}
|
||||
return '0px';
|
||||
});
|
||||
const realText = computed(() => {
|
||||
// 是否被截取
|
||||
const isCutOut = state.offset !== props.text.length;
|
||||
let realText = props.text;
|
||||
if (isCutOut && !state.expanded) {
|
||||
realText = props.text.slice(0, state.offset) + '...';
|
||||
}
|
||||
return realText;
|
||||
});
|
||||
const calculateOffset = (from: number, to: number) => {
|
||||
nextTick(() => {
|
||||
if (Math.abs(from - to) <= 1) return;
|
||||
if (isOverflow()) {
|
||||
to = state.offset;
|
||||
} else {
|
||||
from = state.offset;
|
||||
}
|
||||
state.offset = Math.floor((from + to) / 2);
|
||||
calculateOffset(from, to);
|
||||
});
|
||||
};
|
||||
const isOverflow = () => {
|
||||
const { len, lastWidth } = getLines();
|
||||
if (len < props.maxLines) {
|
||||
return false;
|
||||
}
|
||||
if (props.maxLines) {
|
||||
// 超出部分 行数 > 最大行数 或则 已经是最大行数但最后一行宽度 + 后面内容超出正常宽度
|
||||
const lastLineOver = !!(len === props.maxLines && lastWidth + state.slotBoxWidth > state.textBoxWidth);
|
||||
if (len > props.maxLines || lastLineOver) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const getLines = () => {
|
||||
const clientRects: any = overEllipsis.value?.getClientRects();
|
||||
return {
|
||||
len: clientRects.length,
|
||||
lastWidth: clientRects[clientRects.length - 1]?.width,
|
||||
};
|
||||
};
|
||||
const toggle = () => {
|
||||
state.expanded = !state.expanded;
|
||||
if (!state.expanded) {
|
||||
calculateOffset(0, props.text.length);
|
||||
}
|
||||
};
|
||||
const rearrangeText = (text: any) => {
|
||||
let originalText = '';
|
||||
if (props.text && props.text.indexOf('##') != -1) {
|
||||
let startIndex = props.text.indexOf('{');
|
||||
let endIndex = props.text.indexOf('}');
|
||||
let jsonText = props.text.substring(startIndex, endIndex + 1);
|
||||
let jsonObj = JSON.parse(jsonText);
|
||||
let texts = '##' + jsonText + '##';
|
||||
originalText = text.replace(
|
||||
texts,
|
||||
`<div onclick="jumpKeywords('${jsonObj.type}', '${jsonObj.id}')" style='color:rgb(162,203,240);display: inline-block;'>${jsonObj.txt}<div style="height: 9px;width: 9px;display: inline-block;margin-bottom: 3px;background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAYCAMAAADJYP15AAAAOVBMVEVHcEyh0fuh0fyi0f2h0fyg0Pyf1f+f0/yfz/+h0fyfz/+h0Pyg0Pyh0fyf0vyi0vyh0fyh0fyg0fw8+yy6AAAAEXRSTlMAkLBwgPAwPxDGIODfoFBgXzlWcyEAAAC6SURBVCjPbZDbEsMgCEQNarxU027+/2MLFQ3pZF9kduQA65wof7aCRmF3VqlB1fMy84ZLLU1b3JdPrh6dq6igxDVpb3oBZSCYSwtYIxCkeDPhmuM8Y5Ts7VaMqfwUIFmbgIMfHni7IQy4Njmzrr+alhTKTd24WaE7bjNp3sMXt2oGYlyfeWgcq2c6zzPMWKMkR4Ejx/os+GKSXREKMg6rSGcxEdUjeFloj3OVuzhRbA++/09J1R9///QF6MAK320wOcMAAAAASUVORK5CYII=');background-size: 100% 100%;"></div></div>`,
|
||||
);
|
||||
return originalText;
|
||||
}
|
||||
return text;
|
||||
};
|
||||
function jumpKeywords(type: any, id: any) {
|
||||
window.event.stopPropagation();
|
||||
let item = {
|
||||
href: '',
|
||||
};
|
||||
switch (type) {
|
||||
case '1':
|
||||
item.href = 'yinseinner://memberCentre';
|
||||
break;
|
||||
case '2':
|
||||
item.href = 'yinseinner://sharePromote';
|
||||
break;
|
||||
case '3':
|
||||
item.href = 'yinseinner://incomeCenter';
|
||||
break;
|
||||
case '4':
|
||||
item.href = 'yinseinner://taskHall';
|
||||
break;
|
||||
case '5':
|
||||
item.href = `yinseinner://taskDetails?id=${id}`;
|
||||
break;
|
||||
case '6':
|
||||
item.href = 'yinseinner://wishList';
|
||||
break;
|
||||
case '7':
|
||||
item.href = 'yinseinner://creationCenter';
|
||||
break;
|
||||
case '8':
|
||||
item.href = 'yinseinner://myCertification';
|
||||
break;
|
||||
case '9':
|
||||
item.href = 'yinseinner://announcement';
|
||||
break;
|
||||
case '10':
|
||||
item.href = 'yinseinner://kefu';
|
||||
break;
|
||||
case '11':
|
||||
item.href = `yinseinner://horizontalVideo?id=${id}`;
|
||||
break;
|
||||
case '12':
|
||||
item.href = `yinseinner://userHomePage?uid=${id}`;
|
||||
break;
|
||||
case '13':
|
||||
item.href = 'yinseinner://gameWallet';
|
||||
break;
|
||||
// case '14':
|
||||
// case '15':
|
||||
// item.href = `yinseinner://postDetails?id=${id}`;
|
||||
// break;
|
||||
}
|
||||
jumpAdvs(item);
|
||||
}
|
||||
onMounted(() => {
|
||||
window.jumpKeywords = jumpKeywords;
|
||||
const { len } = getLines();
|
||||
console.log(len, props.maxLines);
|
||||
if (len > props.maxLines) {
|
||||
console.log(state.expanded);
|
||||
state.showSlotNode = true;
|
||||
nextTick(() => {
|
||||
state.slotBoxWidth = <number>slotRef.value?.clientWidth;
|
||||
state.textBoxWidth = <number>textOverflow.value?.clientWidth;
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.slot-box {
|
||||
display: inline-block;
|
||||
color: rgba(62, 100, 234);
|
||||
}
|
||||
.overEllipsis {
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
// color: $greyDeepColor;
|
||||
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.choosen {
|
||||
font-size: 12px;
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(to right, rgb(132, 164, 249), rgb(43, 93, 222));
|
||||
display: inline-block;
|
||||
margin: 0 5px 0 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,238 +0,0 @@
|
||||
<template>
|
||||
<div class="upload-img" @click.stop>
|
||||
<van-uploader
|
||||
v-model="state.fileList"
|
||||
:after-read="afterRead"
|
||||
@delete="delImg"
|
||||
:multiple="multiple"
|
||||
:before-read="beforeRead"
|
||||
:max-count="maxCount"
|
||||
>
|
||||
<div class="addBox">
|
||||
<slot>
|
||||
<div class="upload-text" v-if="props.isCover">
|
||||
<!-- <SvgIcon name="upload_add" height="15px" width="15px"></SvgIcon>-->
|
||||
<img class="icon" src="@/assets/images/png/upload_add.png" alt="" />
|
||||
<span>添加图片</span>
|
||||
</div>
|
||||
<div class="upload-text" v-else>
|
||||
<img class="icon" src="@/assets/images/png/upload_add.png" alt="" />
|
||||
<!-- <SvgIcon name="upload_add" height="18px" width="18px"></SvgIcon>-->
|
||||
</div>
|
||||
</slot>
|
||||
</div>
|
||||
</van-uploader>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import AppApi from '@/service/app';
|
||||
import { showToast } from 'vant';
|
||||
import { reactive } from 'vue';
|
||||
const props = defineProps({
|
||||
maxCount: {
|
||||
type: String,
|
||||
default: '99',
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isCover: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['uploadSuccess', 'delImg']);
|
||||
const state = reactive({
|
||||
fileList: [],
|
||||
maxSize: 1024 * 1024 * 10,
|
||||
});
|
||||
const beforeRead = (file: any) => {
|
||||
if (file.length > props.maxCount) {
|
||||
showToast(`一次最多上传${props.maxCount}张图`);
|
||||
return false;
|
||||
}
|
||||
if (file.length) {
|
||||
file.map(async (item: any) => {
|
||||
if (item.size > state.maxSize) {
|
||||
showToast('单个图片最大为10M');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (file.size > state.maxSize) {
|
||||
showToast('单个图片最大为10M');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// 图片上传
|
||||
const afterRead = async (file: any) => {
|
||||
if (file.length) {
|
||||
file.map(async (item: any) => {
|
||||
let newFile = await compress(item.file);
|
||||
item.file = newFile;
|
||||
await uploadImg(item);
|
||||
});
|
||||
} else {
|
||||
let newFile = await compress(file.file);
|
||||
file.file = newFile;
|
||||
uploadImg(file);
|
||||
}
|
||||
};
|
||||
//图片上传
|
||||
const uploadImg = async (fileInfo: any) => {
|
||||
let req = new FormData();
|
||||
req.append('upload', fileInfo.file);
|
||||
fileInfo.status = 'uploading';
|
||||
fileInfo.message = '上传中...';
|
||||
try {
|
||||
let ret: any = await AppApi.uploadFile(req);
|
||||
fileInfo.status = 'done';
|
||||
fileInfo.message = '上传成功';
|
||||
emit('uploadSuccess', ret.coverImg);
|
||||
} catch (e) {
|
||||
fileInfo.status = 'failed';
|
||||
fileInfo.message = '上传失败';
|
||||
}
|
||||
};
|
||||
//将base64转换为文件对象
|
||||
const convertBase64ToBlob = (base64: any) => {
|
||||
var base64Arr = base64.split(',');
|
||||
var imgtype = '';
|
||||
var base64String = '';
|
||||
if (base64Arr.length > 1) {
|
||||
//如果是图片base64,去掉头信息
|
||||
base64String = base64Arr[1];
|
||||
imgtype = base64Arr[0].substring(base64Arr[0].indexOf(':') + 1, base64Arr[0].indexOf(';'));
|
||||
}
|
||||
// 将base64解码
|
||||
var bytes = atob(base64String);
|
||||
//var bytes = base64;
|
||||
var bytesCode = new ArrayBuffer(bytes.length);
|
||||
// 转换为类型化数组
|
||||
var byteArray = new Uint8Array(bytesCode);
|
||||
|
||||
// 将base64转换为ascii码
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
byteArray[i] = bytes.charCodeAt(i);
|
||||
}
|
||||
// 生成Blob对象(文件对象)
|
||||
return new Blob([bytesCode], { type: imgtype });
|
||||
};
|
||||
// 压缩图片
|
||||
const compress = (file: any) => {
|
||||
if (!file || !window.FileReader) return;
|
||||
if (/^image/.test(file.type)) {
|
||||
let reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
return new Promise((resolve) => {
|
||||
reader.onloadend = function () {
|
||||
let result: any = reader.result;
|
||||
let img: any = new Image();
|
||||
img.src = result;
|
||||
if (result.length <= 200 * 1024) {
|
||||
let blob = convertBase64ToBlob(result);
|
||||
let files = new File([blob], file.name, { type: blob.type });
|
||||
resolve(files);
|
||||
return;
|
||||
}
|
||||
img.onload = function () {
|
||||
let canvas = document.createElement('canvas');
|
||||
let ctx: any = canvas.getContext('2d');
|
||||
let width = img.width;
|
||||
let height = img.height;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
// 铺底色
|
||||
ctx.fillStyle = '#fff';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
//进行最小压缩
|
||||
let ndata = canvas.toDataURL('image/jpeg', 0.3);
|
||||
let blob = convertBase64ToBlob(ndata);
|
||||
let files = new File([blob], file.name, { type: blob.type });
|
||||
resolve(files);
|
||||
};
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
// 删除回调
|
||||
const delImg = (_file: any, detail: any) => {
|
||||
emit('delImg', detail.index);
|
||||
};
|
||||
// 清理图片列表
|
||||
const clearImg = () => {
|
||||
state.fileList = [];
|
||||
};
|
||||
defineExpose({
|
||||
clearImg,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.upload-img {
|
||||
.addBox {
|
||||
width: 111px;
|
||||
height: 111px;
|
||||
border-radius: 8px;
|
||||
border: dashed 1px #4D4D4D;
|
||||
background: #262626;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
.upload-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
span {
|
||||
font-size: 12px;
|
||||
color: #9a9a9a;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
margin: 0 2px 0 0;
|
||||
}
|
||||
|
||||
:deep(.van-uploader__preview-delete) {
|
||||
border-radius: 50%;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #ffffff;
|
||||
.van-uploader__preview-delete-icon {
|
||||
top: 0;
|
||||
right: 0;
|
||||
transform: scale(0.7);
|
||||
}
|
||||
}
|
||||
:deep(.van-uploader__mask) {
|
||||
border-radius: 6px;
|
||||
}
|
||||
:deep(.van-uploader__preview) {
|
||||
width: 111px;
|
||||
height: 111px;
|
||||
border-radius: 6px;
|
||||
margin: 0 3px 3px 0;
|
||||
}
|
||||
:deep(.van-image) {
|
||||
width: 111px;
|
||||
height: 111px;
|
||||
border-radius: 6px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,347 +0,0 @@
|
||||
<template>
|
||||
<div class="upload-video" @click.stop>
|
||||
<van-uploader accept="video/*" :max-count="1" :after-read="afterVideo" v-if="!state.startUploadVideo">
|
||||
<div class="upload-box">
|
||||
<!-- <SvgIcon name="upload_add" height="15px" width="15px"></SvgIcon>-->
|
||||
<img class="icon" src="@/assets/images/png/upload_add.png" alt="" />
|
||||
<span>添加视频</span>
|
||||
</div>
|
||||
</van-uploader>
|
||||
<!-- 上传中样式 -->
|
||||
<div v-if="state.startUploadVideo" class="uploading">
|
||||
<video class="previewVideo" id="video" style="object-fit: cover"></video>
|
||||
<div class="video-mask"></div>
|
||||
<van-circle
|
||||
v-model:current-rate="state.currentRate"
|
||||
:rate="state.uploadStatue.percent"
|
||||
:speed="100"
|
||||
color="#00b95b"
|
||||
:text="state.currentRate + '%'"
|
||||
size="50px"
|
||||
class="circle"
|
||||
/>
|
||||
<p :class="state.uploadStatue.statusText == '上传成功' ? 'green' : 'F5164E'">
|
||||
{{ state.uploadStatue.statusText }}
|
||||
</p>
|
||||
<div
|
||||
class="close"
|
||||
v-if="state.uploadStatue.statusText == '上传成功' || state.uploadStatue.statusText == '上传失败'"
|
||||
@click="uploadDelete"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import SparkMD5 from 'spark-md5';
|
||||
import { Buffer } from 'buffer';
|
||||
import { reactive, nextTick } from 'vue';
|
||||
import CommunityApi from '@/service/community';
|
||||
|
||||
const state = reactive({
|
||||
requestAll: <any>[], //总请求
|
||||
requestNum: 0, //正在请求的数量
|
||||
requestMaxNum: 6, //同时最大请求数量
|
||||
chunk_size: 1024 * 1024 * 2, //分片大小
|
||||
startUploadVideo: false, //视频是否上传中
|
||||
currentRate: 0,
|
||||
uploadStatue: {
|
||||
statusText: '上传中,请勿退出',
|
||||
percent: 0, //当前上传文件执行的百分比
|
||||
},
|
||||
totalProgress: <any>{}, //总进度
|
||||
sendVideoSucNum: 0, //分片上传视频,成功收到的返回
|
||||
videoHeight: 0,
|
||||
uploadData: {
|
||||
newsType: 'SP', //上传类型 COVER-图集 SP-视频
|
||||
tags: [], //视频标签数组
|
||||
playTime: 0, //视频时长
|
||||
cover: '', //封面
|
||||
coverThumb: '', //封面小图
|
||||
seriesCover: [], // 图集图片地址
|
||||
via: '', //视频来源
|
||||
coins: 0, //观看金币
|
||||
size: 0, //文件大小
|
||||
mimeType: '', //文件类型
|
||||
actor: '', //演员名字
|
||||
sourceURL: '', //资源url 为SP时 必传
|
||||
sourceID: '', //上��视频成功后 返回���ID 为SP时必传
|
||||
filename: '', //文件名
|
||||
resolution: '', //分辨率
|
||||
ratio: 1, //视频比例
|
||||
md5: '', //文件摘要
|
||||
freeTime: 0, //免费观影时长
|
||||
location: {
|
||||
city: '',
|
||||
}, //地理位置信息
|
||||
isActivity: false, //是否参加大赛
|
||||
},
|
||||
newUpload: {
|
||||
sourceID: '', //上��视频成功后 返回���ID
|
||||
md5: '', //文件摘要
|
||||
type: 'vid',
|
||||
src: '',
|
||||
height: '',
|
||||
width: '',
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['uploadVideoSuccess']);
|
||||
const fileReaderPromisify = (file: any) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let reader = new FileReader();
|
||||
let Spark = new SparkMD5.ArrayBuffer();
|
||||
reader.readAsArrayBuffer(file);
|
||||
reader.onload = function (e: any) {
|
||||
Spark.append(e.target.result);
|
||||
let md5 = Spark.end();
|
||||
resolve(md5);
|
||||
};
|
||||
reader.onerror = (err) => {
|
||||
reject(err);
|
||||
};
|
||||
});
|
||||
};
|
||||
// 上传视频
|
||||
const afterVideo = async (e: any) => {
|
||||
state.startUploadVideo = true;
|
||||
let file = e.file;
|
||||
let fileMd5: any = await fileReaderPromisify(file);
|
||||
let file_chunks = getFileChunks(file);
|
||||
let length = file_chunks.length;
|
||||
for (let index in file_chunks) {
|
||||
let chunk = file_chunks[Number(index)];
|
||||
let opts = {
|
||||
pos: Number(index) + 1,
|
||||
totalPos: length,
|
||||
data: Buffer.from(await chunk.arrayBuffer(), 'utf8').toString('base64'),
|
||||
id: fileMd5,
|
||||
};
|
||||
state.uploadData.md5 = fileMd5;
|
||||
state.newUpload.md5 = fileMd5;
|
||||
state.requestAll.push(opts);
|
||||
}
|
||||
getVideoPlayerInfo(file); //获取视频宽高
|
||||
requestConcurrency();
|
||||
};
|
||||
//限制请求数量
|
||||
const requestConcurrency = () => {
|
||||
while (state.requestAll.length > 0 && state.requestNum <= state.requestMaxNum && state.requestNum >= 0) {
|
||||
let opts = state.requestAll.shift();
|
||||
upload(opts);
|
||||
}
|
||||
};
|
||||
// 将视频分片
|
||||
const getFileChunks = (file: any) => {
|
||||
let { size } = file;
|
||||
let total_chunks = Math.ceil(size / state.chunk_size);
|
||||
let file_chunks = [];
|
||||
if (size > state.chunk_size) {
|
||||
for (let i = 0; i < total_chunks; i++) {
|
||||
let start = i * state.chunk_size;
|
||||
let end = (i + 1) * state.chunk_size;
|
||||
let chunk = file.slice(start, end);
|
||||
state.totalProgress[i] = 0;
|
||||
file_chunks.push(chunk);
|
||||
}
|
||||
} else {
|
||||
file_chunks.push(file);
|
||||
state.totalProgress[0] = 0;
|
||||
}
|
||||
return file_chunks;
|
||||
};
|
||||
// 开始上传
|
||||
const upload = async (options: any) => {
|
||||
try {
|
||||
state.requestNum++;
|
||||
let callback = (processCallback: any) => {
|
||||
let percent = parseInt(((processCallback.loaded / processCallback.total) * 100).toString());
|
||||
state.totalProgress[options.pos - 1] = percent.toFixed(2);
|
||||
let strArr = Object.values(state.totalProgress);
|
||||
let numberArr = strArr.map(Number);
|
||||
state.uploadStatue.percent = Number(average(numberArr).toFixed(1));
|
||||
};
|
||||
let ret: any = await CommunityApi.uploadVideo(options, callback);
|
||||
state.sendVideoSucNum++;
|
||||
if (state.uploadStatue.percent == 100) {
|
||||
// 所有分片请求发送完毕,等待返回
|
||||
state.uploadStatue.statusText = '处理中,请勿退出';
|
||||
}
|
||||
if (state.uploadStatue.percent == 100 && state.sendVideoSucNum == options.totalPos) {
|
||||
state.uploadStatue.statusText = '上传成功';
|
||||
state.uploadData.sourceURL = ret.videoUri;
|
||||
state.uploadData.sourceID = ret.id;
|
||||
state.newUpload.sourceID = ret.id;
|
||||
state.newUpload.src = ret.videoUri;
|
||||
emit('uploadVideoSuccess', state.uploadData);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
state.currentRate = 0;
|
||||
state.uploadStatue.percent = 0;
|
||||
state.uploadStatue.statusText = '上传失败';
|
||||
state.sendVideoSucNum = 0;
|
||||
} finally {
|
||||
state.requestNum--;
|
||||
requestConcurrency();
|
||||
}
|
||||
};
|
||||
// 获取视频信息
|
||||
const getVideoPlayerInfo = (file: any) => {
|
||||
state.uploadData.size = file.size;
|
||||
state.uploadData.filename = file.name;
|
||||
state.uploadData.mimeType = file.type;
|
||||
// state.newUpload.type = file.type;
|
||||
nextTick(() => {
|
||||
const videoElement: any = document.getElementById('video');
|
||||
videoElement.src = URL.createObjectURL(file);
|
||||
videoElement.addEventListener('loadedmetadata', () => {
|
||||
state.uploadData.playTime = parseInt(videoElement.duration);
|
||||
state.videoHeight = videoElement.videoHeight;
|
||||
state.uploadData.ratio = Number((videoElement.videoWidth / videoElement.videoHeight).toFixed(2));
|
||||
state.uploadData.resolution = videoElement.videoWidth + 'x' + videoElement.videoHeight;
|
||||
state.newUpload.height = videoElement.videoHeight;
|
||||
state.newUpload.width = videoElement.videoWidth;
|
||||
});
|
||||
});
|
||||
};
|
||||
// 还原默认数据
|
||||
const reductionData = () => {
|
||||
state.uploadData = {
|
||||
newsType: 'SP', //上传类型 COVER-图集 SP-视频
|
||||
tags: [], //视频标签数组
|
||||
playTime: 0, //视频时长
|
||||
cover: '', //封面
|
||||
coverThumb: '', //封面小图
|
||||
seriesCover: [], // 图集图片地址
|
||||
via: '', //视频来源
|
||||
coins: 0, //观看金币
|
||||
size: 0, //文件大小
|
||||
mimeType: '', //文件类型
|
||||
actor: '', //演员名字
|
||||
sourceURL: '', //资源url 为SP时 必传
|
||||
sourceID: '', //上��视频成功后 返回���ID 为SP时必传
|
||||
filename: '', //文件名
|
||||
resolution: '', //分辨率
|
||||
ratio: 1, //视频比例
|
||||
md5: '', //文件摘要
|
||||
freeTime: 0, //免费观影时长
|
||||
location: {
|
||||
city: '',
|
||||
}, //地理位置信息
|
||||
isActivity: false, //是否参加大赛
|
||||
};
|
||||
state.newUpload = {
|
||||
sourceID: '',
|
||||
md5: '', //文件摘要
|
||||
type: 'vid',
|
||||
src: '',
|
||||
height: '',
|
||||
width: '',
|
||||
};
|
||||
};
|
||||
// 删除视频
|
||||
const uploadDelete = () => {
|
||||
state.newUpload.src = 'vid';
|
||||
state.uploadData.sourceURL = '';
|
||||
state.uploadStatue.statusText = '上传中,请勿退出';
|
||||
state.uploadStatue.percent = 0;
|
||||
state.currentRate = 0;
|
||||
state.sendVideoSucNum = 0;
|
||||
state.startUploadVideo = false;
|
||||
};
|
||||
// 平均数
|
||||
const average = (nums: any) => {
|
||||
return nums.reduce((a: any, b: any) => a + b) / nums.length;
|
||||
};
|
||||
defineExpose({
|
||||
reductionData,
|
||||
uploadDelete,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.upload-video {
|
||||
margin: 0 3px 0 0;
|
||||
.upload-box {
|
||||
width: 111px;
|
||||
height: 111px;
|
||||
border-radius: 6px;
|
||||
border: dashed 1px rgb(154, 154, 154);
|
||||
background: #262626;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
|
||||
span {
|
||||
font-size: 12px;
|
||||
color: #9a9a9a;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-box span {
|
||||
font-size: 10px;
|
||||
color: rgb(129, 129, 129);
|
||||
margin-top: 5.5px;
|
||||
}
|
||||
|
||||
.uploadCover {
|
||||
padding-left: 0.16rem;
|
||||
}
|
||||
/* 上传中 */
|
||||
.uploading {
|
||||
width: 111px;
|
||||
height: 111px;
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.previewVideo {
|
||||
width: 111px;
|
||||
height: 111px;
|
||||
border-radius: 6px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.video-mask {
|
||||
width: 111px;
|
||||
height: 111px;
|
||||
border-radius: 6px;
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.circle {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.uploading .close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: url('../../assets/images/png/community_close.png') center center no-repeat;
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
:deep(.van-circle__text) {
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,248 +0,0 @@
|
||||
<template>
|
||||
<div class="videoBox" @click.stop="openVideo">
|
||||
<div class="coverBox">
|
||||
<lazyImg
|
||||
class="cover"
|
||||
:src="state.videoInfo?.type ? state.videoInfo?.cover : state.videoInfo?.verticalCover"
|
||||
:key="state.videoInfo?.type ? state.videoInfo?.cover : state.videoInfo?.verticalCover"
|
||||
/>
|
||||
<div class="goldLabel" v-if="state.videoInfo?.price">
|
||||
<SvgIcon name="goldIcon" class="goldIcon" />
|
||||
<div class="price">{{ state.videoInfo?.price }}</div>
|
||||
</div>
|
||||
<div class="readNum" v-if="state.videoInfo?.kind == 4">
|
||||
<SvgIcon name="book" class="bookIcon" />
|
||||
{{ watchCount(state.videoInfo?.countBrowse) }}
|
||||
</div>
|
||||
<div class="readNum" v-if="state.videoInfo?.kind == 6">
|
||||
<SvgIcon name="audio" class="bookIcon" />
|
||||
{{ watchCount(state.videoInfo?.countView) }}
|
||||
</div>
|
||||
<div class="mask" :class="{ imgMask: state.videoInfo?.kind == 5 }">
|
||||
<div
|
||||
class="updatedDesc"
|
||||
v-if="state.videoInfo?.kind == 1 || state.videoInfo?.kind == 4 || state.videoInfo?.kind == 6"
|
||||
>
|
||||
{{ `${state.videoInfo?.updateStatus == 0 ? '已完结' : '连载中'}${state?.videoInfo?.totalEpisode}话` }}
|
||||
</div>
|
||||
<div class="videoData" v-if="state.videoInfo?.kind == 5">
|
||||
<div class="watchCount">
|
||||
<SvgIcon name="viewCount" class="viewCount" />
|
||||
{{ watchCount(state.videoInfo?.countBrowse) }}
|
||||
</div>
|
||||
<div class="workNum">
|
||||
<SvgIcon name="workNumIcon" class="workNumIcon" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="videoTitle ellipsis">{{ state.videoInfo?.title ? state.videoInfo?.title : '无标题' }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { watchCount, videoTime, addVideoHistory } from '@/utils/index';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useVideoStore } from '@/stores/video';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
import path from 'path';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const videoStore = useVideoStore();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
videoInfo: any;
|
||||
videoList: any;
|
||||
type?: string;
|
||||
}>(),
|
||||
{
|
||||
videoInfo: () => <any>{},
|
||||
videoList: () => [],
|
||||
type: () => '',
|
||||
},
|
||||
);
|
||||
const emit = defineEmits(['changeVideo']);
|
||||
const state = {
|
||||
videoInfo: props.videoInfo,
|
||||
};
|
||||
// console.log(state.videoInfo);
|
||||
const openVideo = async () => {
|
||||
if (state.videoInfo.type) {
|
||||
jumpAdv(state.videoInfo);
|
||||
return;
|
||||
}
|
||||
if (state.videoInfo?.kind == 5) {
|
||||
router.push({
|
||||
path: '/portrayPage',
|
||||
query: {
|
||||
id: state.videoInfo.id,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
if (route.path == '/novelDetailsPage') {
|
||||
await router.replace({
|
||||
path: '/novelDetailsPage',
|
||||
query: {
|
||||
id: state.videoInfo.id,
|
||||
},
|
||||
});
|
||||
router.go(0);
|
||||
} else {
|
||||
router.push({
|
||||
path: '/novelDetailsPage',
|
||||
query: {
|
||||
id: state.videoInfo.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// if (state.isMovie) {
|
||||
// emit('changeVideo', state.videoInfo);
|
||||
// } else {
|
||||
// router.push({
|
||||
// path: '/movieDetails',
|
||||
// query: {
|
||||
// vid: state.videoInfo.id,
|
||||
// uid: state.videoInfo.publisher?.uid,
|
||||
// queryPath: state.queryPath,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// if (state.videoInfo.newsType == 'COVER') {
|
||||
// // router.push({
|
||||
// // path: '/postDetails',
|
||||
// // query: {
|
||||
// // postId: state.videoInfo.id,
|
||||
// // },
|
||||
// // });
|
||||
// } else {
|
||||
// if (state.videoInfo.playTime > 300) {
|
||||
// if (state.isMovie) {
|
||||
// emit('changeVideo', state.videoInfo);
|
||||
// } else {
|
||||
// router.push({
|
||||
// path: '/movieDetails',
|
||||
// query: {
|
||||
// vid: state.videoInfo.id,
|
||||
// uid: state.videoInfo.publisher?.uid,
|
||||
// queryPath: state.queryPath,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// return;
|
||||
// } else {
|
||||
// videoStore.deleteVideoList();
|
||||
// videoStore.saveVideoList(state.videoList, state.videoInfo);
|
||||
// router.push('/shortVideoDetails');
|
||||
// }
|
||||
// }
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.videoBox {
|
||||
width: 111px;
|
||||
.coverBox {
|
||||
width: 111px;
|
||||
height: 146px;
|
||||
position: relative;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 8px;
|
||||
:deep(img) {
|
||||
border-radius: 8px;
|
||||
}
|
||||
.goldLabel {
|
||||
min-width: 38px;
|
||||
height: 20px;
|
||||
padding: 0 6px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0px 8px;
|
||||
background: #f00;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.goldIcon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.price {
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
.readNum {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: 6px;
|
||||
height: 14px;
|
||||
padding: 0 2px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
font-size: 10px;
|
||||
.bookIcon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
.mask {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.7) 100%);
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
.videoData {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.watchCount {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
.viewCount {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
.workNum {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 18px;
|
||||
padding: 0 4px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.imgMask {
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
.videoTitle {
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,251 +0,0 @@
|
||||
<template>
|
||||
<div class="vertical_video_warp">
|
||||
<div id="video">
|
||||
<div class="avoid_sliding" @click="pause"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import VideoApi from '@/service/video';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { debounce } from '@/utils';
|
||||
import { onBeforeUnmount, onMounted, Ref, ref, toRefs } from 'vue';
|
||||
import HlsJSPlayer from 'xgplayer-hls.js';
|
||||
import { addVideoHistory } from '@/utils';
|
||||
import { HistoryVideoType } from '@/enums/app';
|
||||
import { analyticsEventVideo } from '@/utils/analyticsEvent';
|
||||
import { useGlobalStore } from '@/stores/global';
|
||||
|
||||
const props = defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
}>();
|
||||
defineExpose({
|
||||
success,
|
||||
});
|
||||
const { videoInfo } = toRefs(props);
|
||||
const { isVip, freeVideo30, userInfo } = useUserStore();
|
||||
let userFreeCount: Ref<Types.Video.UserFreeCount> = ref({
|
||||
isCan: false,
|
||||
watchCount: 0,
|
||||
});
|
||||
const globalStore = useGlobalStore();
|
||||
const emit = defineEmits(['vipBuyShow', 'goldBuyShow', 'getFreeCount']);
|
||||
let player: any = null; //播放器实例
|
||||
let isReport = ref(false); // 视频埋点锁
|
||||
onMounted(() => {
|
||||
//获取免费观看次数
|
||||
getFreeWatchCount();
|
||||
//初始化播放器
|
||||
initVideo();
|
||||
//保存历史记录
|
||||
addVideoHistory(props.videoInfo, HistoryVideoType.VIDEO);
|
||||
});
|
||||
|
||||
/**
|
||||
* @description 暂停
|
||||
*/
|
||||
const pause = () => {
|
||||
player.pause();
|
||||
};
|
||||
/**
|
||||
* @description 初始化播放器
|
||||
*/
|
||||
const initVideo = () => {
|
||||
player = new HlsJSPlayer({
|
||||
id: 'video',
|
||||
url: getPath(),
|
||||
fluid: true,
|
||||
playsinline: true,
|
||||
videoInit: true,
|
||||
loop: true,
|
||||
autoplay: true,
|
||||
controls: true,
|
||||
lang: 'zh-cn',
|
||||
ignores: ['fullscreen', 'i18n', 'play', 'volume', 'definition'],
|
||||
allowPlayAfterEnded: true,
|
||||
allowSeekAfterEnded: true,
|
||||
closeVideoPreventDefault: true,
|
||||
closeVideoStopPropagation: true,
|
||||
closeInactive: true,
|
||||
enableVideoDbltouch: true,
|
||||
});
|
||||
player.on('timeupdate', () => {
|
||||
if (player.hasStart) {
|
||||
if (!playCheck()) {
|
||||
pause();
|
||||
if (player.video.currentTime > props.videoInfo.freeTime) {
|
||||
analyticsEventVideo(props.videoInfo.id, props.videoInfo.title);
|
||||
}
|
||||
debounce(() => {
|
||||
if (videoInfo.value.originCoins === 0) {
|
||||
emit('vipBuyShow');
|
||||
} else {
|
||||
emit('goldBuyShow');
|
||||
}
|
||||
}, 100)();
|
||||
}
|
||||
//埋点
|
||||
analytics();
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description 视频埋点
|
||||
*/
|
||||
const analytics = () => {
|
||||
if (isReport.value) return;
|
||||
if (props.videoInfo.playTime > 300) {
|
||||
if (player.video.currentTime > props.videoInfo.playTime * 0.1) {
|
||||
isReport.value = true;
|
||||
analyticsEventVideo(props.videoInfo.id, props.videoInfo.title);
|
||||
}
|
||||
} else if (player.video.currentTime > 15) {
|
||||
isReport.value = true;
|
||||
analyticsEventVideo(props.videoInfo.id, props.videoInfo.title);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @description 获取用户免费观看次数
|
||||
*/
|
||||
const getFreeWatchCount = () => {
|
||||
VideoApi.getPlayCount(videoInfo.value.id).then((userCount) => {
|
||||
userFreeCount.value = userCount;
|
||||
emit('getFreeCount', userCount);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* @description 获取播放链接
|
||||
*/
|
||||
const getPath = () => {
|
||||
const { baseUrl } = useConfigStore();
|
||||
return `${baseUrl}/api/app/vid/h5/m3u8/${videoInfo.value.sourceURL}?token=${getToken()}&c=${
|
||||
globalStore.videoRoadLine.url
|
||||
}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 检测视频是否可以播放
|
||||
*/
|
||||
const playCheck = () => {
|
||||
let freeTime = videoInfo.value.freeTime || 0;
|
||||
//视频已购买
|
||||
if (videoInfo.value.vidStatus.hasPaid === true) {
|
||||
player.config.disableProgress = false;
|
||||
return true;
|
||||
}
|
||||
//30金币以下视频免费看
|
||||
if (freeVideo30 && videoInfo.value.originCoins < 30 && videoInfo.value.originCoins != 0) {
|
||||
return true;
|
||||
}
|
||||
//免费时长
|
||||
if (player.video.currentTime < freeTime) {
|
||||
player.config.disableProgress = false;
|
||||
return true;
|
||||
}
|
||||
// 会员视频
|
||||
if (videoInfo.value.originCoins === 0 && isVip) {
|
||||
player.config.disableProgress = false;
|
||||
return true;
|
||||
}
|
||||
//自己发布的视频
|
||||
if (userInfo.uid === videoInfo.value.publisher.uid) {
|
||||
player.config.disableProgress = false;
|
||||
return true;
|
||||
}
|
||||
// VIP免费次数
|
||||
if (userFreeCount.value.isCan === true && videoInfo.value.originCoins === 0) {
|
||||
player.config.disableProgress = false;
|
||||
return true;
|
||||
}
|
||||
player.config.disableProgress = true;
|
||||
return false;
|
||||
};
|
||||
//视频购买成功
|
||||
function success() {
|
||||
videoInfo.value.vidStatus.hasPaid = true;
|
||||
player.play();
|
||||
}
|
||||
/**
|
||||
* @description 获取token
|
||||
*/
|
||||
const getToken = () => {
|
||||
const { token } = useUserStore();
|
||||
return token;
|
||||
};
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (player) {
|
||||
player.src = '';
|
||||
player.destroy(true);
|
||||
}
|
||||
player = null;
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// @media (min-height: 700px) {
|
||||
// .vertical_video_warp {
|
||||
// padding-top: 20px;
|
||||
// }
|
||||
// }
|
||||
.vertical_video_warp {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
background: #000000;
|
||||
align-items: center;
|
||||
:deep(.xgplayer-progress-played) {
|
||||
background: #ff0d2c;
|
||||
}
|
||||
:deep(.xgplayer-progress) {
|
||||
top: 20px;
|
||||
}
|
||||
:deep(.xgplayer-start),
|
||||
:deep(.xgplayer-controls) {
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
}
|
||||
:deep(.xgplayer-progress-btn) {
|
||||
display: none !important;
|
||||
}
|
||||
:deep(.xgplayer-time-current:after) {
|
||||
content: ' ';
|
||||
}
|
||||
:deep(.xgplayer-progress) {
|
||||
left: 50%;
|
||||
right: 0;
|
||||
width: 70%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
:deep(.xgplayer-time) {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
:deep(.xgplayer-time-current)::after {
|
||||
display: none;
|
||||
}
|
||||
#video {
|
||||
width: 100%;
|
||||
height: 100% !important;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: relative;
|
||||
:deep(.xgplayer-enter-spinner) {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
.avoid_sliding {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,430 +0,0 @@
|
||||
<template>
|
||||
<div class="video_wrap">
|
||||
<div class="video_content">
|
||||
<!-- 图文播放器 -->
|
||||
<FullScreenGallery
|
||||
:videoInfo="videoInfo"
|
||||
v-if="videoInfo.newsType == 'AD_COVER' || videoInfo.newsType == 'COVER'"
|
||||
/>
|
||||
<!-- 视频播放器 -->
|
||||
<div class="video_box" v-else-if="videoInfo.newsType == 'SP' || videoInfo.newsType == 'AD_SP'">
|
||||
<VerticalVideo
|
||||
:video-info="videoInfo"
|
||||
v-if="videoShow"
|
||||
@goldBuyShow="goldBuyShow"
|
||||
@vipBuyShow="vipBuyShow"
|
||||
@getFreeCount="getFreeCount"
|
||||
ref="verticalVideoRef"
|
||||
/>
|
||||
</div>
|
||||
<!-- 右边菜单 -->
|
||||
<div :class="['right_menu', { pb_8: isNewUser }]">
|
||||
<div v-show="!pureMode.status">
|
||||
<div class="right-info-item" @click.stop="clickLike">
|
||||
<SvgIcon name="videoUnlike" v-if="!videoInfo.vidStatus.hasLiked"></SvgIcon>
|
||||
<SvgIcon name="videoLike" v-else></SvgIcon>
|
||||
<span>{{ watchCount(videoInfo.likeCount) }}</span>
|
||||
</div>
|
||||
<div class="right-info-item" @click.stop="openComment">
|
||||
<SvgIcon name="videoComment"></SvgIcon>
|
||||
<span>{{ watchCount(videoInfo.commentCount) }}</span>
|
||||
</div>
|
||||
<div class="right-info-item" @click.stop="share">
|
||||
<SvgIcon name="videoShare"></SvgIcon>
|
||||
<span>分享</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-info-item" @click="pureMode.status = !pureMode.status">
|
||||
<SvgIcon name="eye" v-if="!pureMode.status"></SvgIcon>
|
||||
<SvgIcon name="uneye" v-else></SvgIcon>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 底部信息 -->
|
||||
<div :class="['button_info', { pb60: isNewUser }]" v-show="!pureMode.status">
|
||||
<div class="tags_box ellipsis">
|
||||
<div
|
||||
class="tags_item"
|
||||
@click="router.push({ path: '/tagShortVideo', query: { tag: item.name, tagId: item.id } })"
|
||||
v-for="item in videoInfo.tags.slice(0, 3)"
|
||||
:key="item.id"
|
||||
>
|
||||
#{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="locationAnduserNameBox">
|
||||
<span class="userName">@{{ videoInfo.publisher.name || '未知用户' }}</span>
|
||||
</div>
|
||||
<div class="title">{{ videoInfo.title }}</div>
|
||||
<!-- 视频购买按钮 -->
|
||||
<div v-if="videoInfo.newsType == 'SP' || videoInfo.newsType == 'COVER'">
|
||||
<!-- 会员视频购买 -->
|
||||
<div class="buying" @click="isJoinMerbershipShow = true" v-if="showVipBuy()">
|
||||
<span>
|
||||
{{
|
||||
userFreeCount.isCan
|
||||
? `免费视频,剩余免费次数${userFreeCount.watchCount}`
|
||||
: `预览${
|
||||
videoInfo.newsType == 'COVER' ? '3张' : `${videoInfo.freeTime}S`
|
||||
},开通会员观看完整版(${videoTime(videoInfo.playTime)})`
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<!-- 金币视频购买 -->
|
||||
<div class="buyingGold" v-else-if="showGoldBuy()" @click="isGoldCoinPurchase = true">
|
||||
<span>{{ getGoldCoin() }}金币,购买完整版 ({{ videoTime(videoInfo.playTime) }})</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 广告下载按钮 -->
|
||||
<div class="adv_down" v-if="videoInfo.newsType == 'AD_COVER' || videoInfo.newsType == 'AD_SP'">立即下载</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div
|
||||
class="new_user_box"
|
||||
v-if="isNewUser && timeObj && timeObj.countdownSec > 0"
|
||||
@click="$router.push('/recharge?name=member')"
|
||||
>
|
||||
<div class="flex-center-center">
|
||||
<SvgIcon name="hot" />
|
||||
<p>限时福利 新人专享年卡</p>
|
||||
</div>
|
||||
<div class="time">
|
||||
<div class="time_item">{{ timeObj.tenHr }}</div>
|
||||
<div class="time_item">{{ timeObj.hr }}</div>
|
||||
<span>:</span>
|
||||
<div class="time_item">{{ timeObj.tenMin }}</div>
|
||||
<div class="time_item">{{ timeObj.min }}</div>
|
||||
<span>:</span>
|
||||
<div class="time_item">{{ timeObj.tenSec }}</div>
|
||||
<div class="time_item">{{ timeObj.sec }}</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<!-- 会员弹窗 -->
|
||||
<MemberPopup :videoInfo="videoInfo" :is-open="isJoinMerbershipShow" @close="isJoinMerbershipShow = false" />
|
||||
<!-- 金币弹窗 -->
|
||||
<GoldPopup
|
||||
:is-open="isGoldCoinPurchase"
|
||||
:video-info="videoInfo"
|
||||
@close="isGoldCoinPurchase = false"
|
||||
@buy-success="buySuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { videoTime, watchCount } from '@/utils/index';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { Ref, ref, toRefs, inject } from 'vue';
|
||||
import VideoApi from '@/service/video';
|
||||
import { LikeType } from '@/enums/app';
|
||||
import { showToast } from 'vant';
|
||||
import UserApi from '@/service/user';
|
||||
import { useVideoStore } from '@/stores/video';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const router = useRouter();
|
||||
const props = defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
videoShow: boolean;
|
||||
pureMode: {
|
||||
status: boolean;
|
||||
};
|
||||
timeObj: any;
|
||||
}>();
|
||||
const openShareBox: any = inject('openShareBox'); // 获取到祖组件的方法
|
||||
const openRewardBox: any = inject('openRewardBox'); // 获取到祖组件的方法
|
||||
const openCommentPopup: any = inject('openCommentPopup'); // 获取到祖组件的方法
|
||||
let userFreeCount: Ref<Types.Video.UserFreeCount> = ref({
|
||||
isCan: false,
|
||||
watchCount: 0,
|
||||
});
|
||||
// const isNewUser = ref(true); //是否为新人
|
||||
const { isVip, freeVideo30, isNewUser } = useUserStore();
|
||||
const { videoInfo, pureMode } = toRefs(props);
|
||||
const verticalVideoRef = ref();
|
||||
let isJoinMerbershipShow = ref(false); //会员购买
|
||||
let isGoldCoinPurchase = ref(false); //金币购买
|
||||
|
||||
//点赞-取消
|
||||
const clickLike = () => {
|
||||
let hasLiked = videoInfo.value.vidStatus.hasLiked;
|
||||
let id = videoInfo.value.id;
|
||||
try {
|
||||
if (hasLiked) {
|
||||
VideoApi.cancleLike(id, LikeType.LikeTypeVideo).then(() => {
|
||||
videoInfo.value.vidStatus.hasLiked = false;
|
||||
videoInfo.value.likeCount--;
|
||||
showToast('取消成功');
|
||||
});
|
||||
} else {
|
||||
VideoApi.like(id, LikeType.LikeTypeVideo).then(() => {
|
||||
videoInfo.value.vidStatus.hasLiked = true;
|
||||
videoInfo.value.likeCount++;
|
||||
showToast('点赞成功');
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
//金币购买弹窗
|
||||
const goldBuyShow = () => {
|
||||
isGoldCoinPurchase.value = true;
|
||||
};
|
||||
|
||||
//免费观看视频次数
|
||||
const getFreeCount = (userCount: Types.Video.UserFreeCount) => {
|
||||
userFreeCount.value = userCount;
|
||||
};
|
||||
//会员购买弹窗
|
||||
const vipBuyShow = () => {
|
||||
isJoinMerbershipShow.value = true;
|
||||
};
|
||||
//获取当前视频价格
|
||||
const getGoldCoin = () => {
|
||||
return isVip ? videoInfo.value.coins : videoInfo.value.originCoins;
|
||||
};
|
||||
|
||||
//会员按钮是否展示
|
||||
const showVipBuy = () => {
|
||||
const { isVip } = useUserStore();
|
||||
if (videoInfo.value.originCoins == 0) {
|
||||
if (isVip) return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
//金币按钮是否展示
|
||||
const showGoldBuy = () => {
|
||||
//已经购买视频
|
||||
if (videoInfo.value.vidStatus.hasPaid === true) {
|
||||
return false;
|
||||
}
|
||||
//30金币以下视频免费看
|
||||
if (freeVideo30 && videoInfo.value.originCoins < 30) {
|
||||
return false;
|
||||
}
|
||||
//金币视频
|
||||
if (videoInfo.value.originCoins > 0 && videoInfo.value.coins > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 视频购买成功
|
||||
*/
|
||||
const buySuccess = () => {
|
||||
isGoldCoinPurchase.value = false;
|
||||
verticalVideoRef.value.success();
|
||||
};
|
||||
|
||||
// 打开分享弹窗
|
||||
const share = () => {
|
||||
openShareBox();
|
||||
};
|
||||
|
||||
// 打开打赏弹窗
|
||||
const openReward = () => {
|
||||
openRewardBox(videoInfo.value.id);
|
||||
};
|
||||
|
||||
// 打开评论弹窗
|
||||
const openComment = () => {
|
||||
openCommentPopup(videoInfo.value);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pb60 {
|
||||
bottom: 40px !important;
|
||||
}
|
||||
.pb_8 {
|
||||
bottom: 20px !important;
|
||||
}
|
||||
.video_wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #ffffff;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
.new_user_box {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background: rgba($color: #999999, $alpha: 0.44);
|
||||
z-index: 1001;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 19px;
|
||||
}
|
||||
p {
|
||||
padding-left: 11px;
|
||||
font-size: 14px;
|
||||
color: #ff0d2c;
|
||||
line-height: 30px;
|
||||
}
|
||||
.time {
|
||||
display: flex;
|
||||
span {
|
||||
padding-left: 4px;
|
||||
}
|
||||
.time_item {
|
||||
margin-left: 4px;
|
||||
width: 14px;
|
||||
height: 17px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
.video_content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.video_box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.right_menu {
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 3%;
|
||||
z-index: 1000;
|
||||
.right-info-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
padding-bottom: 19px;
|
||||
svg {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
span {
|
||||
color: #ffffff;
|
||||
padding-top: 5px;
|
||||
}
|
||||
:deep(.van-switch) {
|
||||
height: 14px;
|
||||
background: rgba($color: #f2f2f2, $alpha: 0.36);
|
||||
width: 36.5px;
|
||||
height: 15px;
|
||||
}
|
||||
:deep(.van-switch__node) {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
top: 0.15vw;
|
||||
left: 1.33vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
.button_info {
|
||||
width: 300px;
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 14px;
|
||||
z-index: 1000;
|
||||
.tags_box {
|
||||
width: 300px;
|
||||
display: flex;
|
||||
.tags_item {
|
||||
padding-right: 14px;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.24px;
|
||||
color: $themeColor;
|
||||
}
|
||||
}
|
||||
.locationAnduserNameBox {
|
||||
padding-top: 13px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.locationAnduser {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
svg {
|
||||
font-size: 22px;
|
||||
}
|
||||
.location {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
padding: 0 13px 0 0;
|
||||
}
|
||||
.userName {
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
padding-top: 10px;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.24px;
|
||||
line-height: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
.buying {
|
||||
margin-top: 10px;
|
||||
width: fit-content;
|
||||
padding: 0 10px;
|
||||
height: 24px;
|
||||
position: relative;
|
||||
background-color: rgba(253, 191, 80, 0.35);
|
||||
border-radius: 13px;
|
||||
padding-left: 22px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
span {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
.buyingGold {
|
||||
margin-top: 10px;
|
||||
width: 171px;
|
||||
height: 24px;
|
||||
position: relative;
|
||||
background: url('../../assets/images/png/goldBuy.png') no-repeat;
|
||||
background-size: 100%;
|
||||
padding-left: 22px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
span {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
.adv_down {
|
||||
margin-top: 10px;
|
||||
width: 94px;
|
||||
height: 26px;
|
||||
background: #ff112f;
|
||||
border-radius: 15px;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,117 +0,0 @@
|
||||
<template>
|
||||
<van-overlay :show="isShow" z-index="2001" @click="emit('close')">
|
||||
<div class="wrapper-gold flex-center-center">
|
||||
<div class="content">
|
||||
<div class="title">开通VIP</div>
|
||||
<div class="line"></div>
|
||||
<div class="about-promote">
|
||||
<div class="sub-title">推广赚钱,最高返利75%</div>
|
||||
<p>成功推广好友,立即获得会员权益</p>
|
||||
<div class="tip">你的观看次数不足</div>
|
||||
</div>
|
||||
<div class="btn-box flex-center-between">
|
||||
<router-link class="promote-btn btn" to="/promotionCode">推广赚钱</router-link>
|
||||
<div class="recharge-btn btn" @click="joinMembership">开通VIP</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="close" @click="emit('close')">
|
||||
<SvgIcon name="close" />
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const router = useRouter();
|
||||
const props = defineProps<{
|
||||
videoInfo: Types.Video.VInfosItem;
|
||||
isOpen: boolean;
|
||||
}>();
|
||||
const emit = defineEmits(['close']);
|
||||
const isShow = computed(() => {
|
||||
return props.isOpen;
|
||||
});
|
||||
/**
|
||||
* @description 开通会员
|
||||
*/
|
||||
const joinMembership = () => {
|
||||
router.push({
|
||||
path: '/recharge',
|
||||
query: {
|
||||
name: 'member',
|
||||
id: props.videoInfo.id,
|
||||
title: props.videoInfo.title || '无标题',
|
||||
},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.wrapper-gold {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
.content {
|
||||
width: 300px;
|
||||
text-align: center;
|
||||
background: linear-gradient(to bottom, #fff0f1, #ffffff, #ffffff);
|
||||
border-radius: 8px;
|
||||
padding: 0 14px 21px 14px;
|
||||
.title {
|
||||
padding: 16px 0;
|
||||
font-size: 24px;
|
||||
font-weight: 400;
|
||||
}
|
||||
.line {
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: #ebebeb;
|
||||
}
|
||||
.about-promote {
|
||||
padding: 18px 0px;
|
||||
.sub-title {
|
||||
font-size: 18px;
|
||||
color: $titleColor;
|
||||
font-weight: 500;
|
||||
}
|
||||
p {
|
||||
font-size: 14px;
|
||||
color: $titleColor;
|
||||
margin-top: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.tip {
|
||||
font-size: 14px;
|
||||
color: $greyDeepColor;
|
||||
margin-top: 26px;
|
||||
}
|
||||
}
|
||||
.btn-box {
|
||||
.btn {
|
||||
height: 38px;
|
||||
width: 129px;
|
||||
line-height: 38px;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.promote-btn {
|
||||
border: 1.5px solid $themeColor;
|
||||
color: $themeColor;
|
||||
}
|
||||
.recharge-btn {
|
||||
background-color: $themeColor;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.close {
|
||||
padding-top: 16px;
|
||||
svg {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,112 +0,0 @@
|
||||
<template>
|
||||
<div class="vipPromptDialog" v-if="props.show">
|
||||
<van-overlay :show="props.show">
|
||||
<div class="contentBox">
|
||||
<div class="content">
|
||||
<div class="title">
|
||||
<span>温馨提示</span>
|
||||
</div>
|
||||
|
||||
<div class="desc">
|
||||
<span>{{ props.msg }}</span>
|
||||
</div>
|
||||
|
||||
<div class="btnBox">
|
||||
<div class="btn" @click="$router.push('/recharge?name=member')">
|
||||
<span>前往购买VIP</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btnBox" @click="close">
|
||||
<img src="@/assets/images/png/closeDialog.png" />
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { withDefaults } from 'vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
show: boolean;
|
||||
msg: string;
|
||||
}>(),
|
||||
{
|
||||
show: () => false,
|
||||
msg: () => '',
|
||||
},
|
||||
);
|
||||
const emit = defineEmits(['close']);
|
||||
/**
|
||||
* 关闭弹窗
|
||||
*/
|
||||
const close = () => {
|
||||
emit('close', false);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vipPromptDialog {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.contentBox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.content {
|
||||
width: 300px;
|
||||
//height: 249px;
|
||||
background: rgb(255, 255, 255);
|
||||
border-radius: 11px;
|
||||
padding: 20px 0;
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
color: rgb(51, 51, 51);
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 16px;
|
||||
color: rgb(51, 51, 51);
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.btnBox {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
|
||||
.btn {
|
||||
width: 189px;
|
||||
height: 37px;
|
||||
background: rgb(255, 13, 44);
|
||||
color: rgb(255, 255, 255);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 18.5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btnBox {
|
||||
margin-top: 24px;
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,132 +0,0 @@
|
||||
<template>
|
||||
<div class="vipTipPopup">
|
||||
<van-popup
|
||||
v-model:show="state.isRewardShow"
|
||||
teleport="body"
|
||||
:close-on-click-overlay="false"
|
||||
:style="{ backgroundColor: 'rgba(0, 0, 0, 0)' }"
|
||||
>
|
||||
<div class="popupBox" v-if="state.isShowGold">
|
||||
<div class="title">温馨提示</div>
|
||||
<div class="desc">
|
||||
<p>您的金币余额不足,请充值金币</p>
|
||||
</div>
|
||||
<div class="btnBox flex-center-center">
|
||||
<div class="btn" @click="state.isRewardShow = false">取消</div>
|
||||
<div class="btn BindBtn" @click="$router.push({ path: '/recharge', query: { name: 'wallet' } })">
|
||||
前往充值
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="popupBox" v-else>
|
||||
<div class="listbox">
|
||||
<p>该功能为会员权益哦</p>
|
||||
</div>
|
||||
<div class="btnBox flex-center-center">
|
||||
<div class="btn" @click="cancel" v-if="!props.isCancelReturn">下次再说</div>
|
||||
<div class="btn" @click="state.isRewardShow = false" v-else>下次再说</div>
|
||||
<div class="btn BindBtn" @click="openVip">开通会员</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const props = defineProps<{
|
||||
isCancelReturn?: boolean;
|
||||
isShowGold?: string;
|
||||
}>();
|
||||
|
||||
const state = reactive({
|
||||
isRewardShow: false,
|
||||
isShowGold: props.isShowGold,
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const cancel = () => {
|
||||
router.go(-1);
|
||||
state.isRewardShow = false;
|
||||
};
|
||||
|
||||
const openPop = () => {
|
||||
state.isRewardShow = true;
|
||||
};
|
||||
|
||||
const openVip = () => {
|
||||
router.push({
|
||||
path: '/recharge',
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
openPop,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
//.vipTipPopup {
|
||||
// background-color: rgba(255, 255, 255);
|
||||
.popupBox {
|
||||
background: rgba(255, 255, 255);
|
||||
border-radius: 6px;
|
||||
height: 136px;
|
||||
width: 311px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
.title {
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
padding-top: 18px;
|
||||
}
|
||||
.desc {
|
||||
font-weight: 400;
|
||||
color: #00000099;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
height: 55px;
|
||||
padding: 16px 0;
|
||||
}
|
||||
.listbox {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
line-height: 70px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
p {
|
||||
font-weight: 500;
|
||||
color: #000;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btnBox {
|
||||
margin: 0 auto;
|
||||
.btn {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
line-height: 48px;
|
||||
border-top: 0.5px solid rgba(231, 231, 231, 1);
|
||||
}
|
||||
.BindBtn {
|
||||
color: $themeColor;
|
||||
border-left: 0.5px solid rgba(231, 231, 231, 1);
|
||||
}
|
||||
}
|
||||
:deep(.van-popup) {
|
||||
border-radius: 12px;
|
||||
}
|
||||
:deep(.van-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
//}
|
||||
</style>
|
||||
@@ -1,66 +0,0 @@
|
||||
<template>
|
||||
<div class="adv-list" v-if="state.advsList.length > 0">
|
||||
<div class="rectAdvBox" @click="jumpAdv(item)" v-for="item in state.advsList" :key="item.id">
|
||||
<lazyImg class="rectAdvIcon" :src="item.cover" />
|
||||
<div class="rectName">{{ item.title }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { getAdItem } from '@/utils/getConfig';
|
||||
import { AdType } from '@/enums/app';
|
||||
import { jumpAdv } from '@/utils/index';
|
||||
import { reactive } from 'vue';
|
||||
const state = reactive({
|
||||
advsList: <Array<Types.App.AdsInfoListItem>>[], // 专栏之间的广告
|
||||
});
|
||||
const props = defineProps({
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
moduleCount: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
const handleAdvList = (origin: any) => {
|
||||
const arr = [];
|
||||
let j = 0;
|
||||
for (let index = 0; index < props.moduleCount * 5; index++, j++) {
|
||||
if (!origin[j]) {
|
||||
j = 0;
|
||||
}
|
||||
arr[index] = origin[j];
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
console.log(handleAdvList(getAdItem(AdType.HOMETOPIC)).length, getAdItem(AdType.HOMETOPIC));
|
||||
if (getAdItem(AdType.HOMETOPIC) && getAdItem(AdType.HOMETOPIC).length > 0) {
|
||||
state.advsList = handleAdvList(getAdItem(AdType.HOMETOPIC)).slice(props.index * 5, (props.index + 1) * 5);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.adv-list {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
color: #fff;
|
||||
// margin-top: 10px;
|
||||
}
|
||||
.rectAdvBox {
|
||||
width: 60px;
|
||||
.rectAdvIcon {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.rectName {
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,263 +0,0 @@
|
||||
<template>
|
||||
<div class="cardPopup">
|
||||
<van-popup v-model:show="state.isRewardShow" teleport="body" z-index="2002">
|
||||
<div class="popupBox">
|
||||
<h1 class="title flex-center-center">身/份/证/卡</h1>
|
||||
<img class="logoImg flex-center-center" src="@/assets/images/png/cardLogo.png" />
|
||||
<!-- <lazyImg class="avatar" :src="state.userInfo.portrait" round :key="state.userInfo.portrait" /> -->
|
||||
<!-- <div class="promoteCode flex-center-center">
|
||||
<span>{{ state.userInfo.promotionCode }}</span>
|
||||
</div> -->
|
||||
<div class="qrCodeBg">
|
||||
<div class="qrCodeBox flex-center-center">
|
||||
<qrcode-vue id="qrCode" class="qrCodeImg" v-if="state.qrUrl" :value="state.qrUrl" level="L" />
|
||||
<van-loading size="50px" type="spinner" color="#c0c9ea" v-else />
|
||||
</div>
|
||||
</div>
|
||||
<div class="lines"></div>
|
||||
<div class="contentBox">
|
||||
<div class="addressBox flex-center-between">
|
||||
<div class="address">
|
||||
<SvgIcon name="Account" class="official" />
|
||||
账号:
|
||||
<span>{{ state.userInfo.uid }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="addressBox flex-center-between">
|
||||
<div class="address">
|
||||
<SvgIcon name="emails" class="official" />
|
||||
官方邮箱:
|
||||
<span>{{ state.email }}</span>
|
||||
</div>
|
||||
<div class="officialCopy" @click="copyLink('email')">复制</div>
|
||||
</div>
|
||||
<div class="addressBox flex-center-between">
|
||||
<div class="address">
|
||||
<SvgIcon name="official" class="official" />
|
||||
官方网站:
|
||||
<span>{{ state.url }}</span>
|
||||
</div>
|
||||
<div class="officialCopy" @click="copyLink('url')">复制</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btnBox flex-center-center">
|
||||
<div class="btn" @click="showToast('请手动截图保存')">请截图保存</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, reactive } from 'vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import UserApi from '@/service/user';
|
||||
import { showToast } from 'vant';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
import useClipboard from 'vue-clipboard3';
|
||||
|
||||
const configStore = useConfigStore();
|
||||
const { toClipboard } = useClipboard();
|
||||
|
||||
const userStore = useUserStore();
|
||||
const userInfo: any = userStore.userInfo;
|
||||
|
||||
const state = reactive({
|
||||
userInfo: <Types.User.UserInfoType>{},
|
||||
userWallet: <Types.User.WalletInfo>{},
|
||||
qrUrl: <string>'',
|
||||
url: configStore.sourceInfo.LAND,
|
||||
email: configStore.sourceInfo.EMAIL,
|
||||
isRewardShow: false,
|
||||
qrCodeId: <string>'',
|
||||
});
|
||||
|
||||
nextTick(async () => {
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
const userStore = useUserStore();
|
||||
state.userInfo = userStore.userInfo;
|
||||
let ret: any = await UserApi.queryCertificate();
|
||||
state.qrUrl = ret.content;
|
||||
});
|
||||
|
||||
const copyLink = async (val: string) => {
|
||||
state.qrCodeId = val;
|
||||
try {
|
||||
if (!state.qrCodeId) {
|
||||
showToast('复制失败');
|
||||
return;
|
||||
}
|
||||
if (state.qrCodeId === 'url') {
|
||||
await toClipboard(state.url); //实现复制
|
||||
showToast('复制成功');
|
||||
} else if (state.qrCodeId === 'email') {
|
||||
await toClipboard(state.email); //实现复制
|
||||
showToast('复制成功');
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
const openPop = () => {
|
||||
state.isRewardShow = true;
|
||||
};
|
||||
defineExpose({
|
||||
openPop,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// background-color: rgba(255, 255, 255);
|
||||
.popupBox {
|
||||
background: linear-gradient(180deg, #f9ca26 0%, #ffffff 100%);
|
||||
border-radius: 6px;
|
||||
height: 470px;
|
||||
width: 343px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
padding: 6px 0;
|
||||
.title {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 6px;
|
||||
}
|
||||
.logoImg {
|
||||
width: 199.29px;
|
||||
height: 56px;
|
||||
margin: 10px auto;
|
||||
}
|
||||
.avatar {
|
||||
height: 76px;
|
||||
width: 76px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid rgb(234, 247, 255);
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: -38px;
|
||||
transform: translate(-50%, 0);
|
||||
z-index: 1;
|
||||
background-color: rgb(234, 247, 255);
|
||||
}
|
||||
.promoteCode {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 46px;
|
||||
font-size: 16px;
|
||||
color: rgb(24, 24, 24);
|
||||
text-align: center;
|
||||
span {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
.qrCodeBg {
|
||||
border: 2px solid rgba(255, 173, 0, 1);
|
||||
border-radius: 12px;
|
||||
margin: 0 auto;
|
||||
// position: absolute;
|
||||
// background: url('./../../../assets/images/png/actCredentialsBg.png') no-repeat;
|
||||
// background-size: 100% 100%;
|
||||
// top: 107px;
|
||||
// left: 50%;
|
||||
// transform: translate(-50%, 0);
|
||||
width: 222px;
|
||||
height: 222px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.qrCodeBox {
|
||||
background-color: white;
|
||||
width: 208px;
|
||||
height: 208px;
|
||||
border-radius: 10px;
|
||||
.qrCodeImg {
|
||||
width: 190px !important;
|
||||
height: 190px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.lines {
|
||||
margin: 19px 0;
|
||||
height: 3px;
|
||||
background-image: linear-gradient(to right, rgba(255, 173, 0, 1) 0%, rgba(255, 173, 0, 1) 50%, transparent 0%);
|
||||
background-size: 14px 3px;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
.lines::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -22.5px;
|
||||
width: 22.5px;
|
||||
height: 45px;
|
||||
// border-radius: 45px 0 0 45px;
|
||||
border-radius: 0 45px 45px 0;
|
||||
background: #000;
|
||||
}
|
||||
.lines::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -22.5px;
|
||||
right: 0;
|
||||
width: 22.5px;
|
||||
height: 45px;
|
||||
border-radius: 45px 0 0 45px;
|
||||
background: #000;
|
||||
}
|
||||
.contentBox {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
padding: 0 16px;
|
||||
.addressBox {
|
||||
margin: 6px 0;
|
||||
.address {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
color: rgb(24, 24, 24);
|
||||
.official {
|
||||
vertical-align: top;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
span {
|
||||
font-weight: 700;
|
||||
white-space: nowrap; /*强制span不换行*/
|
||||
}
|
||||
}
|
||||
.officialCopy {
|
||||
font-size: 14px;
|
||||
white-space: nowrap; /*强制span不换行*/
|
||||
display: inline-block;
|
||||
width: 32px;
|
||||
line-height: 0.9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.btnBox {
|
||||
margin: 25px auto;
|
||||
.btn {
|
||||
height: 40px;
|
||||
width: 343px;
|
||||
background-color: $themeColor;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
color: $titleColor;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
:deep(.van-popup) {
|
||||
border-radius: 10px;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
:deep(.van-overlay) {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user