[Snow Team] mobile-ui-mvp: auto-commit work
This commit is contained in:
@@ -8,9 +8,16 @@ const loading = ref(false)
|
||||
const loadFailed = ref(false)
|
||||
const listings = ref<Listing[]>([])
|
||||
const filterOpen = ref(false)
|
||||
const activeSort = ref('推荐')
|
||||
const activeSort = ref('默认')
|
||||
|
||||
const sortOptions = ['推荐', '低价', '高哈夫币', '免押优先']
|
||||
const channels = [
|
||||
{ label: '全部', icon: '🔥' },
|
||||
{ label: '高哈夫币', icon: '💰' },
|
||||
{ label: '低押金', icon: '🛡️' },
|
||||
{ label: '扫码号', icon: '📱' },
|
||||
{ label: '包夜', icon: '🌙' },
|
||||
]
|
||||
const sortOptions = ['默认', '价格', '比例', '哈夫币', '筛选']
|
||||
const quickFilters = ['三角洲行动', '安卓/扫码', '高段位', '可包夜']
|
||||
|
||||
const fallbackListings: Listing[] = [
|
||||
@@ -90,6 +97,18 @@ const fallbackListings: Listing[] = [
|
||||
|
||||
const displayListings = computed(() => (listings.value.length > 0 ? listings.value : fallbackListings))
|
||||
|
||||
const platformStats = computed(() => {
|
||||
const items = displayListings.value
|
||||
const totalCoin = items.reduce((sum, item) => sum + Number(item.haf_coin_amount || 0), 0)
|
||||
const lowDeposit = items.filter((item) => Number(item.deposit_amount || 0) <= 120).length
|
||||
|
||||
return [
|
||||
{ value: `${items.length}+`, label: '在线租号' },
|
||||
{ value: formatCoin(totalCoin), label: '哈夫币总量' },
|
||||
{ value: `${lowDeposit}个`, label: '低押账号' },
|
||||
]
|
||||
})
|
||||
|
||||
onMounted(loadListings)
|
||||
|
||||
async function loadListings() {
|
||||
@@ -110,6 +129,13 @@ function formatCoin(amount: number) {
|
||||
}
|
||||
return `${amount}`
|
||||
}
|
||||
|
||||
function formatRatio(item: Listing) {
|
||||
if (!item.price_hourly) {
|
||||
return '--'
|
||||
}
|
||||
return `${Math.round(item.haf_coin_amount / item.price_hourly / 10000)}W/元`
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -126,16 +152,16 @@ function formatCoin(amount: number) {
|
||||
<button class="mobile-service" type="button">客服</button>
|
||||
</div>
|
||||
|
||||
<label class="mobile-search">
|
||||
<span>🔍</span>
|
||||
<input type="search" placeholder="搜区服 / 段位 / 哈夫币数量" />
|
||||
</label>
|
||||
|
||||
<div class="fraud-alert">
|
||||
<span>防骗提示</span>
|
||||
平台担保交易,拒绝私下转账/共享验证码,交接全程留痕。
|
||||
</div>
|
||||
|
||||
<label class="mobile-search">
|
||||
<span>🔍</span>
|
||||
<input type="search" placeholder="搜索区服 / 段位 / 哈夫币数量" />
|
||||
</label>
|
||||
|
||||
<div class="mobile-banner">
|
||||
<div>
|
||||
<p>三角洲行动账号专区</p>
|
||||
@@ -147,27 +173,36 @@ function formatCoin(amount: number) {
|
||||
</section>
|
||||
|
||||
<section class="mobile-content">
|
||||
<button class="filter-entry" type="button" @click="filterOpen = !filterOpen">
|
||||
<span>高级筛选</span>
|
||||
<strong>{{ filterOpen ? '收起' : '展开' }}</strong>
|
||||
</button>
|
||||
|
||||
<div v-if="filterOpen" class="filter-panel">
|
||||
<button v-for="item in quickFilters" :key="item" type="button">{{ item }}</button>
|
||||
<div class="channel-strip" aria-label="快捷频道">
|
||||
<button v-for="item in channels" :key="item.label" type="button">
|
||||
<span>{{ item.icon }}</span>
|
||||
{{ item.label }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="sort-pills" aria-label="排序方式">
|
||||
<div class="trust-panel" aria-label="交易数据背书">
|
||||
<div v-for="item in platformStats" :key="item.label">
|
||||
<strong>{{ item.value }}</strong>
|
||||
<span>{{ item.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sort-bar" aria-label="排序方式">
|
||||
<button
|
||||
v-for="item in sortOptions"
|
||||
:key="item"
|
||||
:class="{ active: activeSort === item }"
|
||||
type="button"
|
||||
@click="activeSort = item"
|
||||
@click="item === '筛选' ? (filterOpen = !filterOpen) : (activeSort = item)"
|
||||
>
|
||||
{{ item }}
|
||||
{{ item }}<span v-if="item === '筛选'">▾</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="filterOpen" class="filter-panel">
|
||||
<button v-for="item in quickFilters" :key="item" type="button">{{ item }}</button>
|
||||
</div>
|
||||
|
||||
<p v-if="loadFailed" class="mobile-tip">接口暂不可用,当前展示移动端示例数据。</p>
|
||||
<p v-else-if="loading" class="mobile-tip">正在加载优质账号...</p>
|
||||
|
||||
@@ -188,9 +223,14 @@ function formatCoin(amount: number) {
|
||||
<span>秒接单</span>
|
||||
<span>{{ item.min_rent_hours }}小时起租</span>
|
||||
</div>
|
||||
<div class="asset-row">
|
||||
<span>哈夫币 {{ formatCoin(item.haf_coin_amount) }}</span>
|
||||
<span>比例 {{ formatRatio(item) }}</span>
|
||||
<span>押金 ¥{{ item.deposit_amount }}</span>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<strong>¥{{ item.price_hourly }}<small>/小时</small></strong>
|
||||
<span>押金 ¥{{ item.deposit_amount }}</span>
|
||||
<span>日租 ¥{{ item.price_daily || '--' }} · 周租 ¥{{ item.price_weekly || '--' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</RouterLink>
|
||||
@@ -218,7 +258,7 @@ function formatCoin(amount: number) {
|
||||
.mobile-hero {
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 28px 28px;
|
||||
background: linear-gradient(180deg, #1479ff 0%, #0b66e4 58%, #eef5ff 58%);
|
||||
background: linear-gradient(180deg, #1479ff 0%, #0b66e4 61%, #eef5ff 61%);
|
||||
padding: 14px 14px 0;
|
||||
}
|
||||
|
||||
@@ -270,21 +310,6 @@ function formatCoin(amount: number) {
|
||||
padding: 7px 12px;
|
||||
}
|
||||
|
||||
.fraud-alert {
|
||||
margin-top: 14px;
|
||||
border-radius: 12px;
|
||||
background: #ffe27a;
|
||||
color: #5c3b00;
|
||||
padding: 10px 12px;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.fraud-alert span {
|
||||
margin-right: 6px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.mobile-search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -305,6 +330,21 @@ function formatCoin(amount: number) {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.fraud-alert {
|
||||
margin-top: 12px;
|
||||
border-radius: 12px;
|
||||
background: #ffe27a;
|
||||
color: #5c3b00;
|
||||
padding: 10px 12px;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.fraud-alert span {
|
||||
margin-right: 6px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.mobile-banner {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -359,48 +399,108 @@ function formatCoin(amount: number) {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.filter-entry {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
border-radius: 16px;
|
||||
background: #ffffff;
|
||||
color: #17233d;
|
||||
padding: 14px;
|
||||
font-size: 15px;
|
||||
box-shadow: 0 8px 22px rgba(23, 35, 61, 0.06);
|
||||
}
|
||||
|
||||
.filter-entry strong {
|
||||
color: #1479ff;
|
||||
}
|
||||
|
||||
.filter-panel,
|
||||
.sort-pills {
|
||||
.channel-strip,
|
||||
.sort-bar,
|
||||
.filter-panel {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
overflow-x: auto;
|
||||
padding: 10px 0 2px;
|
||||
padding-bottom: 2px;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.filter-panel button,
|
||||
.sort-pills button {
|
||||
.channel-strip::-webkit-scrollbar,
|
||||
.sort-bar::-webkit-scrollbar,
|
||||
.filter-panel::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.channel-strip button {
|
||||
display: grid;
|
||||
min-width: 72px;
|
||||
gap: 4px;
|
||||
flex: 0 0 auto;
|
||||
place-items: center;
|
||||
border: 0;
|
||||
border-radius: 16px;
|
||||
background: #ffffff;
|
||||
color: #24324a;
|
||||
padding: 11px 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
box-shadow: 0 8px 22px rgba(23, 35, 61, 0.06);
|
||||
}
|
||||
|
||||
.channel-strip span {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.trust-panel {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
border-radius: 18px;
|
||||
background: #ffffff;
|
||||
padding: 12px 10px;
|
||||
box-shadow: 0 8px 22px rgba(23, 35, 61, 0.06);
|
||||
}
|
||||
|
||||
.trust-panel div {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.trust-panel strong,
|
||||
.trust-panel span {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.trust-panel strong {
|
||||
color: #1479ff;
|
||||
font-size: 17px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.trust-panel span {
|
||||
margin-top: 4px;
|
||||
color: #7b8799;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.sort-bar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
margin: 12px -14px 0;
|
||||
background: rgba(238, 245, 255, 0.92);
|
||||
padding: 10px 14px 8px;
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.filter-panel {
|
||||
padding: 8px 0 2px;
|
||||
}
|
||||
|
||||
.sort-bar button,
|
||||
.filter-panel button {
|
||||
flex: 0 0 auto;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
background: #ffffff;
|
||||
color: #4d5b73;
|
||||
padding: 9px 12px;
|
||||
font-weight: 700;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.sort-pills button.active {
|
||||
.sort-bar button.active {
|
||||
background: #1479ff;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.sort-bar button span {
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.mobile-tip {
|
||||
margin: 12px 2px;
|
||||
color: #6b7a90;
|
||||
@@ -425,7 +525,7 @@ function formatCoin(amount: number) {
|
||||
|
||||
.card-cover {
|
||||
display: grid;
|
||||
min-height: 104px;
|
||||
min-height: 116px;
|
||||
place-content: center;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(145deg, #126cff, #63b3ff);
|
||||
@@ -481,11 +581,12 @@ function formatCoin(amount: number) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.card-tags {
|
||||
.card-tags,
|
||||
.asset-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
margin-top: 9px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.card-tags span {
|
||||
@@ -496,12 +597,19 @@ function formatCoin(amount: number) {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.asset-row span {
|
||||
color: #6f7c90;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
justify-content: space-between;
|
||||
margin-top: 11px;
|
||||
gap: 8px;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
.card-footer strong {
|
||||
flex: 0 0 auto;
|
||||
color: #ff5f00;
|
||||
font-size: 18px;
|
||||
}
|
||||
@@ -513,6 +621,13 @@ function formatCoin(amount: number) {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.card-footer span {
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mobile-tabbar {
|
||||
position: fixed;
|
||||
right: 12px;
|
||||
|
||||
Reference in New Issue
Block a user