登陆注册界面优化了

This commit is contained in:
yml
2026-05-22 20:38:52 +08:00
parent 5f1a7f46a8
commit aa9410b990
9 changed files with 1864 additions and 379 deletions
+162 -141
View File
@@ -8,7 +8,8 @@ const loading = ref(false);
const loadFailed = ref(false);
const listings = ref<Listing[]>([]);
const filterOpen = ref(false);
const activeSort = ref("默认");
const activeSort = ref(0);
const activeFilter = ref([]);
const channels = [
{ label: "全部", icon: "🔥" },
@@ -17,8 +18,18 @@ const channels = [
{ label: "扫码号", icon: "📱" },
{ label: "包夜", icon: "🌙" },
];
const sortOptions = ["默认", "价格", "比例", "哈夫币", "筛选"];
const quickFilters = ["三角洲行动", "安卓/扫码", "高段位", "可包夜"];
const sortOptions = [
{ text: "默认", value: 0 },
{ text: "价格", value: 1 },
{ text: "比例", value: 2 },
{ text: "哈夫币", value: 3 },
];
const quickFilters = [
{ text: "三角洲行动", value: "a" },
{ text: "安卓/扫码", value: "b" },
{ text: "高段位", value: "c" },
{ text: "可包夜", value: "d" },
];
const fallbackListings: Listing[] = [
{
@@ -143,10 +154,13 @@ function formatRatio(item: Listing) {
}
return `${Math.round(item.haf_coin_amount / item.price_hourly / 10000)}W/元`;
}
const searchValue = ref("");
</script>
<template>
<main class="mobile-shell">
<!-- 顶部品牌区 - 保留手写样式 -->
<section class="mobile-hero">
<div class="mobile-topbar">
<div class="mobile-brand">
@@ -159,15 +173,21 @@ function formatRatio(item: Listing) {
<button class="mobile-service" type="button">客服</button>
</div>
<label class="mobile-search">
<span>🔍</span>
<input type="search" placeholder="搜区服 / 段位 / 哈夫币数量" />
</label>
<!-- 搜索栏 van-search -->
<van-search
v-model="searchValue"
shape="round"
placeholder="搜区服 / 段位 / 哈夫币数量"
class="home-search"
/>
<div class="fraud-alert">
<span>防骗提示</span>
平台担保交易拒绝私下转账/共享验证码交接全程留痕
</div>
<!-- 防骗提示 van-notice-bar -->
<van-notice-bar
left-icon="warning"
scrollable
text="平台担保交易,拒绝私下转账/共享验证码,交接全程留痕。"
class="fraud-notice"
/>
<div class="mobile-banner">
<div>
@@ -180,13 +200,19 @@ function formatRatio(item: Listing) {
</section>
<section class="mobile-content">
<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>
<!-- 频道按钮组 van-grid -->
<van-grid :column-num="5" :border="false" class="channel-grid">
<van-grid-item v-for="item in channels" :key="item.label">
<template #icon>
<span class="channel-icon">{{ item.icon }}</span>
</template>
<template #text>
<span class="channel-label">{{ item.label }}</span>
</template>
</van-grid-item>
</van-grid>
<!-- 数据背书面板 - 保留手写样式 -->
<div class="trust-panel" aria-label="交易数据背书">
<div v-for="item in platformStats" :key="item.label">
<strong>{{ item.value }}</strong>
@@ -194,31 +220,29 @@ function formatRatio(item: Listing) {
</div>
</div>
<div class="sort-bar" aria-label="排序方式">
<button
v-for="item in sortOptions"
:key="item"
:class="{ active: activeSort === item }"
type="button"
@click="
item === '筛选' ? (filterOpen = !filterOpen) : (activeSort = item)
"
>
{{ item }}<span v-if="item === '筛选'"></span>
</button>
</div>
<!-- 排序/筛选 van-dropdown-menu -->
<van-dropdown-menu class="sort-dropdown">
<van-dropdown-item v-model="activeSort" :options="sortOptions" />
<van-dropdown-item
v-model="activeFilter"
:options="quickFilters"
title="筛选"
/>
</van-dropdown-menu>
<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>
<!-- 加载/错误状态 -->
<van-loading v-if="loading" class="state-loading" size="24px" vertical>
正在加载优质账号...
</van-loading>
<van-notice-bar
v-else-if="loadFailed"
left-icon="info-o"
color="#6b7a90"
background="transparent"
text="接口暂不可用,当前展示移动端示例数据。"
/>
<!-- 列表卡片 - 保留手写 mobile-card 样式 -->
<div class="mobile-list">
<RouterLink
v-for="item in displayListings"
@@ -262,15 +286,14 @@ function formatRatio(item: Listing) {
</div>
</section>
<nav class="mobile-tabbar" aria-label="底部导航">
<RouterLink to="/m" class="tab-item active">首页</RouterLink>
<RouterLink to="/m/listings" class="tab-item">租号</RouterLink>
<RouterLink to="/m/seller/listings/create" class="publish-tab"
>发布</RouterLink
>
<RouterLink to="/m/orders" class="tab-item">订单</RouterLink>
<RouterLink to="/m/profile" class="tab-item">我的</RouterLink>
</nav>
<!-- 底部 TabBar van-tabbar route -->
<van-tabbar route class="home-tabbar">
<van-tabbar-item to="/m" icon="home-o">首页</van-tabbar-item>
<van-tabbar-item to="/m/listings" icon="search">租号</van-tabbar-item>
<van-tabbar-item to="/m/seller/listings/create" icon="add-o" class="tabbar-publish">发布</van-tabbar-item>
<van-tabbar-item to="/m/orders" icon="orders-o">订单</van-tabbar-item>
<van-tabbar-item to="/m/profile" icon="manager-o">我的</van-tabbar-item>
</van-tabbar>
</main>
</template>
@@ -282,6 +305,7 @@ function formatRatio(item: Listing) {
padding-bottom: 92px;
}
/* ========== Hero 区域 ========== */
.mobile-hero {
overflow: hidden;
border-radius: 0 0 28px 28px;
@@ -292,8 +316,7 @@ function formatRatio(item: Listing) {
.mobile-topbar,
.mobile-brand,
.card-title-row,
.card-footer,
.mobile-tabbar {
.card-footer {
display: flex;
align-items: center;
}
@@ -337,41 +360,40 @@ function formatRatio(item: Listing) {
padding: 7px 12px;
}
.mobile-search {
display: flex;
align-items: center;
gap: 8px;
/* ========== van-search 覆盖样式 ========== */
.home-search {
margin-top: 12px;
border-radius: 999px;
background: #ffffff;
padding: 11px 14px;
box-shadow: 0 10px 24px rgba(0, 54, 135, 0.12);
padding: 0;
background: transparent;
}
.mobile-search input {
min-width: 0;
flex: 1;
border: 0;
outline: 0;
.home-search :deep(.van-search__content) {
border-radius: 999px;
background: #ffffff;
box-shadow: 0 10px 24px rgba(0, 54, 135, 0.12);
padding: 8px 14px;
}
.home-search :deep(.van-search__content .van-field__control) {
color: #17233d;
font-size: 14px;
}
.fraud-alert {
/* ========== van-notice-bar 防骗提示 ========== */
.fraud-notice {
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;
.fraud-notice :deep(.van-notice-bar__left-icon) {
color: #5c3b00;
}
/* ========== Banner ========== */
.mobile-banner {
display: flex;
justify-content: space-between;
@@ -422,46 +444,39 @@ function formatRatio(item: Listing) {
transform: rotate(8deg);
}
/* ========== Content 区 ========== */
.mobile-content {
padding: 14px;
}
.channel-strip,
.sort-bar,
.filter-panel {
display: flex;
gap: 8px;
overflow-x: auto;
padding-bottom: 2px;
scrollbar-width: none;
/* ========== van-grid 频道 ========== */
.channel-grid {
margin-top: 0;
}
.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;
.channel-grid :deep(.van-grid-item__content) {
padding: 11px 6px;
background: #ffffff;
color: #24324a;
padding: 11px 12px;
font-size: 12px;
font-weight: 800;
border-radius: 16px;
box-shadow: 0 8px 22px rgba(23, 35, 61, 0.06);
}
.channel-strip span {
font-size: 18px;
.channel-grid :deep(.van-grid-item__content--surround::after) {
display: none;
}
.channel-icon {
font-size: 22px;
line-height: 1;
}
.channel-label {
font-size: 12px;
font-weight: 800;
color: #24324a;
}
/* ========== 数据背书面板 ========== */
.trust-panel {
display: grid;
grid-template-columns: repeat(3, 1fr);
@@ -494,46 +509,38 @@ function formatRatio(item: Listing) {
font-size: 11px;
}
.sort-bar {
position: sticky;
top: 0;
z-index: 10;
/* ========== van-dropdown-menu 排序筛选 ========== */
.sort-dropdown {
margin: 12px -14px 0;
border-radius: 0;
}
.sort-dropdown :deep(.van-dropdown-menu__bar) {
background: rgba(238, 245, 255, 0.92);
padding: 10px 14px 8px;
backdrop-filter: blur(12px);
box-shadow: none;
}
.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;
.sort-dropdown :deep(.van-dropdown-menu__title) {
font-weight: 800;
color: #4d5b73;
font-size: 14px;
}
.sort-bar button.active {
background: #1479ff;
color: #ffffff;
.sort-dropdown :deep(.van-dropdown-menu__title--active) {
color: #1479ff;
}
.sort-bar button span {
margin-left: 2px;
}
.mobile-tip {
margin: 12px 2px;
/* ========== 加载状态 ========== */
.state-loading {
display: flex;
justify-content: center;
padding: 20px 0;
color: #6b7a90;
font-size: 13px;
}
/* ========== 卡片列表 ========== */
.mobile-list {
display: grid;
gap: 12px;
@@ -655,45 +662,59 @@ function formatRatio(item: Listing) {
white-space: nowrap;
}
.mobile-tabbar {
/* ========== van-tabbar 底部导航 ========== */
.home-tabbar {
position: fixed;
right: 12px;
bottom: 12px;
left: 12px;
z-index: 20;
justify-content: space-around;
height: 60px;
border-radius: 22px;
background: rgba(255, 255, 255, 0.96);
box-shadow: 0 16px 36px rgba(23, 35, 61, 0.16);
backdrop-filter: blur(14px);
padding: 0;
}
.tab-item {
.home-tabbar :deep(.van-tabbar) {
border-radius: 22px;
height: 60px;
}
.home-tabbar :deep(.van-tabbar-item) {
color: #708097;
font-size: 12px;
font-weight: 800;
}
.tab-item.active {
.home-tabbar :deep(.van-tabbar-item--active) {
color: #1479ff;
}
.publish-tab {
display: grid;
width: 58px;
height: 58px;
place-items: center;
border: 5px solid #eef5ff;
border-radius: 50%;
background: linear-gradient(180deg, #ffb21a, #ff6a00);
color: #ffffff;
font-size: 13px;
font-weight: 900;
transform: translateY(-18px);
box-shadow: 0 10px 24px rgba(255, 106, 0, 0.35);
.home-tabbar :deep(.van-tabbar-item__icon) {
font-size: 20px;
}
/* 发布按钮特殊样式 */
.tabbar-publish :deep(.van-tabbar-item__icon) {
display: grid;
width: 48px;
height: 48px;
place-items: center;
border-radius: 50%;
background: linear-gradient(180deg, #ffb21a, #ff6a00);
color: #ffffff !important;
font-size: 22px;
transform: translateY(-8px);
box-shadow: 0 8px 20px rgba(255, 106, 0, 0.35);
}
.tabbar-publish :deep(.van-tabbar-item__text) {
color: #ff6a00;
}
/* ========== 响应式适配 ========== */
@media (min-width: 520px) {
.mobile-shell {
max-width: 430px;
@@ -701,7 +722,7 @@ function formatRatio(item: Listing) {
box-shadow: 0 0 0 1px rgba(23, 35, 61, 0.08);
}
.mobile-tabbar {
.home-tabbar {
right: calc((100vw - 430px) / 2 + 12px);
left: calc((100vw - 430px) / 2 + 12px);
}