This commit is contained in:
zyronon 2024-03-28 17:02:36 +08:00
parent da1860cf87
commit 9ff3b92709
7 changed files with 211 additions and 3341 deletions

View File

@ -9,6 +9,22 @@
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0,user-scalable=no"
id="viewport"/>
<title>Douyin</title>
<script crossorigin="anonymous"
integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ=="
src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js"></script>
<!-- <script crossorigin="anonymous"-->
<!-- integrity="sha512-KkkY/3auRhaXDFzFMpwtZ+BrS8EBQ+GfiBxdJ9jGMi6Gg74/sYbq/IZpY593pkNjTmbeRfBwjpZo+7gcpH45Ww=="-->
<!-- src="https://lib.baomitu.com/eruda/3.0.1/eruda.min.js"></script>-->
<!-- <script>eruda.init();</script>-->
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?6f910830f5a7d8b5f7e75d8d67458a7a";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<style>
::-webkit-scrollbar {
display: none; /* Chrome Safari */
@ -41,13 +57,6 @@
}
}
</style>
<script crossorigin="anonymous"
integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ=="
src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js"></script>
<!-- <script crossorigin="anonymous"-->
<!-- integrity="sha512-KkkY/3auRhaXDFzFMpwtZ+BrS8EBQ+GfiBxdJ9jGMi6Gg74/sYbq/IZpY593pkNjTmbeRfBwjpZo+7gcpH45Ww=="-->
<!-- src="https://lib.baomitu.com/eruda/3.0.1/eruda.min.js"></script>-->
<!-- <script>eruda.init();</script>-->
</head>
<body>
<div id="app"></div>

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
<script setup>
import {onMounted, reactive, ref, watch} from "vue";
import {onMounted, onUnmounted, reactive, ref, watch} from "vue";
import GM from '../../utils'
import {
getSlideDistance,
@ -30,6 +30,7 @@ const props = defineProps({
})
const emit = defineEmits(['update:index'])
let ob = null
const judgeValue = 20
const wrapperEl = ref(null)
const state = reactive({
@ -57,6 +58,15 @@ watch(
onMounted(() => {
slideInit(wrapperEl.value, state, SlideType.HORIZONTAL)
ob = new MutationObserver(() => {
state.wrapper.childrenLength = wrapperEl.value.children.length
});
ob.observe(wrapperEl.value, {'childList': true,});
})
onUnmounted(() => {
ob.disconnect()
})
function touchStart(e) {

View File

@ -1,6 +1,6 @@
import resource from "../assets/data/resource.js";
import posts6 from "@/assets/data/posts6.json";
import {cloneDeep} from '@/utils'
import {_copy, cloneDeep} from '@/utils'
import {BASE_URL} from "@/config";
import {useBaseStore} from "@/store/pinia";
import axiosInstance from "@/utils/request";

View File

@ -39,11 +39,12 @@
</template>
</ScrollList>
<div class="shadow">
<AlbumDetail v-if="state.d"
:detail="state.current"
@close="close"/>
</div>
<teleport to="body">
<div class="shadow">
<div class="wrap"></div>
<AlbumDetail :detail="state.current" @close="close"/>
</div>
</teleport>
</div>
</template>
@ -97,20 +98,30 @@ watch(() => props.active, n => {
function close() {
let s = $('.shadow ')
let domRect = rect.value
// $('.cover-card').fadeIn()
s.css('transition', 'all .3s')
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)
$('.cover-card').css('transition', 'all .3s')
$('.cover-card').css('opacity', '1')
$('.cover-card').css('z-index', '1')
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', '-1000vh')
s.css('top', '-200vh')
}, 300)
}
@ -126,43 +137,55 @@ function test(e, item) {
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)
// console.log(state.current)
state.d = true
let domRect = e.currentTarget.getBoundingClientRect()
console.log('e', domRect)
// 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
console.log('sw', sw,sh)
// s.css('width', domRect.width)
// s.css('height', domRect.height)
domRect.sw = sw
domRect.sh = sh
s.css('width', '100vw')
s.css('height', '100vh')
s.css('transform', `scale(${sw},${sh})`)
s.css('transform-origin', `0 0`)
let $cover = $('.cover-card');
// $cover.show()
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(() => {
// w.fadeOut()
s.css('transition', 'all 5s')
// $cover.css('transition', 'all 5s')
// $cover.css('opacity', '0')
// $cover.css('z-index', '-1')
s.css('transition', `all ${t}s`)
s.css('top', 0)
s.css('left', 0)
s.css('transform', `scale(1,1)`)
s.css('transform-origin', `0 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>
@ -211,71 +234,75 @@ function test(e, item) {
width: 96vw;
}
.card {
border-radius: 4rem;
overflow: hidden;
background: var(--main-bg);
}
.poster {
width: 100%;
object-fit: cover;
//height: 33vh;
}
.card {
border-radius: 4rem;
overflow: hidden;
background: var(--main-bg);
.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;
}
}
}
}
.poster {
display: block;
width: 100%;
object-fit: cover;
//height: 33vh;
}
.shadow {
position: absolute;
left: 0;
top: 0;
width: 100vw;
transition: all .3s;
overflow: hidden;
.bottom {
color: gainsboro;
padding: 10rem;
.wrap {
position: absolute;
z-index: 9999;
.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 .3s;
overflow: hidden;
.wrap {
position: absolute;
z-index: 9999;
}
}
</style>

View File

@ -1,64 +1,62 @@
<template>
<div class="goods-detail base-page1">
<div class="goods-detail">
<header>
<Icon
@click="$emit('close')"
@click="close"
icon="material-symbols-light:arrow-back-ios-new"/>
<div class="option" @click="nav('/home/search')">
<Icon icon="jam:search"/>
</div>
</header>
<div class="slide-imgs"
@click="$emit('close')"
>
<SlideHorizontal v-model:index="state.index">
<SlideItem v-for="item in props.detail.note_card?.image_list">
<img :src="_checkImgUrl(item.info_list?.[0]?.url)" alt="">
</SlideItem>
</SlideHorizontal>
<div class="scroll" ref="scrollEl">
<div class="slide-imgs">
<SlideHorizontal v-model:index="state.index">
<SlideItem v-for="item in props.detail.note_card?.image_list">
<img :src="_checkImgUrl(item.info_list?.[0]?.url)" alt="">
</SlideItem>
</SlideHorizontal>
<div class="indicator-bar" v-if="props.detail.note_card?.image_list?.length > 1">
<div class="indicator"
:class="[i <= state.index+1 && 'active']"
v-for="i in props.detail.note_card?.image_list?.length"></div>
</div>
</div>
<div class="content">
<div class="shop">
<header>
<img class="avatar" :src="_checkImgUrl(props.detail.note_card?.user?.avatar)"/>
<div class="right">
<div class="name">{{ props.detail.note_card.user.nick_name }}</div>
<div class="r" @click="$emit('close')">关注</div>
</div>
</header>
<div class="desc">
{{ props.detail.note_card?.display_title }}
<div class="indicator-bar" v-if="props.detail.note_card?.image_list?.length > 1">
<div class="indicator"
:class="[i <= state.index+1 && 'active']"
v-for="i in props.detail.note_card?.image_list?.length"></div>
</div>
<div class="date">{{ props.detail.note_card.createTime }}</div>
</div>
<div class="card comments">
<header>
<span class="l">评论 {{ props.detail.note_card.comment_list.length }}</span>
<div class="r">
<span>查看全部</span>
<Icon class="arrow" icon="mingcute:right-line"/>
<div class="content">
<div class="shop">
<header>
<img class="avatar" :src="_checkImgUrl(props.detail.note_card?.user?.avatar)"/>
<div class="right">
<div class="name">{{ props.detail.note_card.user.nick_name }}</div>
<div class="r">关注</div>
</div>
</header>
<div class="desc">
{{ props.detail.note_card?.display_title }}
</div>
</header>
<div class="comment"
@click="$emit('close')"
v-for="i in props.detail.note_card.comment_list.slice(0,2)">
<img src="https://cdn.seovx.com/?mom=302" alt="" class="avatar">
<span>
<div class="date">{{ props.detail.note_card.createTime }}</div>
</div>
<div class="card comments">
<header>
<span class="l">评论 {{ props.detail.note_card.comment_list.length }}</span>
<div class="r">
<span>查看全部</span>
<Icon class="arrow" icon="mingcute:right-line"/>
</div>
</header>
<div class="comment"
v-for="i in props.detail.note_card.comment_list.slice(0,2)">
<img src="https://cdn.seovx.com/?mom=302" alt="" class="avatar">
<span>
{{ i.name }}{{ i.text }}
</span>
</div>
</div>
</div>
</div>
<div class="toolbar">
<div class="input-wrap">
说点什么...
@ -82,41 +80,18 @@
</div>
</div>
</div>
<div class="cover-card"
@click="$emit('close')"
>
<img class="poster" v-lazy="_checkImgUrl(props.detail.note_card?.cover?.url_default)"/>
<div class="bottom">
<div class="title">
{{ props.detail.note_card?.display_title }}
</div>
<div class="b2">
<div class="user">
<img class="avatar" :src="_checkImgUrl(props.detail.note_card?.user?.avatar)"/>
<div class="name">{{ props.detail.note_card?.user?.nickname }}</div>
</div>
<div class="star">
<Icon icon="solar:heart-linear"/>
<div class="num">{{ props.detail.note_card?.interact_info?.liked_count }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import SlideHorizontal from "@/components/slide/SlideHorizontal.vue";
import SlideItem from "@/components/slide/SlideItem.vue";
import {onMounted, reactive} from "vue";
import {reactive, ref} from "vue";
import {useNav} from "@/utils/hooks/useNav";
import {Icon} from "@iconify/vue";
import {useBaseStore} from "@/store/pinia";
import {_checkImgUrl} from "@/utils";
const nav = useNav()
const store = useBaseStore()
defineOptions({
name: 'Album-Detail'
@ -126,29 +101,27 @@ const props = defineProps({
detail: {
type: Object,
default() {
return {
"id": "",
"note_card": {
"interact_info": {},
"cover": {},
"image_list": [],
"display_title": "",
"user": {},
comment_list: [],
createTime: ''
}
}
return {}
}
}
})
const emit = defineEmits({
close: []
})
const scrollEl = ref()
const state = reactive({
index: 0,
})
onMounted(() => {
$('.cover-card').fadeOut()
})
function close() {
emit('close')
setTimeout(() => {
state.index = 0
scrollEl.value.scrollTop = 0
}, 500)
}
</script>
<style scoped lang="less">
@ -162,9 +135,11 @@ onMounted(() => {
@c: #a2a2a2;
@c2: #c0c0c0;
@red: rgb(248, 38, 74);
position: relative;
opacity: 0;
& > header {
position: absolute;
position: fixed;
left: 0;
top: 0;
width: 100%;
@ -183,6 +158,11 @@ onMounted(() => {
}
}
.scroll {
height: 100vh;
overflow: auto;
}
.slide-imgs {
position: relative;
height: 70vh;
@ -377,62 +357,6 @@ onMounted(() => {
}
}
}
.cover-card {
transition: all .3s;
position: absolute;
left: 0;
top: 0;
z-index: 10;
border-radius: 4rem;
overflow: hidden;
background: var(--main-bg);
img {
width: 100%;
}
.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;
}
}
}
}
}
}
</style>

View File

@ -472,6 +472,10 @@ export function _sleep(duration) {
})
}
export function _copy(val) {
return Utils.copy(val)
}
export function cloneDeep(val) {
return JSON.parse(JSON.stringify(val))
}