优化首页账号展示体验
This commit is contained in:
Vendored
+2
@@ -17,6 +17,8 @@ declare module 'vue' {
|
||||
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
|
||||
ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
|
||||
ElButton: typeof import('element-plus/es')['ElButton']
|
||||
ElCarousel: typeof import('element-plus/es')['ElCarousel']
|
||||
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
|
||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { Bell } from '@element-plus/icons-vue'
|
||||
import { ElCarousel, ElCarouselItem, ElIcon } from 'element-plus'
|
||||
|
||||
interface Props {
|
||||
announcements: string[]
|
||||
@@ -32,6 +31,7 @@ defineProps<Props>()
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 10px 20px;
|
||||
min-width: 0;
|
||||
color: #854d0e;
|
||||
background: #fefce8;
|
||||
border: 1px solid #fef08a;
|
||||
@@ -41,5 +41,18 @@ defineProps<Props>()
|
||||
|
||||
.home-announcement :deep(.el-carousel) {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.home-announcement :deep(.el-carousel__container) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.home-announcement span {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
line-height: 22px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import { ElCarousel, ElCarouselItem } from 'element-plus'
|
||||
|
||||
interface HomeBannerSlide {
|
||||
title?: string
|
||||
eyebrow?: string
|
||||
@@ -47,6 +45,20 @@ defineProps<Props>()
|
||||
min-width: 0;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.hero-board :deep(.el-carousel) {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.hero-board :deep(.el-carousel__container) {
|
||||
height: 240px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-board :deep(.el-carousel__item) {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.hero-slide {
|
||||
@@ -55,7 +67,13 @@ defineProps<Props>()
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 40px;
|
||||
background: #f8fafc;
|
||||
overflow: hidden;
|
||||
color: #17233d;
|
||||
background: linear-gradient(135deg, #eff6ff 0%, #ffffff 58%, #fff7ed 100%);
|
||||
}
|
||||
|
||||
.hero-slide.tone-blue {
|
||||
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 56%, #fff7ed 100%);
|
||||
}
|
||||
|
||||
.hero-slide.tone-orange {
|
||||
@@ -77,7 +95,7 @@ defineProps<Props>()
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(90deg, rgba(0, 0, 0, 0.6) 0%, transparent 60%);
|
||||
background: linear-gradient(90deg, rgba(15, 23, 42, 0.74) 0%, rgba(15, 23, 42, 0.24) 62%, transparent 100%);
|
||||
}
|
||||
|
||||
.hero-copy {
|
||||
@@ -86,22 +104,50 @@ defineProps<Props>()
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.hero-copy span {
|
||||
color: #ff6a00;
|
||||
font-size: 13px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.hero-slide.has-image .hero-copy {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.hero-slide.has-image .hero-copy span {
|
||||
color: #fed7aa;
|
||||
}
|
||||
|
||||
.hero-copy h1 {
|
||||
margin: 12px 0;
|
||||
font-size: 32px;
|
||||
font-weight: 900;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.hero-copy p {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 6px 12px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: #1e293b;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
backdrop-filter: blur(4px);
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.hero-slide em {
|
||||
position: absolute;
|
||||
top: 22px;
|
||||
right: 24px;
|
||||
z-index: 1;
|
||||
padding: 6px 10px;
|
||||
border-radius: 999px;
|
||||
color: #ffffff;
|
||||
background: #ff6a00;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import { ElRadioGroup, ElRadioButton } from 'element-plus'
|
||||
|
||||
interface ZoneOption {
|
||||
key: string
|
||||
label: string
|
||||
@@ -24,6 +22,10 @@ const emit = defineEmits<{
|
||||
function selectZone(key: string) {
|
||||
emit('update:activeZone', key)
|
||||
}
|
||||
|
||||
function updateSort(value: string | number | boolean) {
|
||||
emit('update:sortBy', String(value))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -45,7 +47,7 @@ function selectZone(key: string) {
|
||||
</button>
|
||||
</div>
|
||||
<div class="list-actions">
|
||||
<el-radio-group :model-value="sortBy" size="small" @update:model-value="(val) => emit('update:sortBy', val as string)">
|
||||
<el-radio-group :model-value="sortBy" size="small" @update:model-value="updateSort">
|
||||
<el-radio-button label="recommended">综合推荐</el-radio-button>
|
||||
<el-radio-button label="coinDesc">哈夫币</el-radio-button>
|
||||
<el-radio-button label="awmDesc">AWM数量</el-radio-button>
|
||||
@@ -58,22 +60,27 @@ function selectZone(key: string) {
|
||||
|
||||
<style scoped>
|
||||
.zones-and-sort {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) max-content;
|
||||
gap: 14px;
|
||||
align-items: end;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.zone-tabs {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
gap: 12px;
|
||||
grid-template-columns: repeat(6, minmax(108px, 1fr));
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.zone-tab {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding: 14px;
|
||||
min-width: 0;
|
||||
min-height: 72px;
|
||||
padding: 12px 14px;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 12px;
|
||||
background: #ffffff;
|
||||
@@ -99,9 +106,12 @@ function selectZone(key: string) {
|
||||
}
|
||||
|
||||
.zone-tab strong {
|
||||
overflow: hidden;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #17233d;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.zone-count {
|
||||
@@ -111,12 +121,39 @@ function selectZone(key: string) {
|
||||
}
|
||||
|
||||
.zone-tab small {
|
||||
overflow: hidden;
|
||||
font-size: 11px;
|
||||
color: #7b8798;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.list-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
min-width: max-content;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.list-actions :deep(.el-radio-group) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 1380px) {
|
||||
.zones-and-sort {
|
||||
grid-template-columns: 1fr;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.list-actions {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.zone-tabs {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import type { Listing } from '@/features/listings'
|
||||
import {
|
||||
@@ -24,18 +25,19 @@ interface Props {
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const coverURL = computed(() => props.listing.cover_url || props.listing.screenshot_urls?.[0] || '')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterLink class="listing-card-v2" :to="`/listings/${listing.id}`">
|
||||
<div class="card-cover">
|
||||
<img
|
||||
v-if="listing.cover_url"
|
||||
:data-src="listing.cover_url"
|
||||
v-if="coverURL"
|
||||
:src="coverURL"
|
||||
:alt="getListingTitle(listing)"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
class="lazy-image"
|
||||
/>
|
||||
<div v-else class="empty-cover">HFB</div>
|
||||
<div class="cover-badges">
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { ElEmpty } from 'element-plus'
|
||||
import {
|
||||
defaultHomeAnnouncements,
|
||||
defaultHomeBanners,
|
||||
@@ -174,10 +173,11 @@ loadHome()
|
||||
@update:sort-by="sortBy = $event"
|
||||
/>
|
||||
|
||||
<el-empty
|
||||
v-if="!loading && listings.length === 0"
|
||||
description="没有符合条件的账号"
|
||||
/>
|
||||
<div v-if="!loading && listings.length === 0" class="home-empty-state">
|
||||
<strong>没有符合条件的账号</strong>
|
||||
<span>可以放宽筛选条件或切回全部专区。</span>
|
||||
<button type="button" @click="handleResetFilters">重置条件</button>
|
||||
</div>
|
||||
<div v-else v-loading="loading" class="enhanced-desktop-list">
|
||||
<ListingCard
|
||||
v-for="item in listings"
|
||||
@@ -259,4 +259,38 @@ loadHome()
|
||||
gap: 16px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.home-empty-state {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
gap: 8px;
|
||||
min-height: 148px;
|
||||
padding: 28px;
|
||||
border: 1px dashed #d8e1ee;
|
||||
border-radius: 16px;
|
||||
background: #ffffff;
|
||||
color: #7b8798;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.home-empty-state strong {
|
||||
color: #17233d;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.home-empty-state span {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.home-empty-state button {
|
||||
height: 34px;
|
||||
margin-top: 4px;
|
||||
padding: 0 16px;
|
||||
border: 1px solid #ff6a00;
|
||||
border-radius: 8px;
|
||||
background: #fff7ed;
|
||||
color: #ff6a00;
|
||||
font-weight: 800;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user