refactor: fixed the problem that the scroll component could not remember the height

This commit is contained in:
zyronon 2024-05-03 17:03:28 +08:00
parent de415aeafa
commit d2b532a760
8 changed files with 168 additions and 290 deletions

View File

@ -51,7 +51,7 @@ export default {
}, },
radius: { radius: {
type: String, type: String,
default: '3' default: '6'
} }
}, },
data() { data() {
@ -159,9 +159,9 @@ export default {
} }
&.white { &.white {
background: white; background: white !important;
color: black; color: black;
border: 1px solid gainsboro; border: 1px solid gainsboro !important;
} }
&.info { &.info {

View File

@ -14,7 +14,7 @@ export default {
@import '../assets/less/index'; @import '../assets/less/index';
.NoMore { .NoMore {
font-size: 12rem; font-size: 13rem;
height: 60rem; height: 60rem;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -1,5 +1,10 @@
<template> <template>
<Scroll :loading="state.loading" :full-loading="!state.list.length" @pulldown="loadData"> <Scroll
ref="scroll"
:loading="state.loading"
:full-loading="!state.list.length"
@pulldown="loadData"
>
<slot :list="state.list"></slot> <slot :list="state.list"></slot>
<NoMore v-if="state.total !== 0 && state.total === state.list.length" /> <NoMore v-if="state.total !== 0 && state.total === state.list.length" />
</Scroll> </Scroll>
@ -10,6 +15,7 @@ import { onMounted, reactive } from 'vue'
import { _notice } from '@/utils' import { _notice } from '@/utils'
import Scroll from '@/components/Scroll.vue' import Scroll from '@/components/Scroll.vue'
import NoMore from '@/components/NoMore.vue' import NoMore from '@/components/NoMore.vue'
import { useScroll } from '@/utils/hooks/useScroll.ts'
const props = defineProps({ const props = defineProps({
api: { api: {
@ -19,6 +25,7 @@ const props = defineProps({
} }
} }
}) })
const scroll = useScroll()
const state = reactive({ const state = reactive({
list: [], list: [],

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="RequestUpdate" id="RequestUpdate"> <div class="RequestUpdate" id="RequestUpdate">
<BaseHeader> <BaseHeader :is-fixed="false">
<template v-slot:center> <template v-slot:center>
<span class="f16">求更新</span> <span class="f16">求更新</span>
</template> </template>
@ -112,9 +112,13 @@ function toggleRequestUpdate() {
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
display: flex;
flex-direction: column;
.content { .content {
padding: 60rem 15rem 60rem 15rem; flex: 1;
overflow: auto;
padding: 15rem 15rem 60rem 15rem;
.none { .none {
display: flex; display: flex;

View File

@ -1,6 +1,6 @@
<template> <template>
<div id="AllMessage"> <div id="AllMessage">
<BaseHeader> <BaseHeader :is-fixed="false">
<template v-slot:center> <template v-slot:center>
<div class="center" @click="data.isShowType = !data.isShowType"> <div class="center" @click="data.isShowType = !data.isShowType">
<span class="f16">{{ showTypeText }}</span> <span class="f16">{{ showTypeText }}</span>
@ -43,112 +43,42 @@
<div class="mask" @click="data.isShowType = false"></div> <div class="mask" @click="data.isShowType = false"></div>
</div> </div>
</transition> </transition>
<div class="content"> <Scroll ref="mainScroll">
<Loading v-if="data.loading" /> <div class="messages">
<Scroll <div
v-else class="message"
ref="mainScroll" v-for="(item, i) in store.friends.all"
:use-refresh="true" :key="i"
:loading="data.loadingMore" @click="nav('/message/visitors')"
@refresh="refresh" >
@pulldown="loadData" <div class="left">
> <img v-lazy="_checkImgUrl(item.avatar)" alt="" class="avatar" />
<div class="messages">
<div class="message" @click="nav('/message/visitors')">
<div class="left">
<img
v-lazy="_checkImgUrl(store.userinfo.cover_url[0].url_list[0])"
alt=""
class="avatar"
/>
</div>
<div class="right">
<div class="desc">
<div class="top">
<div class="name">主页访客</div>
</div>
<div class="desc-content">4人最近访问了你的主页看看他们是谁</div>
<div class="bottom">
<div class="time">01-11</div>
</div>
</div>
<img
v-lazy="_checkImgUrl(store.userinfo.cover_url[0].url_list[0])"
alt=""
class="poster"
/>
</div>
</div> </div>
<div class="message" :key="i" v-for="(item, i) in showMessageList" @click="_no"> <div class="right">
<div class="left"> <div class="desc">
<img v-lazy="_checkImgUrl(item.author.avatar)" alt="" class="avatar" /> <div class="name">{{ item.name }}</div>
<img <div class="bottom">
v-if="data.selectShowType === 2" <div class="desc-content">近期访问过你的主页</div>
src="@/assets/img/icon/message/love-message.webp" <div class="time">01-11</div>
alt=""
class="type"
/>
<img
v-if="data.selectShowType === 3"
src="@/assets/img/icon/message/call-message.webp"
alt=""
class="type"
/>
<img
v-if="data.selectShowType === 4"
src="@/assets/img/icon/message/comment-message.webp"
alt=""
class="type"
/>
</div>
<div class="right">
<div class="desc">
<div class="top">
<div class="name">{{ item.author.nickname }}</div>
<div class="tag">朋友</div>
</div>
<div class="desc-content">
<span v-if="data.selectShowType === 1">好好看啊</span>
<span v-if="data.selectShowType === 2">赞了你的作品</span>
<span v-if="data.selectShowType === 3">@{{ store.userinfo.nickname }}</span>
<span v-if="data.selectShowType === 4">好好看啊</span>
</div>
<div class="bottom">
<div class="type" v-if="data.selectShowType === 3">在评论中提到了你</div>
<div class="type" v-if="data.selectShowType === 4">回复了你的评论</div>
<div class="time">01-11</div>
</div>
</div> </div>
<img
v-lazy="_checkImgUrl(item.video + '?vframe/jpg/offset/0/w/300')"
alt=""
class="poster"
/>
</div> </div>
</div> <img
<div class="look-all" v-if="!data.showAll" @click="data.showAll = true"> v-lazy="_checkImgUrl(store.userinfo.cover_url[0].url_list[0])"
<span>查看全部</span> alt=""
<dy-back /> class="poster"
/>
</div> </div>
</div> </div>
<div class="title"> </div>
<span>朋友推荐</span> </Scroll>
<img src="@/assets/img/icon/about-gray.png" alt="" />
</div>
<Peoples v-model:list="data.recommend" :loading="data.loadingMore" mode="recommend" />
</Scroll>
</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Scroll from '@/components/Scroll.vue' import Scroll from '@/components/Scroll.vue'
import Loading from '@/components/Loading.vue'
import Peoples from '../people/components/Peoples.vue'
import resource from '@/assets/data/resource.js'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
import { _checkImgUrl, _no, _sleep, cloneDeep } from '@/utils' import { _checkImgUrl } from '@/utils'
import { computed, onMounted, reactive } from 'vue' import { computed, reactive } from 'vue'
import { useNav } from '@/utils/hooks/useNav.js' import { useNav } from '@/utils/hooks/useNav.js'
defineOptions({ defineOptions({
@ -158,20 +88,10 @@ defineOptions({
const store = useBaseStore() const store = useBaseStore()
const nav = useNav() const nav = useNav()
const data = reactive({ const data = reactive({
loading: false,
loadingMore: false,
isShowType: false, isShowType: false,
showAll: false,
recommend: [],
fans: [],
messages: [],
selectShowType: 1 selectShowType: 1
}) })
onMounted(() => {
getData()
})
const showTypeText = computed(() => { const showTypeText = computed(() => {
switch (data.selectShowType) { switch (data.selectShowType) {
case 1: case 1:
@ -187,52 +107,10 @@ const showTypeText = computed(() => {
} }
}) })
const showMessageList = computed(() => {
if (data.showAll) {
return data.messages
}
return data.messages.slice(0, 2)
})
async function getData() {
data.loading = true
await _sleep(800)
data.loading = false
data.recommend = cloneDeep(store.friends.all)
data.fans = cloneDeep(store.friends.all)
data.recommend.map((v) => {
v.type = -1
})
data.messages = cloneDeep(resource.videos)
}
function toggleShowType(index) { function toggleShowType(index) {
data.selectShowType = index data.selectShowType = index
data.isShowType = false data.isShowType = false
} }
// function remove(index) {
// _notice('')
// data.recommend.splice(index, 1)
// }
async function refresh() {
await _sleep(1000)
//TODO
// data.$refs.mainScroll.refreshEnd()
}
async function loadData() {
if (data.loadingMore) return
data.loadingMore = true
await _sleep(500)
data.loadingMore = false
let temp = cloneDeep(store.friends.all)
temp.map((v) => {
v.type = -1
})
data.recommend = data.recommend.concat(temp)
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@ -242,9 +120,12 @@ async function loadData() {
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
background: var(--color-message);
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
display: flex;
flex-direction: column;
.center { .center {
display: flex; display: flex;
@ -254,6 +135,7 @@ async function loadData() {
width: 15rem; width: 15rem;
transform: rotate(180deg); transform: rotate(180deg);
transition: all 0.3s; transition: all 0.3s;
margin-left: 3rem;
} }
.show { .show {
@ -269,10 +151,12 @@ async function loadData() {
margin-top: var(--common-header-height); margin-top: var(--common-header-height);
.dialog-content { .dialog-content {
background: var(--main-bg); border-radius: 0 0 4rem 4rem;
background: var(--color-message);
overflow: hidden;
img { img {
width: 16rem; width: 18rem;
} }
} }
@ -285,121 +169,82 @@ async function loadData() {
} }
} }
.content { .scroll {
padding: 0 var(--page-padding); flex: 1;
padding-top: var(--common-header-height); padding: 0 10rem;
}
.scroll { .messages {
height: calc(var(--vh, 1vh) * 100 - var(--common-header-height)); .message {
} margin-bottom: 20rem;
.messages {
.message {
margin-bottom: 20rem;
display: flex;
&:first-child {
margin-top: 20rem;
}
.left {
display: flex;
align-items: center;
position: relative;
.avatar {
width: 48rem;
height: 48rem;
border-radius: 50%;
}
.type {
position: absolute;
right: 0;
bottom: 10rem;
width: 17rem;
padding: 2.5rem;
border-radius: 50%;
background: black;
}
margin-right: 10rem;
}
.right {
flex: 1;
display: flex;
justify-content: space-between;
.desc {
display: flex;
flex-direction: column;
justify-content: space-between;
.top {
//margin-bottom: 10rem;
display: flex;
align-items: center;
.tag {
color: var(--second-text-color);
padding: 1rem 4rem;
margin-left: 10rem;
border-radius: 2rem;
background: var(--second-btn-color-tran);
font-size: 10rem;
}
}
.bottom {
//margin-top: 10rem;
display: flex;
align-items: center;
font-size: 12rem;
color: var(--second-text-color);
.type {
margin-right: 10rem;
}
}
}
.poster {
margin-left: 10rem;
width: 64rem;
height: 64rem;
object-fit: cover;
border-radius: 3rem;
}
}
}
.look-all {
font-size: 12rem;
color: var(--second-text-color);
display: flex;
justify-content: center;
align-items: center;
.close {
margin-left: 10rem;
transform: rotate(270deg) !important;
width: 12rem;
height: 12rem;
}
}
}
.title {
margin-top: 15rem;
margin-bottom: 10rem;
font-size: 12rem;
display: flex; display: flex;
gap: 10rem;
&:first-child {
margin-top: 20rem;
}
.left {
display: flex;
align-items: center;
position: relative;
.avatar {
width: 58rem;
height: 58rem;
border-radius: 50%;
}
}
.right {
flex: 1;
display: flex;
justify-content: space-between;
.desc {
display: flex;
flex-direction: column;
justify-content: center;
gap: 5rem;
color: white;
font-size: 16rem;
.bottom {
display: flex;
align-items: center;
font-size: 13rem;
color: lightgrey;
.time {
font-size: 12rem;
margin-left: 10rem;
color: var(--second-text-color);
}
}
}
.poster {
margin-left: 10rem;
width: 58rem;
height: 70rem;
object-fit: cover;
border-radius: 3rem;
}
}
}
.look-all {
font-size: 12rem;
color: var(--second-text-color);
display: flex;
justify-content: center;
align-items: center; align-items: center;
img { .close {
margin-left: 5rem; margin-left: 10rem;
width: 13rem; transform: rotate(270deg) !important;
width: 12rem;
height: 12rem;
} }
} }
} }

View File

@ -81,6 +81,7 @@ onMounted(getData)
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
background: var(--color-message);
color: white; color: white;
font-size: 14rem; font-size: 14rem;

View File

@ -8,9 +8,9 @@
</header> </header>
<Scroll ref="mainScroll"> <Scroll ref="mainScroll">
<div class="friends pl1r"> <div class="friends">
<div <div
class="friend pr1r pl1r" class="friend"
@click="nav('/message/chat')" @click="nav('/message/chat')"
:key="index" :key="index"
v-for="(item, index) in store.friends.all" v-for="(item, index) in store.friends.all"
@ -20,12 +20,13 @@
</div> </div>
<span>{{ item.name }}</span> <span>{{ item.name }}</span>
</div> </div>
<div class="friend pr10p"> <div class="friend">
<img src="../../assets/img/icon/message/setting.png" alt="" /> <div class="avatar">
<span class="ml1r">状态设置</span> <img src="../../assets/img/icon/message/setting.png" alt="" />
</div>
<span>状态设置</span>
</div> </div>
</div> </div>
<div class="line mt2r"></div>
<div class="messages"> <div class="messages">
<!-- 粉丝--> <!-- 粉丝-->
<div class="message" @click="nav('/message/fans')"> <div class="message" @click="nav('/message/fans')">
@ -54,7 +55,7 @@
<div class="name"> <div class="name">
<span>互动消息</span> <span>互动消息</span>
</div> </div>
<div class="detail">xxx 赞了你的评论</div> <div class="detail">xxx 近期访问过你的主页</div>
</div> </div>
<div class="right"> <div class="right">
<dy-back class="arrow" mode="gray" img="back" direction="right" /> <dy-back class="arrow" mode="gray" img="back" direction="right" />
@ -433,11 +434,13 @@ import { useBaseStore } from '@/store/pinia'
import { computed, onMounted, reactive, watch } from 'vue' import { computed, onMounted, reactive, watch } from 'vue'
import { useNav } from '@/utils/hooks/useNav.js' import { useNav } from '@/utils/hooks/useNav.js'
import { _checkImgUrl, _sleep, cloneDeep } from '@/utils' import { _checkImgUrl, _sleep, cloneDeep } from '@/utils'
import { useScroll } from '@/utils/hooks/useScroll'
defineOptions({ defineOptions({
name: 'Message' name: 'Message'
}) })
const mainScroll = useScroll()
const store = useBaseStore() const store = useBaseStore()
const nav = useNav() const nav = useNav()
const data = reactive({ const data = reactive({
@ -521,6 +524,8 @@ async function loadRecommendData() {
.no-search { .no-search {
height: calc(var(--vh, 1vh) * 100); height: calc(var(--vh, 1vh) * 100);
display: flex;
flex-direction: column;
> header { > header {
padding: 0 20rem; padding: 0 20rem;
@ -772,36 +777,48 @@ async function loadRecommendData() {
} }
.scroll { .scroll {
height: calc(100% - var(--common-header-height) - var(--footer-height)); flex: 1;
padding-top: 10rem; padding-top: 10rem;
padding-bottom: var(--footer-height);
} }
.friends { .friends {
overflow-x: scroll; overflow-x: scroll;
display: flex; display: flex;
font-size: 14rem; font-size: 14rem;
padding: 0 10rem;
gap: 20rem;
.friend { .friend {
@width: 70rem;
width: @width;
min-width: @width;
&:nth-last-child(1) { &:nth-last-child(1) {
img { .avatar {
margin: 0 10rem; height: @width;
padding: 17rem;
background: var(--second-btn-color-tran);
width: 30rem;
height: 30rem;
border-radius: 50%; border-radius: 50%;
margin-bottom: 6rem; display: flex;
align-items: center;
justify-content: center;
background: var(--second-btn-color-tran);
margin-bottom: 10rem;
img {
width: 35rem;
height: 35rem;
}
} }
} }
.avatar { .avatar {
position: relative; position: relative;
margin-bottom: 6rem; margin-bottom: 6rem;
width: 100%;
img { img {
@width: 64rem; width: 100%;
width: @width; height: 100%;
height: @width;
border-radius: 50%; border-radius: 50%;
} }
@ -821,7 +838,7 @@ async function loadRecommendData() {
span { span {
width: 64rem; width: 64rem;
font-size: 12rem; font-size: 12rem;
color: lightgray; color: white;
display: block; display: block;
text-align: center; text-align: center;
word-break: break-all; word-break: break-all;
@ -833,6 +850,8 @@ async function loadRecommendData() {
} }
.messages { .messages {
margin-top: 20rem;
.message { .message {
display: flex; display: flex;
align-items: center; align-items: center;
@ -874,12 +893,12 @@ async function loadRecommendData() {
flex: 1; flex: 1;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@padding: 14rem; @padding: 16rem;
padding: @padding 0 @padding 0; padding: @padding 0 @padding 0;
.left { .left {
.name { .name {
font-size: 14rem; font-size: 16rem;
color: white; color: white;
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
@ -896,7 +915,7 @@ async function loadRecommendData() {
.detail { .detail {
color: var(--second-text-color); color: var(--second-text-color);
font-size: 12rem; font-size: 14rem;
margin-top: 4rem; margin-top: 4rem;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -68,11 +68,13 @@ import { nextTick, onMounted, reactive, watch } from 'vue'
import Scroll from '@/components/Scroll.vue' import Scroll from '@/components/Scroll.vue'
import { useNav } from '@/utils/hooks/useNav.js' import { useNav } from '@/utils/hooks/useNav.js'
import { _no, _sleep } from '@/utils' import { _no, _sleep } from '@/utils'
import { useScroll } from '@/utils/hooks/useScroll'
defineOptions({ defineOptions({
name: 'SystemNotice' name: 'SystemNotice'
}) })
const mainScroll = useScroll()
const nav = useNav() const nav = useNav()
const data = reactive({ const data = reactive({
loading: false, loading: false,