优化
This commit is contained in:
parent
32fd4fd3c6
commit
37f3b211a6
@ -13,9 +13,9 @@
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
padding: 1rem 1.8rem;
|
||||
border-radius: .3rem;
|
||||
font-size: 1.2rem;
|
||||
padding: 10rem 18rem;
|
||||
border-radius: 3rem;
|
||||
font-size: 12rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@ -84,19 +84,19 @@
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-size: 1.2rem;
|
||||
font-size: 12rem;
|
||||
display: block;
|
||||
color: black;
|
||||
padding: 1px .6rem;
|
||||
border-radius: 1rem;
|
||||
padding: 1rem 6rem;
|
||||
border-radius: 10rem;
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
.badge2 {
|
||||
transform: scale(.9);
|
||||
font-size: 1.2rem;
|
||||
font-size: 12rem;
|
||||
color: black;
|
||||
@width: 1.8rem;
|
||||
@width: 18rem;
|
||||
width: @width;
|
||||
height: @width;
|
||||
display: flex;
|
||||
@ -112,7 +112,7 @@ p {
|
||||
}
|
||||
|
||||
.line {
|
||||
height: 1px;
|
||||
height: 1rem;
|
||||
background: @line-color2;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
946
src/components/UserPanel.vue
Normal file
946
src/components/UserPanel.vue
Normal file
@ -0,0 +1,946 @@
|
||||
<template>
|
||||
<div id="UserPanel">
|
||||
<div class="main"
|
||||
ref="scroll"
|
||||
@touchstart="touchStart($event)"
|
||||
@touchmove="touchMove($event)"
|
||||
@touchend="touchEnd($event)">
|
||||
<header ref="header"
|
||||
:style='{backgroundImage: `url(${state.localAuthor.cover})`}'
|
||||
@click="state.previewImg = state.localAuthor.cover">
|
||||
<div class="avatar-wrapper">
|
||||
<img v-lazy="Utils.$imgPreview(state.localAuthor.avatar)" class="avatar"
|
||||
@click="state.previewImg = state.localAuthor.avatar">
|
||||
<div class="description">
|
||||
<div class="name f22 mb1r">{{ state.localAuthor.nickname }}</div>
|
||||
<div class="certification" v-if="state.localAuthor.certification ">
|
||||
<img src="@/assets/img/icon/me/certification.webp">
|
||||
{{ state.localAuthor.certification }}
|
||||
</div>
|
||||
<div class="number" v-else>
|
||||
<span>抖音号:{{ state.localAuthor.unique_id }}</span>
|
||||
<img src="@/assets/img/icon/me/copy.png" alt="" @click.stop="Utils.copy">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="info">
|
||||
<div class="heat">
|
||||
<div class="text">
|
||||
<span class="num">{{ Utils.formatNumber(state.localAuthor.aweme_count) }}</span>
|
||||
<span>获赞</span>
|
||||
</div>
|
||||
<div class="text">
|
||||
<span class="num">{{ state.localAuthor.following_count }}</span>
|
||||
<span>关注</span>
|
||||
</div>
|
||||
<div class="text">
|
||||
<span class="num">{{ Utils.formatNumber(state.localAuthor.follower_count) }}</span>
|
||||
<span>粉丝</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="signature f12" v-if="state.localAuthor.desc">
|
||||
<div class="text" v-html="state.localAuthor.desc"></div>
|
||||
</div>
|
||||
|
||||
<div class="more">
|
||||
<div class="age item" v-if="state.localAuthor.birthday">
|
||||
<img v-if="state.localAuthor.sex === '0'" src="@/assets/img/icon/me/woman.png" alt="">
|
||||
<img v-if="state.localAuthor.sex === '1'" src="@/assets/img/icon/me/man.png" alt="">
|
||||
<span>{{ Utils.filterAge(state.localAuthor.birthday) }}岁</span>
|
||||
</div>
|
||||
<div class="item" v-if="state.localAuthor.province || state.localAuthor.city">
|
||||
{{ state.localAuthor.province }}
|
||||
<template v-if="state.localAuthor.province && state.localAuthor.city">
|
||||
-
|
||||
</template>
|
||||
{{ state.localAuthor.city }}
|
||||
</div>
|
||||
<div class="item" v-if="state.localAuthor.school?.name">
|
||||
{{ state.localAuthor.school?.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="other">
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/me/shopping-cart-white.png" alt="">
|
||||
<div class="right">
|
||||
<div class="top">抖音商城</div>
|
||||
<div class="bottom">发现超值好物</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/me/music-white.png" alt="">
|
||||
<div class="right">
|
||||
<div class="top">我的音乐</div>
|
||||
<div class="bottom">已收藏20首</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-buttons">
|
||||
<div class="follow-display">
|
||||
<div class="follow-wrapper" :class="state.localAuthor.is_follow ? 'follow-wrapper-followed' : ''">
|
||||
<div class="no-follow" @click="state.localAuthor.is_follow = true">
|
||||
<img src="@/assets/img/icon/add-white.png" alt="">
|
||||
<span>关注</span>
|
||||
</div>
|
||||
<div class="followed">
|
||||
<div class="l-button" @click="$emit('showFollowSetting2')">
|
||||
<span>已关注</span>
|
||||
<img src="@/assets/img/icon/arrow-up-white.png" alt="">
|
||||
</div>
|
||||
<div class="l-button" @click="$nav('/message/chat')">
|
||||
<span>私信</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="option"
|
||||
:class="state.isShowRecommend?'option-recommend':''"
|
||||
@click="state.toggleRecommend">
|
||||
<img v-if="state.loadings.showRecommend" class="loading" src="@/assets/img/icon/loading-gray.png"
|
||||
alt="">
|
||||
<img v-else class="arrow" src="@/assets/img/icon/arrow-up-white.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recommend" :class="{hidden:!state.isShowRecommend}">
|
||||
<div class="title">
|
||||
<div class="left">
|
||||
<span>你可能感兴趣</span>
|
||||
<img src="@/assets/img/icon/about-gray.png">
|
||||
</div>
|
||||
<div class="right" @click="$nav('/people/find-acquaintance')">
|
||||
<span>查看更多</span>
|
||||
<back direction="right"></back>
|
||||
</div>
|
||||
</div>
|
||||
<div class="friends"
|
||||
@touchstart="friendsTouchStart"
|
||||
@touchend="friendsTouchEnd">
|
||||
<div class="friend" v-for="item in friends.all">
|
||||
<img :style="item.select?'opacity: .5;':''" class="avatar" :src="$imgPreview(item.avatar)" alt="">
|
||||
<span class="name">{{ item.name }}</span>
|
||||
<span class="tips">可能感兴趣的人</span>
|
||||
<b-button type="primary">关注</b-button>
|
||||
<div class="close">
|
||||
<back img="close" scale=".6"></back>
|
||||
</div>
|
||||
</div>
|
||||
<div class="more" @click="$nav('/people/find-acquaintance')">
|
||||
<div class="notice">
|
||||
<div>点击查看</div>
|
||||
<div>更多好友</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="total">
|
||||
作品 62
|
||||
<img class="arrow" src="@/assets/img/icon/arrow-up-white.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="videos">
|
||||
<Posters v-if="state.videos.my.total !== -1" :list="state.videos.my.list"></Posters>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, reactive} from "vue";
|
||||
import Utils from "@/utils";
|
||||
import {useNav} from "@/utils/hooks/useNav";
|
||||
import {useStore} from "vuex";
|
||||
import resource from "@/assets/data/resource";
|
||||
import Posters from '@/components/Posters'
|
||||
|
||||
const $nav = useNav()
|
||||
const store = useStore()
|
||||
const props = defineProps({
|
||||
author: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
isOnThisPage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const friends = () => store.friends
|
||||
const state = reactive({
|
||||
isShowRecommend: false,//是否显示推荐
|
||||
isLoadRecommendFriends: false,//是否已经加载了显示推荐,直接判断friends.all数据长度的话,没有一开始的加载动画
|
||||
previewImg: '',
|
||||
contentIndex: 0,
|
||||
baseActiveIndex: 0,
|
||||
tabContents: [],
|
||||
floatFixed: false,
|
||||
floatShowName: false,
|
||||
isScroll: false,
|
||||
isMoreFunction: false,
|
||||
showFollowSetting: false,
|
||||
refs: {
|
||||
header: null,
|
||||
headerHeight: 0,
|
||||
descHeight: 0,
|
||||
videoSlideHeight: 0,
|
||||
maxSlideHeight: 0
|
||||
},
|
||||
videoItemHeight: 0,
|
||||
startLocationY: 0,
|
||||
fixedLocationY: 0,
|
||||
lastMoveYDistance: 0,
|
||||
canTransformY: 0,
|
||||
startTime: 0,
|
||||
floatHeight: 46,
|
||||
videos: {
|
||||
my: {
|
||||
list: [],
|
||||
total: -1,
|
||||
pageNo: 0
|
||||
},
|
||||
private: {
|
||||
list: [],
|
||||
total: -1
|
||||
},
|
||||
like: {
|
||||
list: [],
|
||||
total: -1
|
||||
},
|
||||
collect: {
|
||||
video: {
|
||||
list: [],
|
||||
total: -1,
|
||||
},
|
||||
audio: {
|
||||
list: [],
|
||||
total: -1,
|
||||
}
|
||||
},
|
||||
},
|
||||
pageSize: 15,
|
||||
initSlideHeight: 0,
|
||||
loadings: {
|
||||
loading0: false,
|
||||
loading1: false,
|
||||
loading2: false,
|
||||
loading3: false,
|
||||
showRecommend: false
|
||||
},
|
||||
tempScroll: false,
|
||||
acceleration: 1.2,
|
||||
sprint: 15,
|
||||
canScroll: true,
|
||||
localAuthor: resource.videos[0].author
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
state.videos.my.list = resource.my
|
||||
state.videos.my.total = resource.my.length
|
||||
})
|
||||
|
||||
function friendsTouchStart() {
|
||||
}
|
||||
|
||||
function friendsTouchEnd() {
|
||||
}
|
||||
|
||||
function touchStart() {
|
||||
}
|
||||
|
||||
function touchMove() {
|
||||
}
|
||||
|
||||
function touchEnd() {
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import "@/assets/less/index";
|
||||
|
||||
.fade1-enter-active,
|
||||
.fade1-leave-active {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.fade1-enter-from,
|
||||
.fade1-leave-to {
|
||||
transform: translateY(10px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.FromBottomDialog {
|
||||
left: inherit;
|
||||
}
|
||||
|
||||
|
||||
#UserPanel {
|
||||
position: fixed;
|
||||
background: @main-bg;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-size: 14rem;
|
||||
|
||||
.preview-img {
|
||||
z-index: 3;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
background: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.resource {
|
||||
width: 100vw;
|
||||
max-height: 100vw;
|
||||
}
|
||||
|
||||
.download {
|
||||
position: absolute;
|
||||
bottom: 20rem;
|
||||
right: 20rem;
|
||||
padding: 3rem;
|
||||
background: @second-btn-color-tran;
|
||||
width: 20rem;
|
||||
}
|
||||
}
|
||||
|
||||
.mask {
|
||||
background: #0000004f;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.main {
|
||||
.notice {
|
||||
font-size: 12rem;
|
||||
height: 40rem;
|
||||
color: @second-text-color;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
height: 12rem;
|
||||
margin-right: 5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.collect {
|
||||
padding: 7rem;
|
||||
|
||||
.video {
|
||||
background: @active-main-bg;
|
||||
border-radius: 5rem;
|
||||
padding: 10rem;
|
||||
margin-bottom: 7rem;
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10rem;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: gainsboro;
|
||||
|
||||
img {
|
||||
height: 20rem;
|
||||
margin-right: 5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: @second-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
display: grid;
|
||||
grid-template-columns: 33.33% 33.33% 33.33%;
|
||||
|
||||
.item {
|
||||
height: calc(33.33vw * 1.3);
|
||||
padding: 2rem;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.poster {
|
||||
border-radius: 4rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.num {
|
||||
color: white;
|
||||
position: absolute;
|
||||
bottom: 5rem;
|
||||
left: 5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14rem;
|
||||
|
||||
.love {
|
||||
width: 14rem;
|
||||
height: 14rem;
|
||||
margin-right: 5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.audio {
|
||||
background: @active-main-bg;
|
||||
border-radius: 5rem;
|
||||
padding: 10rem;
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10rem;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: gainsboro;
|
||||
|
||||
img {
|
||||
height: 15rem;
|
||||
margin-right: 5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: @second-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
display: grid;
|
||||
grid-template-columns: 33.33% 33.33% 33.33%;
|
||||
|
||||
.item {
|
||||
padding: 2rem;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.poster {
|
||||
border-radius: 4rem;
|
||||
width: 100%;
|
||||
height: calc((100vw - 34rem) / 3);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-top: 5rem;
|
||||
color: @second-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
color: white;
|
||||
height: 240rem;
|
||||
background-image: url('@/assets/img/header-bg.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
.avatar-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
bottom: 35rem;
|
||||
left: 20rem;
|
||||
//margin-top: -20rem;
|
||||
//transform: translateY(-20rem);
|
||||
|
||||
.avatar {
|
||||
background: white;
|
||||
padding: 2px;
|
||||
border-radius: 50%;
|
||||
width: 80rem;
|
||||
height: 80rem;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 12rem;
|
||||
color: white;
|
||||
margin-left: 15rem;
|
||||
|
||||
.number, .certification {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
width: 12rem;
|
||||
margin-left: 5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.number {
|
||||
color: @second-text-color;
|
||||
|
||||
img {
|
||||
margin-left: 5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.certification {
|
||||
img {
|
||||
width: 14rem;
|
||||
margin-right: 5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
background: @main-bg;
|
||||
padding: 0 20rem 15rem 20rem;
|
||||
border-radius: 10rem 10rem 0 0;
|
||||
margin-top: -20rem;
|
||||
|
||||
.heat {
|
||||
padding: 15rem 0;
|
||||
color: @second-text-color;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.text {
|
||||
font-size: 12rem;
|
||||
margin-right: 18rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.num {
|
||||
color: white;
|
||||
font-size: 16rem;
|
||||
font-weight: bold;
|
||||
margin-right: 5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.signature {
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5rem;
|
||||
|
||||
img {
|
||||
height: 12rem;
|
||||
margin-left: 6rem;
|
||||
}
|
||||
|
||||
.text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.more {
|
||||
margin-top: 10rem;
|
||||
margin-bottom: 20rem;
|
||||
color: @second-text-color;
|
||||
display: flex;
|
||||
|
||||
.item {
|
||||
padding: 2rem 5rem;
|
||||
border-radius: 2rem;
|
||||
background: @second-btn-color-tran;
|
||||
font-size: 10rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 5rem;
|
||||
|
||||
img {
|
||||
height: 10rem;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.other {
|
||||
display: flex;
|
||||
margin-bottom: 20rem;
|
||||
|
||||
.item {
|
||||
margin-right: 25rem;
|
||||
display: flex;
|
||||
|
||||
img {
|
||||
margin-right: 8rem;
|
||||
border-radius: 4rem;
|
||||
background: @second-btn-color-tran;
|
||||
padding: 8rem;
|
||||
height: 22rem;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
|
||||
.top {
|
||||
color: white;
|
||||
font-size: 14rem;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
color: @second-text-color;
|
||||
font-size: 12rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.my-buttons {
|
||||
margin-top: 20rem;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
@width: 36rem;
|
||||
|
||||
.follow-display {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
|
||||
.follow-wrapper {
|
||||
width: 200%;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
transition: all .3s ease;
|
||||
|
||||
&.follow-wrapper-followed {
|
||||
transform: translate3d(-50%, 0, 0);
|
||||
}
|
||||
|
||||
.no-follow {
|
||||
width: calc(100% - 5rem);
|
||||
color: white;
|
||||
border-radius: 4rem;
|
||||
background: @primary-btn-color;
|
||||
height: @width;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 5rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
span {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.followed {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
|
||||
.l-button {
|
||||
color: white;
|
||||
border-radius: 4rem;
|
||||
background: @second-btn-color;
|
||||
height: @width;
|
||||
width: 50%;
|
||||
margin-right: 5rem;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
span {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
img {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
@width: 14rem;
|
||||
width: @width;
|
||||
height: @width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.option {
|
||||
position: relative;
|
||||
width: @width;
|
||||
height: @width;
|
||||
font-size: 12rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4rem;
|
||||
background: @second-btn-color;
|
||||
color: white;
|
||||
|
||||
&.option-recommend {
|
||||
.arrow {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
@width: 12rem;
|
||||
width: @width;
|
||||
height: @width;
|
||||
animation: rotate .6s linear infinite;
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0deg)
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.arrow {
|
||||
transition: transform .3s ease;
|
||||
transform: rotate(180deg);
|
||||
@width: 16rem;
|
||||
width: @width;
|
||||
height: @width;
|
||||
}
|
||||
}
|
||||
|
||||
.recommend {
|
||||
transition: all .3s ease;
|
||||
height: 220rem;
|
||||
overflow: hidden;
|
||||
|
||||
&.hidden {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 0 20rem 0 20rem;
|
||||
font-size: 12rem;
|
||||
color: @second-text-color;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
img {
|
||||
margin-left: 3rem;
|
||||
width: 13rem;
|
||||
height: 13rem;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.friends {
|
||||
padding-left: 20rem;
|
||||
margin-top: 10rem;
|
||||
display: flex;
|
||||
overflow-x: scroll;
|
||||
|
||||
.friend {
|
||||
position: relative;
|
||||
background: @second-btn-color-tran;
|
||||
margin-right: 10rem;
|
||||
padding: 10rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.avatar {
|
||||
@width: 100rem;
|
||||
border-radius: 50%;
|
||||
width: @width;
|
||||
height: @width;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-top: 10rem;
|
||||
font-size: 12rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 5rem;
|
||||
font-size: 12rem;
|
||||
color: @second-text-color;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin-top: 10rem;
|
||||
width: 150rem;
|
||||
height: 26rem;
|
||||
font-size: 12rem;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 2rem;
|
||||
right: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.more {
|
||||
.notice {
|
||||
width: 100rem;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: @second-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.total {
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 20rem;
|
||||
|
||||
img {
|
||||
transform: rotate(180deg);
|
||||
margin-left: 5rem;
|
||||
width: 12rem;
|
||||
height: 12rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.videos {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.float {
|
||||
position: fixed;
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 46rem;
|
||||
padding: 0 15rem;
|
||||
background: transparent;
|
||||
transition: all .2s;
|
||||
|
||||
.center {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
position: absolute;
|
||||
color: white;
|
||||
}
|
||||
|
||||
&.fixed {
|
||||
background: @main-bg;
|
||||
|
||||
img {
|
||||
background: @main-bg !important;
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
img {
|
||||
transform: rotate(180deg);
|
||||
border-radius: 50%;
|
||||
background: rgba(82, 80, 80, 0.5);
|
||||
padding: 6rem;
|
||||
width: 18rem;
|
||||
}
|
||||
}
|
||||
|
||||
.follow-btn {
|
||||
color: white;
|
||||
position: absolute;
|
||||
font-size: 12rem;
|
||||
padding: 3rem 12rem;
|
||||
border-radius: 2rem;
|
||||
right: 60rem;
|
||||
background: @primary-btn-color;
|
||||
|
||||
&.followed {
|
||||
background: @second-btn-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
color: white;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
.request {
|
||||
font-size: 12rem;
|
||||
height: 26rem;
|
||||
display: flex;
|
||||
padding-right: 13rem;
|
||||
padding-left: 5rem;
|
||||
align-items: center;
|
||||
border-radius: 20rem;
|
||||
background: rgba(82, 80, 80, 0.5);
|
||||
|
||||
img {
|
||||
padding: 6rem;
|
||||
width: 18rem;
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
margin-left: 15rem;
|
||||
border-radius: 50%;
|
||||
background: rgba(82, 80, 80, 0.5);
|
||||
padding: 6rem;
|
||||
width: 18rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
684
src/components/UserPanel2.vue
Normal file
684
src/components/UserPanel2.vue
Normal file
@ -0,0 +1,684 @@
|
||||
<template>
|
||||
<div id="UserPanel">
|
||||
<div class="scroll"
|
||||
ref="scroll"
|
||||
@touchstart="touchStart($event)"
|
||||
@touchmove="touchMove($event)"
|
||||
@touchend="touchEnd($event)">
|
||||
<div ref="desc" class="desc">
|
||||
<header ref="header"
|
||||
:style='{backgroundImage: `url(${state.localAuthor.cover})`}'
|
||||
@click="state.previewImg = state.localAuthor.cover"></header>
|
||||
<div class="detail">
|
||||
<div class="detail-wrapper">
|
||||
<div class="head">
|
||||
<img v-lazy="Utils.$imgPreview(state.localAuthor.avatar)" class="head-image"
|
||||
@click="state.previewImg = state.localAuthor.avatar">
|
||||
<div class="heat">
|
||||
<div class="text">
|
||||
<span>获赞</span>
|
||||
<span class="num">{{ Utils.formatNumber(state.localAuthor.aweme_count) }}</span>
|
||||
</div>
|
||||
<div class="text">
|
||||
<span>关注</span>
|
||||
<span class="num">{{ state.localAuthor.following_count }}</span>
|
||||
</div>
|
||||
<div class="text">
|
||||
<span>粉丝</span>
|
||||
<span class="num">{{ Utils.formatNumber(state.localAuthor.follower_count) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description">
|
||||
<p class="name f22 mt1r mb1r">{{ state.localAuthor.nickname }}</p>
|
||||
<div class="certification" v-if="state.localAuthor.certification ">
|
||||
<img src="../../assets/img/icon/me/certification.webp">
|
||||
{{ state.localAuthor.certification }}
|
||||
</div>
|
||||
<div class="number" v-else>
|
||||
<span>抖音号:{{ state.localAuthor.unique_id }}</span>
|
||||
<img src="../../assets/img/icon/me/copy.png" alt="" @click.stop="copy">
|
||||
</div>
|
||||
<div class="signature f12" v-if="state.localAuthor.desc">
|
||||
<div class="text" v-html="state.localAuthor.desc"></div>
|
||||
</div>
|
||||
<div class="more">
|
||||
<div class="age item" v-if="state.localAuthor.birthday">
|
||||
<img v-if="state.localAuthor.sex === '0'" src="../../assets/img/icon/me/woman.png" alt="">
|
||||
<img v-if="state.localAuthor.sex === '1'" src="../../assets/img/icon/me/man.png" alt="">
|
||||
<span>{{ filterAge(state.localAuthor.birthday) }}岁</span>
|
||||
</div>
|
||||
<div class="item" v-if="state.localAuthor.province || state.localAuthor.city">
|
||||
{{ state.localAuthor.province }}
|
||||
<template v-if="state.localAuthor.province && state.localAuthor.city">
|
||||
-
|
||||
</template>
|
||||
{{ state.localAuthor.city }}
|
||||
</div>
|
||||
<div class="item" v-if="state.localAuthor.school?.name">
|
||||
{{ state.localAuthor.school?.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="other">
|
||||
<div class="item">
|
||||
<img src="../../assets/img/icon/me/shopping-cart-white.png" alt="">
|
||||
<div class="right">
|
||||
<div class="top">抖音商城</div>
|
||||
<div class="bottom">发现超值好物</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img src="../../assets/img/icon/me/music-white.png" alt="">
|
||||
<div class="right">
|
||||
<div class="top">我的音乐</div>
|
||||
<div class="bottom">已收藏20首</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-buttons">
|
||||
<div class="follow-display">
|
||||
<div class="follow-wrapper" :class="state.localAuthor.is_follow ? 'follow-wrapper-followed' : ''">
|
||||
<div class="no-follow" @click="state.localAuthor.is_follow = true">
|
||||
<img src="../../assets/img/icon/add-white.png" alt="">
|
||||
<span>关注</span>
|
||||
</div>
|
||||
<div class="followed">
|
||||
<div class="l-button" @click="$emit('showFollowSetting2')">
|
||||
<span>已关注</span>
|
||||
<img src="../../assets/img/icon/arrow-up-white.png" alt="">
|
||||
</div>
|
||||
<div class="l-button" @click="$nav('/message/chat')">
|
||||
<span>私信</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="option"
|
||||
:class="state.isShowRecommend?'option-recommend':''"
|
||||
@click="toggleRecommend">
|
||||
<img v-if="loadings.showRecommend" class="loading" src="../../assets/img/icon/loading-gray.png" alt="">
|
||||
<img v-else class="arrow" src="../../assets/img/icon/arrow-up-white.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="recommend" :class="{hidden:!state.isShowRecommend}">
|
||||
<div class="title">
|
||||
<div class="left">
|
||||
<span>你可能感兴趣</span>
|
||||
<img src="../../assets/img/icon/about-gray.png">
|
||||
</div>
|
||||
<div class="right" @click="$nav('/people/find-acquaintance')">
|
||||
<span>查看更多</span>
|
||||
<back direction="right"></back>
|
||||
</div>
|
||||
</div>
|
||||
<div class="friends"
|
||||
@touchstart="friendsTouchStart"
|
||||
@touchend="friendsTouchEnd">
|
||||
<div class="friend" v-for="item in state.friends.all">
|
||||
<img :style="item.select?'opacity: .5;':''" class="avatar" :src="$imgPreview(item.avatar)" alt="">
|
||||
<span class="name">{{ item.name }}</span>
|
||||
<span class="tips">可能感兴趣的人</span>
|
||||
<b-button type="primary">关注</b-button>
|
||||
<div class="close">
|
||||
<back img="close" scale=".6"></back>
|
||||
</div>
|
||||
</div>
|
||||
<div class="more" @click="$nav('/people/find-acquaintance')">
|
||||
<div class="notice">
|
||||
<div>点击查看</div>
|
||||
<div>更多好友</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {nextTick, reactive} from "vue";
|
||||
import Utils from "@/utils";
|
||||
import {useNav} from "@/utils/hooks/useNav";
|
||||
|
||||
const $nav = useNav()
|
||||
const props = defineProps({
|
||||
author: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
isOnThisPage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
const state = reactive({
|
||||
isShowRecommend: false,//是否显示推荐
|
||||
isLoadRecommendFriends: false,//是否已经加载了显示推荐,直接判断friends.all数据长度的话,没有一开始的加载动画
|
||||
previewImg: '',
|
||||
contentIndex: 0,
|
||||
baseActiveIndex: 0,
|
||||
tabContents: [],
|
||||
floatFixed: false,
|
||||
floatShowName: false,
|
||||
isScroll: false,
|
||||
isMoreFunction: false,
|
||||
showFollowSetting: false,
|
||||
refs: {
|
||||
header: null,
|
||||
headerHeight: 0,
|
||||
descHeight: 0,
|
||||
videoSlideHeight: 0,
|
||||
maxSlideHeight: 0
|
||||
},
|
||||
videoItemHeight: 0,
|
||||
startLocationY: 0,
|
||||
fixedLocationY: 0,
|
||||
lastMoveYDistance: 0,
|
||||
canTransformY: 0,
|
||||
startTime: 0,
|
||||
floatHeight: 46,
|
||||
videos: {
|
||||
my: {
|
||||
list: [],
|
||||
total: -1,
|
||||
pageNo: 0
|
||||
},
|
||||
private: {
|
||||
list: [],
|
||||
total: -1
|
||||
},
|
||||
like: {
|
||||
list: [],
|
||||
total: -1
|
||||
},
|
||||
collect: {
|
||||
video: {
|
||||
list: [],
|
||||
total: -1,
|
||||
},
|
||||
audio: {
|
||||
list: [],
|
||||
total: -1,
|
||||
}
|
||||
},
|
||||
},
|
||||
pageSize: 15,
|
||||
initSlideHeight: 0,
|
||||
loadings: {
|
||||
loading0: false,
|
||||
loading1: false,
|
||||
loading2: false,
|
||||
loading3: false,
|
||||
showRecommend: false
|
||||
},
|
||||
tempScroll: false,
|
||||
acceleration: 1.2,
|
||||
sprint: 15,
|
||||
canScroll: true,
|
||||
localAuthor: {}
|
||||
})
|
||||
|
||||
function back() {
|
||||
if (this.$route.path === '/me/uploader') {
|
||||
this.$back()
|
||||
} else {
|
||||
this.$emit('back')
|
||||
}
|
||||
}
|
||||
|
||||
function copy() {
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('readonly', 'readonly');
|
||||
input.setAttribute('value', state.localAuthor.unique_id);
|
||||
document.body.appendChild(input);
|
||||
input.setSelectionRange(0, 9999);
|
||||
if (document.execCommand('copy')) {
|
||||
document.execCommand('copy');
|
||||
this.$notice('已复制')
|
||||
}
|
||||
document.body.removeChild(input);
|
||||
}
|
||||
|
||||
function cancelFollow() {
|
||||
state.localAuthor.is_follow = false
|
||||
}
|
||||
|
||||
function changeIndicatorIndex(index) {
|
||||
this.$refs.Indicator.changeIndex(index)
|
||||
}
|
||||
|
||||
async function getAuthor() {
|
||||
this.changeIndex(0, null)
|
||||
let res = await this.$api.user.author({id: this.author.id})
|
||||
// let res = await this.$api.user.author({id: '54884802577'})
|
||||
if (res.code === this.SUCCESS) {
|
||||
state.localAuthor = {...state.localAuthor, ...res.data}
|
||||
this.refreshDescHeight()
|
||||
}
|
||||
}
|
||||
|
||||
function toggleRecommend() {
|
||||
if (this.isLoadRecommendFriends) {
|
||||
state.isShowRecommend = !state.isShowRecommend
|
||||
this.refreshDescHeight()
|
||||
} else {
|
||||
this.loadings.showRecommend = true
|
||||
setTimeout(() => {
|
||||
this.loadings.showRecommend = false
|
||||
this.isLoadRecommendFriends = true
|
||||
state.isShowRecommend = !state.isShowRecommend
|
||||
this.refreshDescHeight()
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
function refreshDescHeight() {
|
||||
//这里nextTick不生效
|
||||
setTimeout(() => {
|
||||
let desc = $('.desc')
|
||||
this.refs.descHeight = desc.height()
|
||||
this.initSlideHeight = this.bodyHeight - 50 - this.refs.descHeight
|
||||
this.canTransformY = this.refs.descHeight - this.floatHeight
|
||||
}, 300)
|
||||
}
|
||||
|
||||
function friendsTouchStart() {
|
||||
this.$emit('toggleCanMove', false)
|
||||
}
|
||||
|
||||
function friendsTouchEnd() {
|
||||
this.$emit('toggleCanMove', true)
|
||||
}
|
||||
|
||||
function followButton() {
|
||||
if (state.localAuthor.is_follow) {
|
||||
this.$nav('/message/chat')
|
||||
} else {
|
||||
state.localAuthor.is_follow = true
|
||||
}
|
||||
}
|
||||
|
||||
function setLoadingFalse() {
|
||||
this.loadings.loading0 = false
|
||||
this.loadings.loading1 = false
|
||||
this.loadings.loading2 = false
|
||||
this.loadings.loading3 = false
|
||||
}
|
||||
|
||||
function click(e) {
|
||||
if (this.baseActiveIndex === 0) return
|
||||
if (this.baseActiveIndex === 1) {
|
||||
this.baseActiveIndex = 0
|
||||
this.$stopPropagation(e)
|
||||
}
|
||||
}
|
||||
|
||||
async function getScrollAreaHeight(index = this.contentIndex) {
|
||||
let scrollAreaHeight = 0
|
||||
if (index === 3) {
|
||||
await nextTick(async () => {
|
||||
scrollAreaHeight = this.$refs.collect.clientHeight + 60 + 40
|
||||
})
|
||||
} else {
|
||||
scrollAreaHeight = Math.ceil(this.videos[Object.keys(this.videos)[index]].list.length / 3) * this.videoItemHeight
|
||||
switch (index) {
|
||||
case 0:
|
||||
scrollAreaHeight += 60
|
||||
break
|
||||
case 1:
|
||||
scrollAreaHeight += 60 + state.localAuthor.is_private === 1 ? 0 : 40
|
||||
break
|
||||
case 2:
|
||||
scrollAreaHeight += 60 + 40
|
||||
break
|
||||
}
|
||||
}
|
||||
return scrollAreaHeight
|
||||
}
|
||||
|
||||
async function changeIndex(newVal, oldVal) {
|
||||
// debugger
|
||||
if (this.loadings['loading' + newVal]) return
|
||||
let videoOb = this.videos[Object.keys(this.videos)[newVal]]
|
||||
if (newVal === 3) {
|
||||
if (videoOb.video.total === -1) {
|
||||
this.loadings['loading' + newVal] = true
|
||||
let res = await this.$api.videos.collect({pageNo: this.videos.collect.pageNo, pageSize: this.pageSize,})
|
||||
if (res.code === this.SUCCESS) this.videos.collect = res.data
|
||||
}
|
||||
} else {
|
||||
if (videoOb.total === -1) {
|
||||
this.loadings['loading' + newVal] = true
|
||||
let res
|
||||
switch (newVal) {
|
||||
case 0:
|
||||
res = await this.$api.videos.my({pageNo: this.videos.my.pageNo, pageSize: this.pageSize,})
|
||||
if (res.code === this.SUCCESS) this.videos.my = res.data
|
||||
break
|
||||
case 1:
|
||||
res = await this.$api.videos.private({pageNo: this.videos.private.pageNo, pageSize: this.pageSize,})
|
||||
if (res.code === this.SUCCESS) this.videos.private = res.data
|
||||
break
|
||||
case 2:
|
||||
res = await this.$api.videos.like({pageNo: this.videos.like.pageNo, pageSize: this.pageSize,})
|
||||
if (res.code === this.SUCCESS) this.videos.like = res.data
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setLoadingFalse()
|
||||
|
||||
let scrollAreaHeight = await this.getScrollAreaHeight(newVal)
|
||||
|
||||
if (oldVal !== null) {
|
||||
let transformY = this.getTransform(this.$refs.scroll)
|
||||
let screenSlideHeight = this.initSlideHeight + Math.abs(transformY)
|
||||
if (this.isScroll) {
|
||||
this.refs.videoSlideHeight = this.refs.maxSlideHeight
|
||||
} else {
|
||||
if (scrollAreaHeight > screenSlideHeight) {
|
||||
this.refs.videoSlideHeight = this.refs.maxSlideHeight
|
||||
} else {
|
||||
this.refs.videoSlideHeight = screenSlideHeight
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (scrollAreaHeight < this.refs.maxSlideHeight) {
|
||||
this.refs.videoSlideHeight = scrollAreaHeight
|
||||
} else {
|
||||
this.refs.videoSlideHeight = this.refs.maxSlideHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadMoreData() {
|
||||
if (this.loadings['loading' + this.contentIndex]) return
|
||||
console.log('到底了')
|
||||
let videoOb = this.videos[Object.keys(this.videos)[this.contentIndex]]
|
||||
if (videoOb.total > videoOb.list.length) {
|
||||
videoOb.pageNo++
|
||||
this.loadings['loading' + this.contentIndex] = true
|
||||
let res
|
||||
switch (this.contentIndex) {
|
||||
case 0:
|
||||
res = await this.$api.videos.my({pageNo: videoOb.pageNo, pageSize: this.pageSize,})
|
||||
break
|
||||
case 1:
|
||||
res = await this.$api.videos.private({pageNo: videoOb.pageNo, pageSize: this.pageSize,})
|
||||
break
|
||||
case 2:
|
||||
res = await this.$api.videos.like({pageNo: videoOb.pageNo, pageSize: this.pageSize,})
|
||||
break
|
||||
case 3:
|
||||
res = await this.$api.videos.collect({pageNo: videoOb.pageNo, pageSize: this.pageSize,})
|
||||
break
|
||||
}
|
||||
this.loadings['loading' + this.contentIndex] = false
|
||||
if (res.code === this.SUCCESS) {
|
||||
videoOb.list = videoOb.list.concat(res.data.list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function touchStart(e) {
|
||||
this.$refs.scroll.style.transition = 'none'
|
||||
this.fixedLocationY = this.startLocationY = e.touches[0].pageY
|
||||
this.startTime = Date.now()
|
||||
}
|
||||
|
||||
function move(e) {
|
||||
// (!this.isScroll) && e.preventDefault();
|
||||
}
|
||||
|
||||
async function scroll() {
|
||||
if (this.isScroll) {
|
||||
let SlideItems = document.querySelectorAll('.SlideItem')
|
||||
let SlideItem = SlideItems[this.contentIndex]
|
||||
if (SlideItem.scrollHeight - SlideItem.clientHeight < SlideItem.scrollTop + 60) {
|
||||
this.loadMoreData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function touchMove(e) {
|
||||
if (!this.canScroll) return
|
||||
let moveDistance = e.touches[0].pageY - this.startLocationY
|
||||
let pageMoveDistance = this.lastMoveYDistance + moveDistance * this.acceleration
|
||||
// console.log('move-pageMoveDistance', pageMoveDistance)
|
||||
// console.log('move-moveDistance', moveDistance)
|
||||
//手指往上划,是负
|
||||
|
||||
if (this.isScroll) {
|
||||
let SlideItems = document.querySelectorAll('.SlideItem')
|
||||
let SlideItem = SlideItems[this.contentIndex]
|
||||
if (SlideItem.scrollTop === 0) {
|
||||
this.tempScroll = this.isScroll = false
|
||||
this.startLocationY = e.touches[0].pageY
|
||||
this.lastMoveYDistance = -this.canTransformY
|
||||
}
|
||||
} else {
|
||||
//手指往下划,页面向上动
|
||||
if (moveDistance > 0) {
|
||||
if (pageMoveDistance > 0) {
|
||||
this.$refs.scroll.style.transform = `translate3d(0,0,0)`
|
||||
if (pageMoveDistance < 400) {
|
||||
this.refs.header.style.transition = 'all 0s'
|
||||
this.refs.header.style.height = this.refs.headerHeight + (pageMoveDistance / 2) + 'px'
|
||||
}
|
||||
} else {
|
||||
let scrollAreaHeight = await this.getScrollAreaHeight()
|
||||
//如果可滚动区的高度大于posterHeight,并且移动超过30,就直接滚到顶
|
||||
if (this.refs.videoSlideHeight > scrollAreaHeight && Math.abs(moveDistance) > 20) {
|
||||
this.$refs.scroll.style.transition = 'all .2s'
|
||||
this.$refs.scroll.style.transform = `translate3d(0,0,0)`
|
||||
let SlideItems = document.querySelectorAll('.SlideItem')
|
||||
SlideItems.forEach(SlideItem => {
|
||||
SlideItem.scrollTop = 0
|
||||
})
|
||||
this.floatShowName = this.floatFixed = this.isScroll = false
|
||||
this.lastMoveYDistance = 0
|
||||
this.startLocationY = e.touches[0].pageY
|
||||
this.changeIndex(this.contentIndex, this.contentIndex)
|
||||
return;
|
||||
}
|
||||
if (Math.abs(pageMoveDistance) < this.canTransformY) {
|
||||
let SlideItems = document.querySelectorAll('.SlideItem')
|
||||
SlideItems.forEach(SlideItem => {
|
||||
SlideItem.scrollTop = 0
|
||||
})
|
||||
this.tempScroll = false
|
||||
}
|
||||
this.floatFixed = Math.abs(pageMoveDistance) > 100
|
||||
this.floatShowName = Math.abs(pageMoveDistance) > 150
|
||||
this.$refs.scroll.style.transform = `translate3d(0,${pageMoveDistance}px,0)`
|
||||
}
|
||||
} else {
|
||||
//手指往上划,页面向下动
|
||||
if (Math.abs(pageMoveDistance) < this.canTransformY) {
|
||||
|
||||
if (this.refs.videoSlideHeight < this.refs.maxSlideHeight) {
|
||||
let endTransformY = Math.abs(this.canTransformY) - (this.refs.maxSlideHeight - this.refs.videoSlideHeight)
|
||||
let moveTransformY = Math.abs(pageMoveDistance) < Math.abs(endTransformY) ? pageMoveDistance : -endTransformY
|
||||
this.$refs.scroll.style.transform = `translate3d(0,${moveTransformY}px,0)`
|
||||
|
||||
this.startLocationY = e.touches[0].pageY
|
||||
this.lastMoveYDistance = moveTransformY
|
||||
|
||||
this.floatFixed = Math.abs(moveTransformY) > 100
|
||||
this.floatShowName = Math.abs(moveTransformY) > 150
|
||||
} else {
|
||||
this.floatFixed = Math.abs(pageMoveDistance) > 100
|
||||
this.floatShowName = Math.abs(pageMoveDistance) > 150
|
||||
this.$refs.scroll.style.transform = `translate3d(0,${pageMoveDistance}px,0)`
|
||||
}
|
||||
} else {
|
||||
this.refs.header.style.height = this.refs.headerHeight + 'px'
|
||||
this.$refs.scroll.style.transform = `translate3d(0,${-this.canTransformY}px,0)`
|
||||
let SlideItems = document.querySelectorAll('.SlideItem')
|
||||
let SlideItem = SlideItems[this.contentIndex]
|
||||
|
||||
if (!this.isScroll) {
|
||||
this.tempScroll = true
|
||||
SlideItem.scrollTop = Math.abs(pageMoveDistance) - this.refs.descHeight + this.floatHeight
|
||||
}
|
||||
if (SlideItem.scrollHeight - SlideItem.clientHeight < SlideItem.scrollTop + 60) {
|
||||
this.loadMoreData()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function touchEnd(e) {
|
||||
if (!this.canScroll) return
|
||||
let moveDistance = e.changedTouches[0].pageY - this.startLocationY
|
||||
let pageMoveDistance = this.lastMoveYDistance + moveDistance * this.acceleration
|
||||
|
||||
// console.log('end-pageMoveDistance', pageMoveDistance)
|
||||
// console.log('end-moveDistance', moveDistance)
|
||||
|
||||
if (this.isScroll) {
|
||||
this.tempScroll = false
|
||||
this.lastMoveYDistance = -this.canTransformY
|
||||
} else {
|
||||
let endTime = Date.now()
|
||||
let gapTime = endTime - this.startTime
|
||||
|
||||
// console.log('end-gapTime', gapTime)
|
||||
let endTransformY = Math.abs(this.canTransformY) - (this.refs.maxSlideHeight - this.refs.videoSlideHeight)
|
||||
|
||||
|
||||
//手指往下划,页面向上动
|
||||
if (moveDistance >= 0) {
|
||||
if (pageMoveDistance > 0) {
|
||||
this.refs.header.style.transition = 'all .3s'
|
||||
this.refs.header.style.height = this.refs.headerHeight + 'px'
|
||||
this.lastMoveYDistance = 0
|
||||
this.floatShowName = this.floatFixed = this.isScroll = this.tempScroll = false
|
||||
} else {
|
||||
//猛的划一下
|
||||
if ((Math.abs(moveDistance) > 100) && gapTime > 100 && gapTime < 150) {
|
||||
this.floatShowName = this.floatFixed = this.isScroll = false
|
||||
|
||||
//用cancelAnimationFrame快速滚动到顶部,要比transition = 'all .3s'快
|
||||
this.$refs.scroll.style.transition = 'none'
|
||||
let transformY = this.getTransform(this.$refs.scroll)
|
||||
//当前的transformY
|
||||
// console.log('transformY', transformY)
|
||||
let timer
|
||||
cancelAnimationFrame(timer);
|
||||
let fn = () => {
|
||||
//说明没到顶
|
||||
if (transformY < 0) {
|
||||
transformY = transformY + 40
|
||||
this.$refs.scroll.style.transform = `translate3d(0,${transformY > 0 ? 0 : transformY}px,0)`
|
||||
timer = requestAnimationFrame(fn);
|
||||
} else {
|
||||
//transformY === 0说明,本来就在顶部,然后猛的一划,这里要判断下
|
||||
if (transformY !== 0) {
|
||||
if (this.$getCss(this.refs.header, 'height') < 400) {
|
||||
this.refs.header.style.transition = 'none'
|
||||
this.refs.header.style.height = this.$getCss(this.refs.header, 'height') + 10 + 'px'
|
||||
timer = requestAnimationFrame(fn);
|
||||
} else {
|
||||
this.refs.header.style.transition = 'all .6s'
|
||||
this.refs.header.style.height = this.refs.headerHeight + 'px'
|
||||
this.lastMoveYDistance = 0
|
||||
cancelAnimationFrame(timer);
|
||||
}
|
||||
} else {
|
||||
//快速动画结束
|
||||
this.lastMoveYDistance = 0
|
||||
cancelAnimationFrame(timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
timer = requestAnimationFrame(fn);
|
||||
|
||||
} else if ((Math.abs(moveDistance) > 100) && gapTime > 150 && gapTime < 300) {
|
||||
// //用cancelAnimationFrame快速滚动到顶部,要比transition = 'all .3s'快
|
||||
this.$refs.scroll.style.transition = 'all .3s'
|
||||
this.$refs.scroll.style.transform = `translate3d(0,0,0)`
|
||||
this.lastMoveYDistance = 0
|
||||
this.floatShowName = this.floatFixed = this.isScroll = false
|
||||
let SlideItems = document.querySelectorAll('.SlideItem')
|
||||
SlideItems.forEach(SlideItem => {
|
||||
SlideItem.scrollTop = 0
|
||||
})
|
||||
this.tempScroll = this.isScroll = false
|
||||
} else {
|
||||
this.lastMoveYDistance = pageMoveDistance
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((Math.abs(moveDistance) > 100) && gapTime < 250) {
|
||||
//往下划
|
||||
this.$refs.scroll.style.transition = 'all .3s'
|
||||
if (this.refs.videoSlideHeight < this.refs.maxSlideHeight) {
|
||||
this.$refs.scroll.style.transform = `translate3d(0,${-endTransformY}px,0)`
|
||||
// this.floatShowName = this.floatFixed = true
|
||||
this.floatFixed = Math.abs(endTransformY) > 100
|
||||
this.floatShowName = Math.abs(endTransformY) > 150
|
||||
this.lastMoveYDistance = -endTransformY
|
||||
} else {
|
||||
this.$refs.scroll.style.transform = `translate3d(0,${-this.canTransformY}px,0)`
|
||||
this.floatShowName = this.floatFixed = this.isScroll = true
|
||||
this.tempScroll = false
|
||||
this.lastMoveYDistance = -this.canTransformY
|
||||
}
|
||||
} else {
|
||||
//手指往上划,页面向下动
|
||||
if (Math.abs(pageMoveDistance) < this.canTransformY) {
|
||||
if (this.refs.videoSlideHeight < this.refs.maxSlideHeight) {
|
||||
this.lastMoveYDistance = Math.abs(pageMoveDistance) < Math.abs(endTransformY) ? pageMoveDistance : -endTransformY
|
||||
} else {
|
||||
let endDistance = pageMoveDistance
|
||||
if (Math.abs(moveDistance) > 20) {
|
||||
if (moveDistance > 0) {
|
||||
endDistance += this.sprint
|
||||
} else {
|
||||
endDistance -= this.sprint
|
||||
}
|
||||
}
|
||||
this.lastMoveYDistance = endDistance
|
||||
this.$refs.scroll.style.transition = 'all .3s'
|
||||
this.$refs.scroll.style.transform = `translate3d(0,${endDistance}px,0)`
|
||||
}
|
||||
} else {
|
||||
this.isScroll = true
|
||||
this.tempScroll = false
|
||||
this.lastMoveYDistance = -this.canTransformY
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getTransform(el) {
|
||||
let transform = el.style.transform
|
||||
if (!transform) return 0
|
||||
// console.log('transform',transform)
|
||||
let transformY = transform.substring(transform.indexOf('0px') + 5, transform.lastIndexOf('0px') - 4)
|
||||
// console.log('transformY',transformY)
|
||||
//当前的transformY
|
||||
transformY = parseInt(transformY)
|
||||
return transformY
|
||||
}
|
||||
|
||||
function filterAge(age) {
|
||||
if (!age) return
|
||||
let date = new Date(age)
|
||||
return new Date().getFullYear() - date.getFullYear()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.UserPanel {
|
||||
|
||||
}
|
||||
</style>
|
||||
@ -3,7 +3,8 @@
|
||||
<!-- <SlideUser></SlideUser>-->
|
||||
<!-- <SlideImgs></SlideImgs>-->
|
||||
<!-- <TestSwiperJs></TestSwiperJs>-->
|
||||
<slideHooks></slideHooks>
|
||||
<!-- <slideHooks></slideHooks>-->
|
||||
<UserPanel/>
|
||||
|
||||
<!-- <div class="body">-->
|
||||
<!-- <div class="wrapper">-->
|
||||
@ -21,10 +22,12 @@ import TestImg from "./TestImg";
|
||||
import slideHooks from '../slideHooks'
|
||||
import TestSwiperJs from "./TestSwiperJs";
|
||||
import {mat4} from "gl-matrix";
|
||||
import UserPanel from "@/components/UserPanel.vue";
|
||||
|
||||
export default {
|
||||
name: "Test",
|
||||
components: {
|
||||
UserPanel,
|
||||
slideHooks,
|
||||
TestSlide,
|
||||
SlideUser,
|
||||
|
||||
@ -73,12 +73,12 @@ export default {
|
||||
const app = Vue.createApp({
|
||||
render() {
|
||||
return <SimpleConfirmDialog
|
||||
onCancel={tempCancelCb}
|
||||
onDismiss={remove}
|
||||
title={title}
|
||||
okText={okText}
|
||||
cancelText={cancelText}
|
||||
onOk={tempOkCb}/>
|
||||
onCancel={tempCancelCb}
|
||||
onDismiss={remove}
|
||||
title={title}
|
||||
okText={okText}
|
||||
cancelText={cancelText}
|
||||
onOk={tempOkCb}/>
|
||||
},
|
||||
})
|
||||
let parent = document.createElement('div')
|
||||
@ -237,7 +237,7 @@ export default {
|
||||
params: (function () {
|
||||
const ret = {}
|
||||
const seg = a.search.replace(/^\?/, '')
|
||||
.split('&')
|
||||
.split('&')
|
||||
const len = seg.length
|
||||
let i = 0
|
||||
let s
|
||||
@ -266,14 +266,6 @@ export default {
|
||||
}
|
||||
return Config.filePreview + url
|
||||
},
|
||||
formatNumber(num) {
|
||||
if (!num) return
|
||||
if (num < 10000) {
|
||||
return num
|
||||
} else {
|
||||
return (num / 10000).toFixed(1) + 'w'
|
||||
}
|
||||
},
|
||||
$getTransform(el) {
|
||||
let transform = el.style.transform
|
||||
if (!transform) return 0
|
||||
@ -354,6 +346,19 @@ export default {
|
||||
}
|
||||
return str
|
||||
},
|
||||
formatNumber(num) {
|
||||
if (!num) return
|
||||
if (num < 10000) {
|
||||
return num
|
||||
} else {
|
||||
return (num / 10000).toFixed(1) + 'w'
|
||||
}
|
||||
},
|
||||
filterAge(age) {
|
||||
if (!age) return
|
||||
let date = new Date(age)
|
||||
return new Date().getFullYear() - date.getFullYear()
|
||||
},
|
||||
randomNum(minNum, maxNum) {
|
||||
switch (arguments.length) {
|
||||
case 1:
|
||||
@ -378,5 +383,17 @@ export default {
|
||||
old[key] = val
|
||||
emit('update:item', old)
|
||||
bus.emit('update:item', {position: props.position, item: old})
|
||||
},
|
||||
copy(val) {
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('readonly', 'readonly');
|
||||
input.setAttribute('value', val);
|
||||
document.body.appendChild(input);
|
||||
input.setSelectionRange(0, 9999);
|
||||
if (document.execCommand('copy')) {
|
||||
document.execCommand('copy');
|
||||
this.$notice('已复制')
|
||||
}
|
||||
document.body.removeChild(input);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user