fix: 直播样式调整

This commit is contained in:
kaizheng(郑凯) 2025-03-09 15:06:29 +08:00
parent 74d35a6491
commit d1094417d8
16 changed files with 622 additions and 282 deletions

2
.gitignore vendored
View File

@ -2,7 +2,7 @@
node_modules node_modules
/dist /dist
/build /build
/test
# local env files # local env files
.env.local .env.local

299
src/assets/css/live.css Normal file
View File

@ -0,0 +1,299 @@
body {
--bubble_time: 3s;
--bubble_scale: 3s;
}
.bubble {
position: absolute;
width: 80px;
height: 80px;
left: 50%;
left: 50%;
background-repeat: no-repeat;
background-size: 100%;
transform-origin: bottom;
}
.b1 {
background-image: url(../images/liveIcon/bg1.png);
}
.b2 {
background-image: url(../images/liveIcon/bg2.png);
}
.b3 {
background-image: url(../images/liveIcon/bg3.png);
}
.b4 {
background-image: url(../images/liveIcon/bg4.png);
}
.b5 {
background-image: url(../images/liveIcon/bg5.png);
}
.b6 {
background-image: url(../images/liveIcon/bg6.png);
}
.bl1 {
animation: bubble_1 var(--bubble_time) linear 1 forwards,
bubble_big_1 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
.bl2 {
animation: bubble_2 var(--bubble_time) linear 1 forwards,
bubble_big_2 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
.bl3 {
animation: bubble_3 var(--bubble_time) linear 1 forwards,
bubble_big_1 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
.bl4 {
animation: bubble_4 var(--bubble_time) linear 1 forwards,
bubble_big_2 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
.bl5 {
animation: bubble_5 var(--bubble_time) linear 1 forwards,
bubble_big_1 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
.bl6 {
animation: bubble_6 var(--bubble_time) linear 1 forwards,
bubble_big_3 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
.bl7 {
animation: bubble_7 var(--bubble_time) linear 1 forwards,
bubble_big_1 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
.bl8 {
animation: bubble_8 var(--bubble_time) linear 1 forwards,
bubble_big_3 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
.bl9 {
animation: bubble_9 var(--bubble_time) linear 1 forwards,
bubble_big_2 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
.bl10 {
animation: bubble_10 var(--bubble_time) linear 1 forwards,
bubble_big_1 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
.bl11 {
animation: bubble_11 var(--bubble_time) linear 1 forwards,
bubble_big_2 var(--bubble_scale) linear 1 forwards,
bubble_y var(--bubble_time) linear 1 forwards;
}
@keyframes bubble_11 {
0% {
}
25% {
margin-left: -15px;
}
50% {
margin-left: -15px;
}
100% {
margin-left: -20px;
}
}
@keyframes bubble_10 {
0% {
}
25% {
margin-left: -20px;
}
50% {
margin-left: -20px;
}
100% {
margin-left: -20px;
}
}
@keyframes bubble_9 {
0% {
}
25% {
margin-left: 10px;
}
50% {
margin-left: 10px;
}
100% {
margin-left: 10px;
}
}
@keyframes bubble_8 {
0% {
}
25% {
margin-left: 30px;
}
50% {
margin-left: 30px;
}
100% {
margin-left: 30px;
}
}
@keyframes bubble_7 {
0% {
}
25% {
margin-left: 6px;
}
50% {
margin-left: 2px;
}
75% {
margin-left: 4px;
}
100% {
margin-left: 6px;
}
}
@keyframes bubble_6 {
0% {
}
25% {
margin-left: -6px;
}
50% {
margin-left: -2px;
}
75% {
margin-left: -4px;
}
100% {
margin-left: -6px;
}
}
@keyframes bubble_5 {
0% {
}
25% {
margin-left: 10px;
}
50% {
margin-left: -10px;
}
75% {
margin-left: -20px;
}
100% {
margin-left: -40px;
}
}
@keyframes bubble_4 {
0% {
}
25% {
margin-left: -10px;
}
50% {
margin-left: -10px;
}
75% {
margin-left: 40px;
}
100% {
margin-left: 20px;
}
}
@keyframes bubble_3 {
0% {
}
25% {
margin-left: -40px;
}
50% {
margin-left: 20px;
}
75% {
margin-left: 40px;
}
100% {
margin-left: -20px;
}
}
@keyframes bubble_2 {
0% {
}
25% {
margin-left: 40px;
}
50% {
margin-left: 50px;
}
75% {
margin-left: 20px;
}
100% {
margin-left: 10px;
}
}
@keyframes bubble_1 {
0% {
}
25% {
margin-left: -16px;
}
50% {
margin-left: 16px;
}
75% {
margin-left: -30px;
}
100% {
margin-left: 30px;
}
}
@keyframes bubble_big_1 {
0% {
/* transform: scale(0.3); */
width: 20px;
height: 20px;
}
100% {
width: 80px;
height: 80px;
}
}
@keyframes bubble_big_2 {
0% {
/* transform: scale(0.3); */
width: 15px;
height: 15px;
}
100% {
/* transform: scale(0.9); */
width: 60px;
height: 60px;
}
}
@keyframes bubble_big_3 {
0% {
width: 10px;
height: 10px;
}
100% {
width: 40px;
height: 40px;
}
}
@keyframes bubble_y {
0% {
top: -10px;
}
10% {
top: -40px;
}
75% {
opacity: 1;
}
100% {
top: -400px;
opacity: 0;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,22 @@
export default function useContinuousClickLive() {
const addContinuousClickLive = (boxClass) => {
const b = Math.floor(Math.random() * 6) + 1
const bl = Math.floor(Math.random() * 11) + 1 // bl1~bl11
let d = document.createElement("div")
d.className = `bubble b${b} bl${bl}`
d.dataset.t = String(Date.now())
const likeBox = document.querySelector(boxClass)
likeBox.appendChild(d)
;((d) => {
d.addEventListener("animationend", () => {
debugger
if (likeBox.contains(d)) {
likeBox.removeChild(d)
}
})
})(d)
}
return addContinuousClickLive
}

View File

@ -20,12 +20,11 @@
detail.advisorBasic && detail.advisorBasic.avatar detail.advisorBasic && detail.advisorBasic.avatar
? detail.advisorBasic.avatar ? detail.advisorBasic.avatar
: defaultPhoto : defaultPhoto
" " />
/>
</div> </div>
<div class="news-content-wrap"> <div class="news-content-wrap">
<div class="user-info"> <div class="user-info">
<h3>{{ detail.advisorBasic?.showName }} <span>讲师</span></h3> <h3><span>讲师</span>{{ detail.advisorBasic?.showName }}</h3>
</div> </div>
<div> <div>
<p class="text"> <p class="text">
@ -49,16 +48,14 @@
`li${item.id}`, `li${item.id}`,
item.phone === store.state.userInfo.userId ? 'row-reverse' : '', item.phone === store.state.userInfo.userId ? 'row-reverse' : '',
]" ]"
:key="item.id" :key="item.id">
>
<div v-if="item.show"> <div v-if="item.show">
<!-- <div v-if="item.type === 3" class="warn"> <!-- <div v-if="item.type === 3" class="warn">
{{ item.userName }}进入直播间 {{ item.userName }}进入直播间
</div> --> </div> -->
<div <div
class="chat-time" class="chat-time"
v-if="(isTg && item.tgChatTime) || (!isTg && item.chatTime)" v-if="(isTg && item.tgChatTime) || (!isTg && item.chatTime)">
>
{{ isTg ? item.tgChatTime : item.chatTime }} {{ isTg ? item.tgChatTime : item.chatTime }}
</div> </div>
<div v-if="item.type === 5" class="warn"> <div v-if="item.type === 5" class="warn">
@ -72,8 +69,7 @@
<button <button
class="share" class="share"
@click="sendMsg(5)" @click="sendMsg(5)"
v-if="item.phone !== store.state.userInfo.userId" v-if="item.phone !== store.state.userInfo.userId">
>
我也要分享 我也要分享
</button> </button>
</div> </div>
@ -82,8 +78,7 @@
:class="[ :class="[
'flex', 'flex',
item.phone === store.state.userInfo.userId ? 'row-reverse' : '', item.phone === store.state.userInfo.userId ? 'row-reverse' : '',
]" ]">
>
<div class="photo"> <div class="photo">
<img <img
:src=" :src="
@ -95,8 +90,7 @@
? item.imgUrl ? item.imgUrl
: tgDefaultPhoto : tgDefaultPhoto
" "
alt="" alt="" />
/>
</div> </div>
<div class="news-content-wrap"> <div class="news-content-wrap">
<div class="user-info"> <div class="user-info">
@ -160,8 +154,7 @@
v-else v-else
class="img" class="img"
@click="imagePreview(item.content.split('upImg-')[1])" @click="imagePreview(item.content.split('upImg-')[1])"
:src="item.content.split('upImg-')[1]" :src="item.content.split('upImg-')[1]" />
/>
<div v-if="item.advisorId" class="license"> <div v-if="item.advisorId" class="license">
{{ detail.advisorBasic.name {{ detail.advisorBasic.name
}}<i v-if="detail.advisorBasic.license" }}<i v-if="detail.advisorBasic.license"
@ -176,8 +169,7 @@
:item="item.productBasic" :item="item.productBasic"
:liveProductId="detail.id" :liveProductId="detail.id"
:tgId="detail.advisorBasic?.id" :tgId="detail.advisorBasic?.id"
:isShopCar="true" :isShopCar="true" />
/>
</div> </div>
<div v-else-if="item.type === 4"> <div v-else-if="item.type === 4">
<p> <p>
@ -197,15 +189,13 @@
v-if=" v-if="
item.phone !== store.state.userInfo.userId && item.phone !== store.state.userInfo.userId &&
detail.isSubAdvisor !== 1 detail.isSubAdvisor !== 1
" ">
>
我也关注 我也关注
</button> </button>
</div> </div>
<div <div
v-else-if="[6, 7, 9, 10].includes(item.type)" v-else-if="[6, 7, 9, 10].includes(item.type)"
style="color: #f46946" style="color: #f46946">
>
<p>{{ item.content }}</p> <p>{{ item.content }}</p>
</div> </div>
<div v-else-if="item.type === 8" style="color: #f46946"> <div v-else-if="item.type === 8" style="color: #f46946">
@ -264,25 +254,25 @@ import {
onMounted, onMounted,
computed, computed,
defineEmits, defineEmits,
} from "vue"; } from "vue"
import { useStore } from "vuex"; import { useStore } from "vuex"
import { showToast, showImagePreview } from "vant"; import { showToast, showImagePreview } from "vant"
import { import {
sendFollowMessage, sendFollowMessage,
queryQuestionCheck, queryQuestionCheck,
queryLiveTgHisMsg, queryLiveTgHisMsg,
queryLiveHisMsg, queryLiveHisMsg,
} from "@/api/video"; } from "@/api/video"
import QuestionnairePopup from "../components/QuestionnairePopup.vue"; import QuestionnairePopup from "../components/QuestionnairePopup.vue"
import useChatData from "@/hooks/useChatData"; import useChatData from "@/hooks/useChatData"
import useGetLiveStatusObj from "@/hooks/useGetLiveStatusObj"; import useGetLiveStatusObj from "@/hooks/useGetLiveStatusObj"
import ProductItem from "../components/ProductItem.vue"; import ProductItem from "../components/ProductItem.vue"
import { attentionTg } from "@/api/index"; import { attentionTg } from "@/api/index"
import emitter from "@/utils/emitter"; import emitter from "@/utils/emitter"
// import dayjs from "dayjs"; // import dayjs from "dayjs";
const store = useStore(); const store = useStore()
const $liveStatusObj = useGetLiveStatusObj(); const $liveStatusObj = useGetLiveStatusObj()
const props = defineProps({ const props = defineProps({
className: { className: {
@ -302,76 +292,76 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}); })
const defaultPhoto = require("@/assets/images/default-photo.png"); const defaultPhoto = require("@/assets/images/default-photo.png")
const tgDefaultPhoto = require("@/assets/images/tg-p.webp"); const tgDefaultPhoto = require("@/assets/images/tg-p.webp")
// const productFloatShow = ref(false); // const productFloatShow = ref(false);
const scrollClassName = ref(`interact-scroll-${new Date().getTime()}`); const scrollClassName = ref(`interact-scroll-${new Date().getTime()}`)
const { msgListRef, bs } = useChatData( const { msgListRef, bs } = useChatData(
Object.assign({ isTg: props.isTg }, props.detail, { Object.assign({ isTg: props.isTg }, props.detail, {
className: `.${scrollClassName.value}`, className: `.${scrollClassName.value}`,
}) })
); )
const hasNext = computed(() => { const hasNext = computed(() => {
return props.isTg return props.isTg
? store.state.interactMsgObj.tgHasHisMsg ? store.state.interactMsgObj.tgHasHisMsg
: store.state.interactMsgObj.hasHisMsg; : store.state.interactMsgObj.hasHisMsg
}); })
watch(hasNext, (value) => { watch(hasNext, (value) => {
if (value) bs.value && bs.value.openPullDown(); if (value) bs.value && bs.value.openPullDown()
}); })
watch( watch(
() => props.informMsgList, () => props.informMsgList,
() => { () => {
nextTick(() => { nextTick(() => {
bs.value && bs.value.refresh(); bs.value && bs.value.refresh()
if ( if (
(props.isTg && store.state.interactMsgObj.isTgScrollToBottom) || (props.isTg && store.state.interactMsgObj.isTgScrollToBottom) ||
(!props.isTg && store.state.interactMsgObj.isScrollToBottom) (!props.isTg && store.state.interactMsgObj.isScrollToBottom)
) { ) {
nextTick(() => { nextTick(() => {
bs.value && bs.value.scrollTo(0, bs.value.maxScrollY, 0); bs.value && bs.value.scrollTo(0, bs.value.maxScrollY, 0)
}); })
} }
}); })
}, },
{ deep: true } { deep: true }
); )
let intervalTime = null; let intervalTime = null
const replenishMsg = async () => { const replenishMsg = async () => {
let fn = props.isTg ? queryLiveTgHisMsg : queryLiveHisMsg; let fn = props.isTg ? queryLiveTgHisMsg : queryLiveHisMsg
let ret = await fn({ let ret = await fn({
id: props.detail.id, id: props.detail.id,
lastId: "", lastId: "",
size: 20, size: 20,
status: 1, status: 1,
}); })
if (ret.code === 0) { if (ret.code === 0) {
let list = ret.data.list.reverse(); let list = ret.data.list.reverse()
emitter.emit("informMsgListPush", list); emitter.emit("informMsgListPush", list)
} }
}; }
let getNewMsg = (once) => { let getNewMsg = (once) => {
if (once) { if (once) {
replenishMsg(); replenishMsg()
} else { } else {
clearInterval(intervalTime); clearInterval(intervalTime)
intervalTime = setInterval(replenishMsg, 1000 * 30); intervalTime = setInterval(replenishMsg, 1000 * 30)
} }
}; }
emitter.on("getNewMsg", getNewMsg); emitter.on("getNewMsg", getNewMsg)
emitter.on("cancelGetNewMsg", () => { emitter.on("cancelGetNewMsg", () => {
clearInterval(intervalTime); clearInterval(intervalTime)
}); })
async function subAdvisor() { async function subAdvisor() {
let ret = await attentionTg({ let ret = await attentionTg({
@ -379,11 +369,11 @@ async function subAdvisor() {
channel: 2, channel: 2,
option: props.detail.isSubAdvisor === 1 ? 2 : 1, option: props.detail.isSubAdvisor === 1 ? 2 : 1,
videoId: props.detail.id, videoId: props.detail.id,
}); })
if (ret.code === 0) { if (ret.code === 0) {
emitter.emit("updateVideoDetail", { emitter.emit("updateVideoDetail", {
isSubAdvisor: props.detail.isSubAdvisor === 1 ? 2 : 1, isSubAdvisor: props.detail.isSubAdvisor === 1 ? 2 : 1,
}); })
props.detail.isSubAdvisor === 1 && props.detail.isSubAdvisor === 1 &&
[ [
$liveStatusObj.InLive, $liveStatusObj.InLive,
@ -393,86 +383,86 @@ async function subAdvisor() {
sendFollowMessage({ sendFollowMessage({
id: props.detail.id, id: props.detail.id,
option: props.detail.isSubAdvisor === 1 ? 2 : 1, option: props.detail.isSubAdvisor === 1 ? 2 : 1,
}); })
} }
} }
const questionnairePopupRef = ref(); const questionnairePopupRef = ref()
const questionId = ref(); const questionId = ref()
const goAnswer = async (item) => { const goAnswer = async (item) => {
let ret = await queryQuestionCheck({ questionId: item.questionId }); let ret = await queryQuestionCheck({ questionId: item.questionId })
if (ret.code === 0) { if (ret.code === 0) {
if (ret.data.result) { if (ret.data.result) {
questionId.value = item.questionId; questionId.value = item.questionId
questionnairePopupRef.value.showPopup = true; questionnairePopupRef.value.showPopup = true
} else if (ret.data.type === 1) { } else if (ret.data.type === 1) {
return showToast("您已完成问卷任务,无须重复填写!"); return showToast("您已完成问卷任务,无须重复填写!")
} else if (ret.data.type === 2) { } else if (ret.data.type === 2) {
return showToast("问卷已删除!"); return showToast("问卷已删除!")
} }
} }
}; }
const emit = defineEmits(["optShare"]); const emit = defineEmits(["optShare"])
const sendMsg = (type, params) => { const sendMsg = (type, params) => {
if (type === 5) { if (type === 5) {
emit("optShare"); emit("optShare")
} }
emitter.emit("emSendMsg", { emitter.emit("emSendMsg", {
type, type,
params, params,
}); })
}; }
onBeforeUnmount(() => { onBeforeUnmount(() => {
emitter.off("getNewMsg"); emitter.off("getNewMsg")
emitter.off("cancelGetNewMsg"); emitter.off("cancelGetNewMsg")
}); })
const imagePreview = (url) => { const imagePreview = (url) => {
showImagePreview({ showImagePreview({
images: [url], images: [url],
closeable: true, closeable: true,
}); })
}; }
const newMsgNum = computed(() => { const newMsgNum = computed(() => {
return props.isTg return props.isTg
? store.state.interactMsgObj.temTgInteractShowNum ? store.state.interactMsgObj.temTgInteractShowNum
: store.state.interactMsgObj.temUserInteractShowNum; : store.state.interactMsgObj.temUserInteractShowNum
}); })
onMounted(() => { onMounted(() => {
bs.value.on("scrollEnd", () => { bs.value.on("scrollEnd", () => {
let isBottom = bs.value.maxScrollY + 20 >= bs.value.y; let isBottom = bs.value.maxScrollY + 20 >= bs.value.y
store.commit("setIsScrollToBottom", { store.commit("setIsScrollToBottom", {
isTg: props.isTg, isTg: props.isTg,
data: isBottom, data: isBottom,
}); })
if (isBottom) resetData(); if (isBottom) resetData()
}); })
}); })
const lookNewMsg = () => { const lookNewMsg = () => {
resetData(); resetData()
}; }
const resetData = () => { const resetData = () => {
store.commit("interactMsgMerge", { isTg: props.isTg }); store.commit("interactMsgMerge", { isTg: props.isTg })
nextTick(() => { nextTick(() => {
bs.value && bs.value.refresh(); bs.value && bs.value.refresh()
nextTick(() => { nextTick(() => {
bs.value && bs.value.scrollTo(0, bs.value.maxScrollY, 0); bs.value && bs.value.scrollTo(0, bs.value.maxScrollY, 0)
}); })
}); })
}; }
const maskUserName = (value) => { const maskUserName = (value) => {
return value.charAt(0) + "**"; return value.charAt(0) + "**"
}; }
defineExpose({ defineExpose({
bs, bs,
}); })
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.interact-scroll { .interact-scroll {
@ -519,18 +509,19 @@ defineExpose({
h3 { h3 {
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 28px; font-size: 24px;
color: #1b2330; color: #666666;
line-height: 28px; line-height: 28px;
margin-bottom: 20px; margin-bottom: 20px;
font-weight: 600;
span { span {
color: #ff6f16;
font-size: 22px; font-size: 22px;
line-height: 22px; line-height: 22px;
margin-left: 20px; margin-right: 10px;
border: 1px solid #ff3d36; background: linear-gradient(90deg, #66adff, #1472ff);
padding: 6px 8px; padding: 6px 8px;
border-radius: 8px; border-radius: 4px;
color: #fff;
} }
} }
} }
@ -568,14 +559,14 @@ defineExpose({
} }
.reply-content, .reply-content,
.text { .text {
background: #2e78fa; background: #87ee7e;
color: #fff; color: #333;
} }
.reply-content, .reply-content,
.text, .text,
& > img, & > img,
.share-tip { .share-tip {
border-radius: 20px 4px 20px 20px; border-radius: 10px 4px 10px 10px;
} }
.news-content-wrap > div { .news-content-wrap > div {
flex-flow: row-reverse; flex-flow: row-reverse;
@ -605,11 +596,11 @@ defineExpose({
.reply-content { .reply-content {
padding: 16px 24px; padding: 16px 24px;
background: #fff; background: #fff;
border-radius: 4px 20px 20px 20px; border-radius: 4px 10px 10px 10px;
font-size: 26px; font-size: 28px;
color: #606877; color: #333;
text-align: justify; text-align: justify;
line-height: 30px; line-height: 36px;
} }
.license { .license {
padding: 0; padding: 0;

View File

@ -2,37 +2,35 @@
<div class="scroll-wrap"> <div class="scroll-wrap">
<div class="detail-desc"> <div class="detail-desc">
<div class="detail-title fw-5" @click="$egg(3, 1000)"> <div class="detail-title fw-5" @click="$egg(3, 1000)">
{{ detail.title }} <h4>{{ detail.title }}</h4>
<div class="play-count">{{ detail.readCount }}次播放</div>
</div> </div>
<div class="tag-count flex-ac-sb"> <div class="tag-count flex-ac-sb">
<div v-show="detail.infoVO" class="tag"> <div v-show="detail.infoVO" class="tag">
{{ `${detail.infoVO?.productName} 专属服务` }} {{ `${detail.infoVO?.productName} 专属服务` }}
</div> </div>
<div class="count flex-ac"> <!-- <div class="count flex-ac">
<div class="play-count">{{ detail.readCount }}次播放</div> <div class="play-count">{{ detail.readCount }}次播放</div>
<div class="star-count flex-ac" v-if="!$shieldConfig.tgLive"> <div class="star-count flex-ac" v-if="!$shieldConfig.tgLive">
<img <img
v-if="detail.isFavor === 1" v-if="detail.isFavor === 1"
src="@/assets/images/like-icon3.png" src="@/assets/images/like-icon3.png"
alt="" alt="" />
/>
<img <img
v-else v-else
src="@/assets/images/like-icon.png" src="@/assets/images/like-icon.png"
alt="" alt=""
@click="sendLikeVideo(1)" @click="sendLikeVideo(1)" />
/>
<div <div
class="text-18 fw-5" class="text-18 fw-5"
:class="detail.isFavor === 1 ? 'tc-f13721' : 'tc-1B2330'" :class="detail.isFavor === 1 ? 'tc-f13721' : 'tc-1B2330'">
>
{{ detail.favorUserCount ? detail.favorUserCount : "" }} {{ detail.favorUserCount ? detail.favorUserCount : "" }}
</div> </div>
</div> </div>
</div> </div> -->
</div> </div>
<div class="author"> <div class="author">
<div class="mb20"> <div>
<div class="author-desc flex-ac"> <div class="author-desc flex-ac">
<img <img
class="avatar" class="avatar"
@ -41,41 +39,38 @@
? detail.advisorBasic.avatar ? detail.advisorBasic.avatar
: defaultPhoto : defaultPhoto
" "
alt="" alt="" />
/> <label>主讲</label>
<div> <div>
<div class="text-28 tc-606877"> <div class="text-28 tc-606877">
{{ detail.advisorBasic?.showName }} {{ detail.advisorBasic?.showName }}
</div> </div>
</div> </div>
<label>主讲</label>
</div> </div>
<div class="handle flex-ac no-wrap"> <div class="handle flex-ac no-wrap">
<button <button
class="add" class="add"
@click.stop="subAdvisor" @click.stop="subAdvisor"
v-if="!$shieldConfig.tgLive" v-if="!$shieldConfig.tgLive">
>
{{ detail.isSubAdvisor === 1 ? "取消关注" : "关注" }} {{ detail.isSubAdvisor === 1 ? "取消关注" : "关注" }}
</button> </button>
</div> </div>
</div> </div>
<div class="author-desc flex-ac" v-if="detail.guestInfo"> <div class="author-desc flex-ac" v-if="detail.guestInfo">
<img class="avatar" :src="detail.guestInfo.avatar" alt="" /> <img class="avatar" :src="detail.guestInfo.avatar" alt="" />
<label>嘉宾</label>
<div> <div>
<div class="text-28 tc-606877"> <div class="text-28 tc-606877">
{{ detail.guestInfo.showName }} {{ detail.guestInfo.showName }}
</div> </div>
</div> </div>
<label>嘉宾</label>
</div> </div>
</div> </div>
</div> </div>
<div class="line"></div> <div class="line"></div>
<div <div
v-if="detail.liveStatus === $liveStatusObj.NotStart" v-if="detail.liveStatus === $liveStatusObj.NotStart"
class="countdown-wrapper" class="countdown-wrapper">
>
<!-- <img class="coupon" src="@/assets/image/coupon@2x.png" alt="" @click="toTicket()" /> --> <!-- <img class="coupon" src="@/assets/image/coupon@2x.png" alt="" @click="toTicket()" /> -->
<div class="title-time flex-ac-sb"> <div class="title-time flex-ac-sb">
<div class="text-36 fw-5 tc-1B2330"> <div class="text-36 fw-5 tc-1B2330">
@ -93,13 +88,11 @@
detail.isSubscribe !== 1 && detail.allowSubscribe !== 2 detail.isSubscribe !== 1 && detail.allowSubscribe !== 2
? 'to-preview' ? 'to-preview'
: 'previewd' : 'previewd'
" ">
>
<div <div
v-if="detail.isSubscribe !== 1 && detail.allowSubscribe !== 2" v-if="detail.isSubscribe !== 1 && detail.allowSubscribe !== 2"
class="flex-ac" class="flex-ac"
v-preReClick="setSubLiveVideo" v-preReClick="setSubLiveVideo">
>
<img class="status-icon" src="@/assets/images/status2.png" alt="" /> <img class="status-icon" src="@/assets/images/status2.png" alt="" />
<div class="desc tc-2E78FA"> <div class="desc tc-2E78FA">
{{ detail.playType == 1 ? "预约直播" : "预约视频" }} {{ detail.playType == 1 ? "预约直播" : "预约视频" }}
@ -116,7 +109,7 @@
</div> </div>
<div class="line"></div> <div class="line"></div>
<div class="watch-focus"> <div class="watch-focus">
<div class="text-36 tc-1B2330 fw-5">本期看点</div> <div class="text-36 tc-1B2330 fw-5">视频简介</div>
<div class="watch-content tc-1B2330"> <div class="watch-content tc-1B2330">
{{ detail.viewPoint }} {{ detail.viewPoint }}
</div> </div>
@ -126,25 +119,25 @@
</template> </template>
<script setup> <script setup>
import { defineProps, onMounted } from "vue"; import { defineProps, onMounted } from "vue"
import { useRoute } from "vue-router"; import { useRoute } from "vue-router"
import { sendFollowMessage, likeVideo } from "@/api/video"; import { sendFollowMessage } from "@/api/video"
import { attentionTg } from "@/api/index"; import { attentionTg } from "@/api/index"
import emitter from "@/utils/emitter"; import emitter from "@/utils/emitter"
import CountDown from "./components/CountDown.vue"; import CountDown from "./components/CountDown.vue"
import useGetLiveStatusObj from "@/hooks/useGetLiveStatusObj"; import useGetLiveStatusObj from "@/hooks/useGetLiveStatusObj"
import useDisableScroll from "@/hooks/useDisableScroll"; import useDisableScroll from "@/hooks/useDisableScroll"
import { subLiveVideo } from "@/api/video"; import { subLiveVideo } from "@/api/video"
import useShieldConfig from "@/hooks/useShieldConfig"; import useShieldConfig from "@/hooks/useShieldConfig"
import useLoadConsole from "@/hooks/useLoadConsole"; import useLoadConsole from "@/hooks/useLoadConsole"
const $egg = useLoadConsole(); const $egg = useLoadConsole()
const $liveStatusObj = useGetLiveStatusObj(); const $liveStatusObj = useGetLiveStatusObj()
const route = useRoute(); const route = useRoute()
const $shieldConfig = useShieldConfig(); const $shieldConfig = useShieldConfig()
const { addScrollEvent } = useDisableScroll(); const { addScrollEvent } = useDisableScroll()
onMounted(() => { onMounted(() => {
addScrollEvent(".scroll-wrap"); addScrollEvent(".scroll-wrap")
}); })
const props = defineProps({ const props = defineProps({
detail: { detail: {
@ -152,8 +145,8 @@ const props = defineProps({
ype: Object, ype: Object,
default: () => ({}), default: () => ({}),
}, },
}); })
const defaultPhoto = require("@/assets/images/default-photo.png"); const defaultPhoto = require("@/assets/images/default-photo.png")
// //
async function subAdvisor() { async function subAdvisor() {
@ -162,11 +155,11 @@ async function subAdvisor() {
channel: 2, channel: 2,
option: props.detail.isSubAdvisor === 1 ? 2 : 1, option: props.detail.isSubAdvisor === 1 ? 2 : 1,
videoId: props.detail.id, videoId: props.detail.id,
}); })
if (ret.code === 0) { if (ret.code === 0) {
emitter.emit("updateVideoDetail", { emitter.emit("updateVideoDetail", {
isSubAdvisor: props.detail.isSubAdvisor === 1 ? 2 : 1, isSubAdvisor: props.detail.isSubAdvisor === 1 ? 2 : 1,
}); })
props.detail.isSubAdvisor === 1 && props.detail.isSubAdvisor === 1 &&
[ [
$liveStatusObj.InLive, $liveStatusObj.InLive,
@ -176,37 +169,37 @@ async function subAdvisor() {
sendFollowMessage({ sendFollowMessage({
id: props.detail.id, id: props.detail.id,
option: props.detail.isSubAdvisor === 1 ? 2 : 1, option: props.detail.isSubAdvisor === 1 ? 2 : 1,
}); })
} }
} }
const sendLikeVideo = async (liveNum) => { // const sendLikeVideo = async (liveNum) => {
const ret = await likeVideo({ // const ret = await likeVideo({
id: props.detail.id, // id: props.detail.id,
option: 1, // option: 1,
num: liveNum, // num: liveNum,
}); // })
if (ret.code === 0) { // if (ret.code === 0) {
emitter.emit("updateVideoDetail", { // emitter.emit("updateVideoDetail", {
isFavor: 1, // isFavor: 1,
favorUserCount: ret.data.count, // favorUserCount: ret.data.count,
}); // })
} // }
}; // }
const setSubLiveVideo = async () => { const setSubLiveVideo = async () => {
let ret = await subLiveVideo({ let ret = await subLiveVideo({
id: props.detail.id, id: props.detail.id,
option: props.detail.isSubscribe === 1 ? 2 : 1, option: props.detail.isSubscribe === 1 ? 2 : 1,
saleUserId: route.query.saleUserId, saleUserId: route.query.saleUserId,
}); })
if (ret.code === 0) { if (ret.code === 0) {
emitter.emit("updateVideoDetail", { emitter.emit("updateVideoDetail", {
isSubscribe: props.detail.isSubscribe === 1 ? 2 : 1, isSubscribe: props.detail.isSubscribe === 1 ? 2 : 1,
subscribeUserCount: ret.data.count, subscribeUserCount: ret.data.count,
}); })
} }
}; }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.mb20 { .mb20 {
@ -260,11 +253,25 @@ const setSubLiveVideo = async () => {
background-color: #fff; background-color: #fff;
text-align: left; text-align: left;
.detail-title { .detail-title {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 36px; font-size: 36px;
line-height: 54px; line-height: 54px;
margin-bottom: 8px; margin-bottom: 8px;
color: #1b2330; color: #1b2330;
font-weight: 500; font-weight: 500;
h4 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
.play-count {
margin: 0 20px 0 16px;
color: #9aa4b6;
font-size: 24px;
}
} }
.tag { .tag {
padding: 6px 8px; padding: 6px 8px;
@ -276,9 +283,9 @@ const setSubLiveVideo = async () => {
color: #9aa4b6; color: #9aa4b6;
font-size: 24px; font-size: 24px;
} }
.play-count { // .play-count {
margin: 0 20px 0 16px; // margin: 0 20px 0 16px;
} // }
.star-count { .star-count {
img { img {
width: 32px; width: 32px;
@ -290,6 +297,12 @@ const setSubLiveVideo = async () => {
padding: 24px; padding: 24px;
background: #f8f9fa; background: #f8f9fa;
border-radius: 12px; border-radius: 12px;
& > div {
margin-bottom: 20px;
}
& > div:last-child {
margin-bottom: 0;
}
.avatar { .avatar {
margin-right: 12px; margin-right: 12px;
width: 60px; width: 60px;
@ -314,12 +327,13 @@ const setSubLiveVideo = async () => {
} }
.author-desc { .author-desc {
label { label {
font-size: 24px; font-size: 22px;
color: #2e78fa; line-height: 22px;
border: 1px solid #2e78fa; margin-right: 10px;
padding: 4px 16px; background: linear-gradient(90deg, #66adff, #1472ff);
border-radius: 12px; padding: 6px 8px;
margin-left: 16px; border-radius: 4px;
color: #fff;
} }
} }
} }

View File

@ -6,16 +6,18 @@
:overlay="false" :overlay="false"
:round="false" :round="false"
:lock-scroll="false" :lock-scroll="false"
:lazy-render="false" :lazy-render="false">
>
<div class="msg-content"> <div class="msg-content">
<ChatFrame <ChatFrame
:informMsgList="detail.interactType === 2 ? store.state.interactMsgObj.userInteractMsgList : store.state.interactMsgObj.tgInteractMsgList" :informMsgList="
detail.interactType === 2
? store.state.interactMsgObj.userInteractMsgList
: store.state.interactMsgObj.tgInteractMsgList
"
:detail="detail" :detail="detail"
:isTg="detail.interactType === 1" :isTg="detail.interactType === 1"
@optShare="optShare" @optShare="optShare"
ref="ChatFrameRef" ref="ChatFrameRef" />
/>
</div> </div>
<div class="input-area"> <div class="input-area">
<input <input
@ -27,7 +29,7 @@
? '直播结束,暂不支持互动哟~' ? '直播结束,暂不支持互动哟~'
: isSpeak : isSpeak
? '互动已关闭...' ? '互动已关闭...'
: '与老师互动...' : '说点什么...'
" "
v-model.trim="text" v-model.trim="text"
@focus="inputMsg" @focus="inputMsg"
@ -36,13 +38,11 @@
isSpeak || isSpeak ||
[$liveStatusObj.FinishPlay].includes(detail.liveStatus) [$liveStatusObj.FinishPlay].includes(detail.liveStatus)
" "
@keyup.enter="sendMsg(1, { text })" @keyup.enter="sendMsg(1, { text })" />
/>
<button <button
class="send" class="send"
:disabled="!text || sendTextLoading" :disabled="!text || sendTextLoading"
@click="sendMsg(1, { text })" @click="sendMsg(1, { text })">
>
发送 发送
</button> </button>
</div> </div>
@ -51,15 +51,22 @@
</template> </template>
<script setup> <script setup>
import { ref, defineProps, watch, defineExpose, nextTick, defineEmits } from "vue"; import {
import { showToast } from "vant"; ref,
import emitter from "@/utils/emitter"; defineProps,
import useGetLiveStatusObj from "@/hooks/useGetLiveStatusObj"; watch,
import ChatFrame from "./ChatFrame.vue"; defineExpose,
import { useStore } from "vuex"; nextTick,
const $liveStatusObj = useGetLiveStatusObj(); defineEmits,
} from "vue"
import { showToast } from "vant"
import emitter from "@/utils/emitter"
import useGetLiveStatusObj from "@/hooks/useGetLiveStatusObj"
import ChatFrame from "./ChatFrame.vue"
import { useStore } from "vuex"
const $liveStatusObj = useGetLiveStatusObj()
const store = useStore(); const store = useStore()
const props = defineProps({ const props = defineProps({
detail: { detail: {
// //
@ -71,85 +78,85 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
optShare:{ optShare: {
type: Function, type: Function,
default: ()=>{} default: () => {},
} },
}); })
const show = ref(false); const show = ref(false)
const showRecommend = ref(false); // const showRecommend = ref(false) //
watch( watch(
() => props.activityObj, () => props.activityObj,
() => { () => {
if (props.activityObj && Object.keys(props.activityObj).length) { if (props.activityObj && Object.keys(props.activityObj).length) {
showRecommend.value = true; showRecommend.value = true
} }
} }
); )
const ChatFrameRef = ref(); const ChatFrameRef = ref()
const emit = defineEmits(['bsRefresh']) const emit = defineEmits(["bsRefresh"])
watch( watch(
() => show.value, () => show.value,
(val) => { (val) => {
nextTick(() => { nextTick(() => {
if (val) { if (val) {
if (ChatFrameRef.value && ChatFrameRef.value.bs){ if (ChatFrameRef.value && ChatFrameRef.value.bs) {
ChatFrameRef.value.bs.refresh(); ChatFrameRef.value.bs.refresh()
ChatFrameRef.value.bs.scrollTo(0, ChatFrameRef.value.bs.maxScrollY, 0); ChatFrameRef.value.bs.scrollTo(0, ChatFrameRef.value.bs.maxScrollY, 0)
} }
} else { } else {
emit('bsRefresh') emit("bsRefresh")
} }
}); })
} }
); )
function inputMsg() { function inputMsg() {
let bs = ChatFrameRef.value.bs; let bs = ChatFrameRef.value.bs
bs && bs.stop(); bs && bs.stop()
bs && bs.scrollTo(0, bs.maxScrollY, 0); bs && bs.scrollTo(0, bs.maxScrollY, 0)
} }
const text = ref(); const text = ref()
const sendTextLoading = ref(false); const sendTextLoading = ref(false)
const sendMsg = (type, params = {}) => { const sendMsg = (type, params = {}) => {
if (![1, 4].includes(type)) { if (![1, 4].includes(type)) {
// //
emitter.emit("emSendMsg", { type, params }); emitter.emit("emSendMsg", { type, params })
} }
switch (type) { switch (type) {
case 1: case 1:
if (text.value) { if (text.value) {
sendTextLoading.value = true; sendTextLoading.value = true
emitter.emit("emSendMsg", { emitter.emit("emSendMsg", {
type, type,
params: { params: {
...params, ...params,
callBack: () => { callBack: () => {
sendTextLoading.value = false; sendTextLoading.value = false
text.value = ""; text.value = ""
}, },
errorBack: () => { errorBack: () => {
sendTextLoading.value = false; sendTextLoading.value = false
}, },
}, },
}); })
} else { } else {
showToast("请输入互动内容!"); showToast("请输入互动内容!")
} }
break; break
default: default:
break; break
} }
}; }
defineExpose({ defineExpose({
show, show,
}); })
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
::v-deep .van-popup { ::v-deep .van-popup {

View File

@ -9,8 +9,7 @@
" "
:detail="detail" :detail="detail"
:isTg="detail.interactType === 2" :isTg="detail.interactType === 2"
@optShare="optShare" @optShare="optShare" />
/>
<div class="operate-wrap"> <div class="operate-wrap">
<div class="operate" @click="showInteractAction"> <div class="operate" @click="showInteractAction">
<img src="@/assets/images/msg-icon.png" alt="" /> <img src="@/assets/images/msg-icon.png" alt="" />
@ -18,20 +17,17 @@
<div <div
class="operate" class="operate"
@click="changeMsgTip" @click="changeMsgTip"
v-show="detail.interactType === 2" v-show="detail.interactType === 2">
>
<img :src="msgTipIcon[msgTipIndex]" alt="" /> <img :src="msgTipIcon[msgTipIndex]" alt="" />
</div> </div>
<ul <ul
class="new-msg-list" class="new-msg-list"
v-show="msgTipIndex === 1" v-show="msgTipIndex === 1"
v-if="detail.interactType === 2" v-if="detail.interactType === 2">
>
<li <li
v-for="(item, index) in newMsgTree" v-for="(item, index) in newMsgTree"
:key="index" :key="index"
@click="showInteractAction" @click="showInteractAction">
>
<div class="content"> <div class="content">
<p>{{ item.content }}</p> <p>{{ item.content }}</p>
<img :src="item.imgUrl" /> <img :src="item.imgUrl" />
@ -43,8 +39,7 @@
<div <div
class="recommend-img" class="recommend-img"
v-show="showRecommend" v-show="showRecommend"
@click="toActivityPage(1)" @click="toActivityPage(1)">
>
<img :src="activityObj.imgUrl" alt="" srcset="" /> <img :src="activityObj.imgUrl" alt="" srcset="" />
<i @click.stop="closeActivity"></i> <i @click.stop="closeActivity"></i>
</div> </div>
@ -63,7 +58,7 @@
? '直播结束,暂不支持互动哟~' ? '直播结束,暂不支持互动哟~'
: isSpeak : isSpeak
? '互动已关闭...' ? '互动已关闭...'
: '与老师互动...' : '说点什么...'
" "
v-model.trim="text" v-model.trim="text"
@focus="inputMsg" @focus="inputMsg"
@ -72,13 +67,11 @@
isSpeak || isSpeak ||
[$liveStatusObj.FinishPlay].includes(detail.liveStatus) [$liveStatusObj.FinishPlay].includes(detail.liveStatus)
" "
@keyup.enter="sendMsg(1, { text })" @keyup.enter="sendMsg(1, { text })" />
/>
<button <button
class="send" class="send"
:disabled="!text || sendTextLoading" :disabled="!text || sendTextLoading"
@click="sendMsg(1, { text })" @click="sendMsg(1, { text })">
>
发送 发送
</button> </button>
<button <button
@ -87,13 +80,16 @@
v-if=" v-if="
terminalType === 'Browser' || terminalType === 'Browser' ||
(terminalType === 'App' && system === 'android') (terminalType === 'App' && system === 'android')
" "></button>
></button>
<button <button
v-if="detail.liveStatus !== $liveStatusObj.NotStart" class="star-btn"
:class="['star', favorUserCountObj.isFavor === 1 ? 'active' : '']" v-if="detail.liveStatus !== $liveStatusObj.NotStart">
@click.stop="sendMsg(4)" <div
> @click.stop="sendMsg(4)"
:class="[
'star',
favorUserCountObj.isFavor === 1 ? 'active' : '',
]"></div>
<span v-if="favorUserCountObj.favorUserCount">{{ <span v-if="favorUserCountObj.favorUserCount">{{
bigNumberTransform(favorUserCountObj.favorUserCount) bigNumberTransform(favorUserCountObj.favorUserCount)
}}</span> }}</span>
@ -105,8 +101,7 @@
couponDetail && couponDetail &&
couponDetail.sendTotalNumber - couponDetail.sendGottenNumber > 0 couponDetail.sendTotalNumber - couponDetail.sendGottenNumber > 0
" "
@click="showDiscountCoupon" @click="showDiscountCoupon">
>
<!-- <p> <!-- <p>
仅剩{{ couponDetail.sendTotalNumber - couponDetail.sendGottenNumber }} 仅剩{{ couponDetail.sendTotalNumber - couponDetail.sendGottenNumber }}
</p> --> </p> -->
@ -122,8 +117,7 @@
ref="InteractRef" ref="InteractRef"
:isSpeak="isSpeak" :isSpeak="isSpeak"
:optShare="optShare" :optShare="optShare"
@bsRefresh="bsRefresh" @bsRefresh="bsRefresh" />
/>
</template> </template>
<script setup> <script setup>
@ -151,6 +145,7 @@ import ChatFrame from "./ChatFrame.vue"
import Interact from "./Interact.vue" import Interact from "./Interact.vue"
import { terminalType } from "@/utils/index" import { terminalType } from "@/utils/index"
import { getSystem } from "@/utils/index" import { getSystem } from "@/utils/index"
import useContinuousClickLive from "@/hooks/useContinuousClickLive"
// import TgChatFrame from "./TgChatFrame.vue"; // import TgChatFrame from "./TgChatFrame.vue";
// import MainInteract from "./MainInteract.vue"; // import MainInteract from "./MainInteract.vue";
import { queryCartRead } from "@/api/video" import { queryCartRead } from "@/api/video"
@ -317,12 +312,12 @@ const closeCarPush = () => {
} }
let liveIndex = 0 let liveIndex = 0
const liveIcon = [ // const liveIcon = [
require("@/assets/images/liveIcon/icon1.png"), // require("@/assets/images/liveIcon/icon1.png"),
require("@/assets/images/liveIcon/icon2.png"), // require("@/assets/images/liveIcon/icon2.png"),
require("@/assets/images/liveIcon/icon3.png"), // require("@/assets/images/liveIcon/icon3.png"),
require("@/assets/images/liveIcon/icon4.png"), // require("@/assets/images/liveIcon/icon4.png"),
] // ]
const favorUserCountObj = reactive({ const favorUserCountObj = reactive({
favorUserCount: props.detail.favorUserCount, favorUserCount: props.detail.favorUserCount,
isFavor: props.detail.isFavor, isFavor: props.detail.isFavor,
@ -342,18 +337,22 @@ const sendLikeVideo = async (liveNum) => {
} }
let sendLiveTime = null let sendLiveTime = null
const addContinuousClickLive = useContinuousClickLive()
console.log(addContinuousClickLive)
const dblclickLive = () => { const dblclickLive = () => {
const img = document.createElement("img") debugger
img.setAttribute("src", liveIcon[liveIndex % 4]) // const img = document.createElement("img")
img.setAttribute("class", "live-icon") // img.setAttribute("src", liveIcon[liveIndex % 4])
document.querySelector(".star").appendChild(img) // img.setAttribute("class", "live-icon")
liveIndex++ // const starBox = document.querySelector(".star-btn")
;((img) => { // starBox.appendChild(img)
setTimeout(() => { // liveIndex++
let star = document.querySelector(".star") // ;((img) => {
star && star.removeChild(img) // setTimeout(() => {
}, 2000) // starBox && starBox.removeChild(img)
})(img) // }, 2000)
// })(img)
addContinuousClickLive(".star-btn")
clearTimeout(sendLiveTime) clearTimeout(sendLiveTime)
sendLiveTime = setTimeout(() => { sendLiveTime = setTimeout(() => {
sendLikeVideo(liveIndex) sendLikeVideo(liveIndex)
@ -443,6 +442,8 @@ defineExpose({
}) })
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import url("@/assets/css/live.css");
::v-deep .user-in-tip { ::v-deep .user-in-tip {
position: absolute; position: absolute;
top: 40px; top: 40px;
@ -522,20 +523,26 @@ defineExpose({
width: 64px; width: 64px;
height: 64px; height: 64px;
margin-left: 20px; margin-left: 20px;
background: url(../../../assets/images/share1.png) no-repeat center; background: url(../../../assets/images/share3.png) no-repeat center;
background-size: contain; background-size: contain;
border-radius: 50%; border-radius: 50%;
} }
.star { .star-btn {
width: 64px; width: 64px;
height: 64px; height: 64px;
position: relative; position: relative;
background: url(../../../assets/images/h-like.png) no-repeat center; background: none;
background-size: 52px 52px; margin-right: 10px;
margin-left: 20px; .star {
&.active { width: 100%;
background: url(../../../assets/images/h-like1.png) no-repeat center; height: 100%;
background: url(../../../assets/images/h-like.png) no-repeat center;
background-size: 52px 52px; background-size: 52px 52px;
margin-left: 20px;
&.active {
background: url(../../../assets/images/h-like1.png) no-repeat center;
background-size: 52px 52px;
}
} }
span { span {
position: absolute; position: absolute;