douyin/src/pages/home/slide/Community.vue
2024-04-19 02:18:54 +08:00

313 lines
6.8 KiB
Vue

<template>
<div id="Community">
<ScrollList class="Scroll" v-if="state.show" :api="recommendedPost">
<template v-slot="{ list }">
<div class="search" @click="nav('/home/search')">
<div class="left">
<Icon class="icon" icon="ion:search" @click.stop="$no()" />
<span>壁纸</span>
</div>
<div class="right">搜索</div>
</div>
<WaterfallList :list="list" class="list">
<template v-slot="{ item }">
<div class="card" @click="(e) => showDetail(e, item)">
<img class="poster" v-lazy="_checkImgUrl(item.note_card?.cover?.url_default)" />
<div class="bottom">
<div class="title">
{{ item.note_card?.display_title }}
</div>
<div class="b2">
<div class="user">
<img class="avatar" :src="_checkImgUrl(item.note_card?.user?.avatar)" />
<div class="name">{{ item.note_card?.user?.nickname }}</div>
</div>
<div class="star">
<Icon icon="solar:heart-linear" />
<div class="num">
{{ item.note_card?.interact_info?.liked_count }}
</div>
</div>
</div>
</div>
</div>
</template>
</WaterfallList>
</template>
</ScrollList>
<teleport to="body">
<div class="shadow">
<div class="wrap"></div>
<AlbumDetail :detail="state.current" @close="close" />
</div>
</teleport>
</div>
</template>
<script setup>
import { reactive, ref, watch } from 'vue'
import { $no, _checkImgUrl, cloneDeep } from '@/utils'
import { recommendedPost } from '@/api/user'
import { useNav } from '@/utils/hooks/useNav'
import { Icon } from '@iconify/vue'
import WaterfallList from '@/components/WaterfallList.vue'
import ScrollList from '@/components/ScrollList.vue'
import { useBaseStore } from '@/store/pinia'
import AlbumDetail from '@/pages/other/AlbumDetail.vue'
import Mock from 'mockjs'
import $ from 'jquery'
//@click="nav('album-detail',{},item)"
const nav = useNav()
const baseStore = useBaseStore()
const props = defineProps({
active: {
type: Boolean,
default: false
}
})
const state = reactive({
show: false,
current: {
id: '',
note_card: {
interact_info: {},
cover: {},
image_list: [],
display_title: '',
user: {},
comment_list: [],
createTime: ''
}
},
d: false
})
let rect = ref({})
watch(
() => props.active,
(n) => {
if (n && !state.show) {
state.show = true
}
},
{ immediate: true }
)
function close() {
let s = $('.shadow ')
let domRect = rect.value
let t = '.3'
s.css('transition', `all ${t}s`)
s.css('top', domRect.top)
s.css('left', domRect.left)
s.css('width', domRect.width)
s.css('height', domRect.height)
let a = $('.goods-detail')
a.css('transition', `all ${t}s`)
a.css('opacity', '0')
a.css('width', '100vw')
a.css('height', '100vh')
a.css('transform', `scale(${domRect.sw},${domRect.sh})`)
a.css('transform-origin', `0 0`)
let d = $('.shadow .wrap')
d.css('transition', `all ${t}s`)
d.css('opacity', '1')
// state.d = false
setTimeout(() => {
s.css('z-index', '-100')
s.css('transition', 'all 0s')
s.css('top', '-200vh')
}, 300)
}
function showDetail(e, item) {
let data = Mock.mock({
'comment_list|3-50': [
{
name: '@cname',
text: '@cparagraph(3)'
}
]
})
item.note_card.comment_list = data.comment_list
item.note_card.createTime = Mock.Random.date('MM-dd')
item.note_card.interact_info.collect_count = Mock.Random.integer(60, 3000)
item.note_card.interact_info.share_count = Mock.Random.integer(60, 3000)
state.current = cloneDeep(item)
// console.log(state.current)
state.d = true
let domRect = e.currentTarget.getBoundingClientRect()
// console.log('e', domRect)
let s = $('.shadow ')
s.css('z-index', '1')
s.css('transition', '0s')
s.css('top', domRect.top)
s.css('left', domRect.left)
s.css('width', domRect.width)
s.css('height', domRect.height)
let t = '.3'
let d = $('.shadow .wrap')
d.empty()
d.show()
d.append($(e.currentTarget).clone())
d.css('transition', `all ${t}s`)
d.css('opacity', '1')
let sw = domRect.width / baseStore.bodyWidth
let sh = domRect.height / baseStore.bodyHeight
domRect.sw = sw
domRect.sh = sh
let a = $('.goods-detail')
a.css('opacity', '0')
a.css('width', '100vw')
a.css('height', '100vh')
a.css('transform', `scale(${domRect.sw},${domRect.sh})`)
a.css('transform-origin', `0 0`)
rect.value = domRect
setTimeout(() => {
s.css('transition', `all ${t}s`)
s.css('top', 0)
s.css('left', 0)
s.css('width', '100vw')
s.css('height', '100vh')
d.css('opacity', '0')
d.css('z-index', '-1')
a.css('transition', `all ${t}s`)
a.css('opacity', '1')
a.css('transform', `scale(1,1)`)
a.css('transform-origin', `0 0`)
})
}
</script>
<style scoped lang="less">
#Community {
font-size: 14rem;
color: white;
padding-top: var(--home-header-height);
background: rgb(21, 23, 36);
.Scroll {
height: calc(
var(--vh, 1vh) * 100 - var(--home-header-height) - var(--footer-height)
) !important;
}
@p: 1rem;
.search {
margin-left: 2vw;
width: 96vw;
box-sizing: border-box;
padding: 10rem;
border: 1px solid #646464;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16rem;
margin-bottom: 10rem;
border-radius: 8rem;
.left {
display: flex;
align-items: center;
gap: 5rem;
color: gray;
svg {
font-size: 16rem;
}
}
}
.list {
margin-left: 2vw;
width: 96vw;
}
}
.card {
border-radius: 4rem;
overflow: hidden;
background: var(--main-bg);
.poster {
display: block;
width: 100%;
object-fit: cover;
//height: 33vh;
}
.bottom {
color: gainsboro;
padding: 10rem;
.title {
font-size: 14rem;
margin-bottom: 8rem;
}
.b2 {
display: flex;
justify-content: space-between;
align-items: center;
.user {
display: flex;
font-size: 12rem;
img {
width: 15rem;
border-radius: 50%;
margin-right: 5rem;
}
}
.star {
display: flex;
align-items: center;
gap: 3rem;
svg {
font-size: 15rem;
}
.num {
font-size: 12rem;
}
}
}
}
}
.shadow {
background: var(--color-message);
position: absolute;
left: 0;
top: -200vh;
width: 100vw;
transition: all 0.3s;
overflow: hidden;
z-index: -100;
.wrap {
position: absolute;
z-index: 9999;
}
}
</style>