优化移动端首页卡片展示

This commit is contained in:
yml
2026-06-08 22:07:25 +08:00
parent b15e0fb78d
commit 9b802c1a5c
2 changed files with 243 additions and 38 deletions
@@ -431,12 +431,16 @@
.mobile-list {
display: grid;
gap: 12px;
gap: 10px;
}
.mobile-card {
display: grid;
grid-template-columns: 104px minmax(0, 1fr);
column-gap: 8px;
row-gap: 8px;
overflow: hidden;
padding: 8px;
border: 1px solid #e2e8f0;
border-radius: 8px;
background: #fff;
@@ -446,10 +450,12 @@
.card-cover {
position: relative;
aspect-ratio: 16 / 9;
display: grid;
width: 104px;
height: 104px;
place-items: center;
overflow: hidden;
border-radius: 8px;
background: #e2e8f0;
color: #64748b;
font-weight: 800;
@@ -463,87 +469,217 @@
.card-cover-labels {
position: absolute;
left: 8px;
top: 8px;
left: 6px;
top: 6px;
display: flex;
gap: 6px;
}
.card-cover-labels em {
padding: 3px 7px;
padding: 2px 6px;
border-radius: 999px;
background: rgba(255, 106, 0, 0.92);
color: #fff;
font-size: 11px;
font-size: 10px;
font-style: normal;
font-weight: 800;
}
.card-main {
padding: 12px;
display: flex;
min-width: 0;
flex-direction: column;
padding: 0;
}
.card-title-row h2 {
margin: 0;
display: -webkit-box;
min-height: 35px;
overflow: hidden;
color: #0f172a;
font-size: 16px;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px;
line-height: 1.34;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.mobile-listing-no {
.card-meta-row {
display: flex;
flex-wrap: wrap;
gap: 4px;
margin-top: 3px;
}
.mobile-listing-no,
.daily-loss-badge {
display: inline-flex;
width: fit-content;
margin-top: 6px;
padding: 3px 7px;
align-items: center;
min-height: 17px;
padding: 1px 6px;
border-radius: 999px;
background: #fff7ed;
color: #c2410c;
font-size: 11px;
background: #f5f7fa;
color: #64748b;
font-size: 10px;
font-weight: 800;
line-height: 1.2;
}
.daily-loss-badge {
border: none;
background: #f5f7fa;
color: #64748b;
}
.card-subtitle {
margin: 6px 0 10px;
color: #64748b;
font-size: 13px;
line-height: 1.4;
width: fit-content;
margin: 0;
padding: 1px 6px;
border-radius: 999px;
background: #fff7ed;
color: #ea580c;
font-size: 10px;
font-weight: 900;
line-height: 1.35;
}
.card-action-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 4px;
margin-top: 4px;
}
.card-badges-row,
.card-chip-row {
display: flex;
flex-wrap: wrap;
gap: 6px;
gap: 4px;
}
.server-badge,
.card-chip-row span {
padding: 3px 7px;
display: inline-flex;
align-items: center;
gap: 3px;
padding: 1px 5px;
border-radius: 999px;
border: 1px solid transparent;
background: #f1f5f9;
color: #475569;
font-size: 11px;
font-size: 10px;
font-weight: 700;
line-height: 1.35;
}
.server-badge.tone-wechat {
background: #ecfdf5;
color: #16a34a;
}
.server-badge.tone-qq {
background: #eff6ff;
color: #1683ff;
}
.server-badge.tone-scan {
background: #fff7ed;
color: #ea580c;
}
.server-badge.tone-password {
background: #fef2f2;
color: #dc2626;
}
.server-badge.tone-steam {
background: #eef2ff;
color: #4f46e5;
}
.card-chip-row span.tone-coin {
border-color: #fed7aa;
background: #fff7ed;
color: #c2410c;
}
.card-chip-row span.tone-insurance {
border-color: #fed7aa;
background: #fff7ed;
color: #c2410c;
}
.card-chip-row span.tone-stamina {
border-color: #fed7aa;
background: #fff7ed;
color: #c2410c;
}
.card-chip-row span.tone-load {
border-color: #fed7aa;
background: #fff7ed;
color: #c2410c;
}
.card-chip-row span.tone-rank {
border-color: #fed7aa;
background: #fff7ed;
color: #c2410c;
}
.card-chip-row span.tone-weapon {
border-color: #fed7aa;
background: #fff7ed;
color: #c2410c;
}
.card-chip-row span.tone-asset {
border-color: #fed7aa;
background: #fff7ed;
color: #c2410c;
}
.card-chip-row span.tone-time {
border-color: #fed7aa;
background: #fff7ed;
color: #c2410c;
}
.card-footer {
margin-top: 10px;
margin-top: 5px;
}
.price-col {
display: inline-flex;
width: fit-content;
max-width: 100%;
align-items: baseline;
gap: 6px;
}
.price-col strong {
color: #ef4444;
font-size: 20px;
font-weight: 900;
line-height: 1;
}
.rent-sub {
margin-left: 8px;
color: #64748b;
font-size: 12px;
padding: 1px 6px;
border-radius: 999px;
background: #fff7ed;
color: #9a3412;
font-size: 10px;
font-weight: 700;
}
.card-chip-row {
padding: 0 12px 12px;
grid-column: 1 / -1;
max-height: 42px;
overflow: hidden;
padding: 0;
}
.mobile-load-state {
@@ -568,4 +704,19 @@
padding: 0 12px;
font-size: 14px;
}
.mobile-card {
grid-template-columns: 96px minmax(0, 1fr);
column-gap: 8px;
padding: 8px;
}
.card-cover {
width: 96px;
height: 96px;
}
.card-title-row h2 {
font-size: 13px;
}
}
@@ -24,8 +24,9 @@ import MobileHomeFilterSheet, { type FilterSection } from './MobileHomeFilterShe
import {
getListingChips,
getListingDisplayPrice,
getListingSubtitle,
getListingTitle,
getDailyLoss,
getRatioValue,
formatListingCode,
getLoginMethod,
getServerRegion,
@@ -462,6 +463,35 @@ function zoneCount(key: string) {
if (key === 'all') return zoneCounts.value.all ?? totalListings.value
return zoneCounts.value[key] ?? 0
}
function getAccessBadgeMeta(value: string) {
const text = value.trim()
if (text.includes('微信')) return { icon: 'wechat', tone: 'wechat' }
if (text.toUpperCase().includes('QQ')) return { icon: 'qq', tone: 'qq' }
if (text.includes('扫码')) return { icon: 'scan', tone: 'scan' }
if (text.includes('账号') || text.includes('密码')) return { icon: 'lock', tone: 'password' }
if (text.includes('Steam')) return { icon: 'desktop-o', tone: 'steam' }
return { icon: 'bookmark-o', tone: 'default' }
}
function getMobileRatioText(item: Listing) {
const ratio = getRatioValue(item)
if (ratio <= 0) return ''
const formatted = Number.isInteger(ratio) ? String(ratio) : ratio.toFixed(1)
return `1元=${formatted}w哈夫币`
}
function chipTone(label: string) {
if (label.includes('哈夫币')) return 'coin'
if (label.includes('保险')) return 'insurance'
if (label.includes('体力')) return 'stamina'
if (label.includes('负重')) return 'load'
if (label.includes('段位')) return 'rank'
if (label.includes('AWM')) return 'weapon'
if (label.includes('总资产')) return 'asset'
if (label.includes('方便')) return 'time'
return 'default'
}
</script>
<template>
@@ -628,14 +658,34 @@ function zoneCount(key: string) {
<div class="card-title-row">
<h2>{{ getListingTitle(item) }}</h2>
</div>
<div class="card-meta-row">
<div class="mobile-listing-no">编号 {{ formatListingCode(item) }}</div>
<p class="card-subtitle">{{ getListingSubtitle(item) }}</p>
<div v-if="getDailyLoss(item)" class="daily-loss-badge">
消耗 {{ getDailyLoss(item) }}/
</div>
</div>
<div class="card-action-row">
<p v-if="getMobileRatioText(item)" class="card-subtitle">
{{ getMobileRatioText(item) }}
</p>
<div class="card-badges-row">
<span class="server-badge">{{ getServerRegion(item) }}</span>
<span v-if="getLoginMethod(item)" class="server-badge">
<span
class="server-badge"
:class="`tone-${getAccessBadgeMeta(getServerRegion(item)).tone}`"
>
<van-icon :name="getAccessBadgeMeta(getServerRegion(item)).icon" :size="13" />
{{ getServerRegion(item) }}
</span>
<span
v-if="getLoginMethod(item)"
class="server-badge"
:class="`tone-${getAccessBadgeMeta(getLoginMethod(item)).tone}`"
>
<van-icon :name="getAccessBadgeMeta(getLoginMethod(item)).icon" :size="13" />
{{ getLoginMethod(item) }}
</span>
</div>
</div>
<div class="card-footer">
<div class="price-col">
<strong>¥{{ getListingDisplayPrice(item) }}</strong>
@@ -644,7 +694,11 @@ function zoneCount(key: string) {
</div>
</div>
<div class="card-chip-row">
<span v-for="chip in getListingChips(item)" :key="`${item.id}-${chip.label}`">
<span
v-for="chip in getListingChips(item)"
:key="`${item.id}-${chip.label}`"
:class="`tone-${chipTone(chip.label)}`"
>
{{ chip.label }}:{{ chip.value }}
</span>
</div>