优化:列表显示优化

This commit is contained in:
ivan 2026-02-08 16:57:15 +08:00
parent 830b8c594d
commit 14c4ec322f

View File

@ -1,4 +1,5 @@
<template> <template>
<div class="home-page">
<v-container class="home-container"> <v-container class="home-container">
<v-row justify="center" align="center" class="home-tabs"> <v-row justify="center" align="center" class="home-tabs">
<v-tabs v-model="activeTab" class="home-tab-bar"> <v-tabs v-model="activeTab" class="home-tab-bar">
@ -21,11 +22,95 @@
<span>加载中...</span> <span>加载中...</span>
</div> </div>
<div v-else-if="listLength >= maxItems" class="no-more-tip">没有更多了</div> <div v-else-if="listLength >= maxItems" class="no-more-tip">没有更多了</div>
<v-btn
v-else
class="load-more-btn"
variant="outlined"
color="primary"
:disabled="loadingMore"
@click="loadMore"
>
加载更多
</v-btn>
</div> </div>
</div> </div>
</v-pull-to-refresh> </v-pull-to-refresh>
</div> </div>
</v-container> </v-container>
<footer class="home-footer">
<div class="footer-inner">
<div class="footer-top">
<div class="footer-brand">
<div class="footer-logo">
<span class="logo-mark">M</span>
<span class="logo-text">Polymarket</span>
</div>
<p class="footer-slogan">The World's Largest Prediction Market</p>
</div>
<div class="footer-links-row">
<div class="footer-col">
<h4 class="footer-col-title">Support & Social</h4>
<ul class="footer-link-list">
<li><a href="#">Contact us</a></li>
<li><a href="#">Learn</a></li>
<li><a href="#">X (Twitter)</a></li>
<li><a href="#">Instagram</a></li>
<li><a href="#">Discord</a></li>
<li><a href="#">TikTok</a></li>
<li><a href="#">News</a></li>
</ul>
</div>
<div class="footer-col">
<h4 class="footer-col-title">Polymarket</h4>
<ul class="footer-link-list">
<li><a href="#">Accuracy</a></li>
<li><a href="#">Activity</a></li>
<li><a href="#">Leaderboard</a></li>
<li><a href="#">Rewards</a></li>
<li><a href="#">Press</a></li>
<li><a href="#">Careers</a></li>
<li><a href="#">APIs</a></li>
</ul>
</div>
</div>
</div>
<div class="footer-bottom">
<div class="footer-legal-links">
<a href="#">Adventure One QSS Inc. © 2026</a>
<span class="sep">/</span>
<a href="#">Privacy</a>
<span class="sep">/</span>
<a href="#">Terms of Use</a>
<span class="sep">/</span>
<a href="#">Help Center</a>
<span class="sep">/</span>
<a href="#">Docs</a>
</div>
<div class="footer-lang-social">
<v-select
v-model="footerLang"
:items="['English']"
density="compact"
hide-details
variant="outlined"
class="footer-lang-select"
/>
<div class="footer-social-icons">
<v-icon size="20">mdi-email-outline</v-icon>
<v-icon size="20">mdi-twitter</v-icon>
<v-icon size="20">mdi-instagram</v-icon>
<v-icon size="20">mdi-discord</v-icon>
<v-icon size="20">mdi-music</v-icon>
</div>
</div>
</div>
<p class="footer-disclaimer">
Polymarket operates globally through separate legal entities. Polymarket US is operated by QCX LLC d/b/a Polymarket US, a CFTC-regulated Designated Contract Market. This international platform is not regulated by the CFTC and operates independently. Trading involves substantial risk of loss. See our <a href="#">Terms of Service &amp; Privacy Policy</a>.
</p>
</div>
</footer>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -40,10 +125,13 @@ const maxItems = 50
const listLength = ref(INITIAL_COUNT) const listLength = ref(INITIAL_COUNT)
const loadingMore = ref(false) const loadingMore = ref(false)
const footerLang = ref('English')
const scrollRef = ref<HTMLElement | null>(null) const scrollRef = ref<HTMLElement | null>(null)
const sentinelRef = ref<HTMLElement | null>(null) const sentinelRef = ref<HTMLElement | null>(null)
let observer: IntersectionObserver | null = null let observer: IntersectionObserver | null = null
const SCROLL_LOAD_THRESHOLD = 280
function onRefresh({ done }: { done: () => void }) { function onRefresh({ done }: { done: () => void }) {
setTimeout(() => { setTimeout(() => {
listLength.value = INITIAL_COUNT listLength.value = INITIAL_COUNT
@ -60,23 +148,39 @@ function loadMore() {
}, 400) }, 400)
} }
function checkScrollLoad() {
const el = scrollRef.value
if (!el || loadingMore.value || listLength.value >= maxItems) return
const { scrollTop, clientHeight, scrollHeight } = el
if (scrollHeight - scrollTop - clientHeight < SCROLL_LOAD_THRESHOLD) {
loadMore()
}
}
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
if (!sentinelRef.value || !scrollRef.value) return const scrollEl = scrollRef.value
const sentinel = sentinelRef.value
if (!sentinel || !scrollEl) return
observer = new IntersectionObserver( observer = new IntersectionObserver(
(entries) => { (entries) => {
if (!entries[0]?.isIntersecting) return if (!entries[0]?.isIntersecting) return
loadMore() loadMore()
}, },
{ root: scrollRef.value, rootMargin: '80px', threshold: 0 } { root: scrollEl, rootMargin: `${SCROLL_LOAD_THRESHOLD}px`, threshold: 0 }
) )
observer.observe(sentinelRef.value) observer.observe(sentinel)
scrollEl.addEventListener('scroll', checkScrollLoad, { passive: true })
}) })
}) })
onUnmounted(() => { onUnmounted(() => {
if (observer && sentinelRef.value) observer.unobserve(sentinelRef.value) const sentinel = sentinelRef.value
if (observer && sentinel) observer.unobserve(sentinel)
observer = null observer = null
scrollRef.value?.removeEventListener('scroll', checkScrollLoad)
}) })
</script> </script>
@ -111,15 +215,23 @@ onUnmounted(() => {
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
/* 占满剩余视口高度,内容多时在内部滚动 */
min-height: calc(100vh - 64px - 48px - 32px);
max-height: calc(100vh - 64px - 48px - 32px); max-height: calc(100vh - 64px - 48px - 32px);
} }
/* 卡片最小宽度与 MarketCard 一致 310pxauto-fill 按可用宽度自动 14 列,避免第三列被裁 */
.home-list { .home-list {
width: 100%; width: 100%;
display: flex; display: grid;
flex-wrap: wrap;
gap: 20px; gap: 20px;
padding-bottom: 8px; padding-bottom: 8px;
grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
}
.home-list > * {
min-width: 0;
width: 100%;
} }
.load-more-footer { .load-more-footer {
@ -136,7 +248,7 @@ onUnmounted(() => {
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
height: 1px; height: 8px;
pointer-events: none; pointer-events: none;
opacity: 0; opacity: 0;
} }
@ -152,10 +264,15 @@ onUnmounted(() => {
font-size: 14px; font-size: 14px;
} }
/* When only one column fits */ .load-more-btn {
@media (max-width: 600px) { text-transform: none;
.home-list > div { margin-top: 4px;
flex: 1 1 100%; }
/* 大屏最多 4 列,避免过宽时出现 5 列以上 */
@media (min-width: 1320px) {
.home-list {
grid-template-columns: repeat(4, minmax(310px, 1fr));
} }
} }
@ -215,4 +332,198 @@ onUnmounted(() => {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
/* Footer */
.home-page {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.home-footer {
width: 100%;
background-color: #374151;
color: rgba(255, 255, 255, 0.85);
margin-top: auto;
padding: 48px 24px 32px;
}
.footer-inner {
max-width: 1200px;
margin: 0 auto;
}
.footer-top {
display: flex;
flex-wrap: wrap;
gap: 48px;
padding-bottom: 32px;
border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.footer-brand {
flex-shrink: 0;
}
.footer-logo {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.logo-mark {
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
background: rgba(255, 255, 255, 0.15);
color: #fff;
font-weight: 700;
font-size: 18px;
border-radius: 6px;
}
.logo-text {
font-size: 1.25rem;
font-weight: 600;
color: #fff;
}
.footer-slogan {
font-size: 0.875rem;
color: rgba(255, 255, 255, 0.7);
margin: 0;
}
.footer-links-row {
display: flex;
gap: 64px;
flex-wrap: wrap;
}
.footer-col-title {
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: rgba(255, 255, 255, 0.9);
margin: 0 0 12px 0;
padding-bottom: 8px;
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.footer-link-list {
list-style: none;
margin: 0;
padding: 0;
}
.footer-link-list li {
margin-bottom: 6px;
}
.footer-link-list a {
color: rgba(255, 255, 255, 0.75);
text-decoration: none;
font-size: 0.875rem;
}
.footer-link-list a:hover {
color: #fff;
}
.footer-bottom {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 16px;
padding-top: 24px;
padding-bottom: 24px;
}
.footer-legal-links {
font-size: 0.8125rem;
}
.footer-legal-links a {
color: rgba(255, 255, 255, 0.75);
text-decoration: none;
}
.footer-legal-links a:hover {
color: #fff;
}
.footer-legal-links .sep {
margin: 0 8px;
color: rgba(255, 255, 255, 0.4);
}
.footer-lang-social {
display: flex;
align-items: center;
gap: 16px;
}
.footer-lang-select {
max-width: 120px;
}
.footer-lang-select :deep(.v-field) {
background: rgba(255, 255, 255, 0.08);
color: #fff;
font-size: 0.875rem;
}
.footer-social-icons {
display: flex;
gap: 12px;
color: rgba(255, 255, 255, 0.8);
}
.footer-social-icons .v-icon {
cursor: pointer;
}
.footer-social-icons .v-icon:hover {
color: #fff;
}
.footer-disclaimer {
font-size: 0.75rem;
line-height: 1.5;
color: rgba(255, 255, 255, 0.6);
margin: 0;
max-width: 720px;
}
.footer-disclaimer a {
color: rgba(255, 255, 255, 0.85);
text-decoration: underline;
}
.footer-disclaimer a:hover {
color: #fff;
}
@media (max-width: 600px) {
.home-footer {
padding: 32px 16px 24px;
}
.footer-top {
flex-direction: column;
gap: 32px;
padding-bottom: 24px;
}
.footer-links-row {
gap: 32px;
}
.footer-bottom {
flex-direction: column;
align-items: flex-start;
}
}
</style> </style>