Files
hfb_sys/frontend/src/views/mobile/MobileProfileView.vue
T
2026-05-22 21:00:27 +08:00

488 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed } from "vue";
import { useRouter } from "vue-router";
import { useSessionStore } from "@/stores/session";
const session = useSessionStore();
const router = useRouter();
const isLoggedIn = computed(() => Boolean(session.token));
const displayName = computed(() => session.phone ? `用户${session.phone.slice(-6)}` : `用户${session.userId || 883099}`);
const displayId = computed(() => session.userId || 138865);
const maskedPhone = computed(() => session.phone ? `${session.phone.slice(0, 3)}****${session.phone.slice(-4)}` : "登录后查看手机号");
const sellerOrders = [
{ label: "商品管理", icon: "🛍️", to: "/m/seller/listings/create" },
{ label: "交易中", icon: "📦", to: "/m/orders" },
{ label: "已完成", icon: "✈️", to: "/m/orders" },
{ label: "退款/售后", icon: "💴", to: "/m/orders" },
];
const buyerOrders = [
{ label: "未支付", icon: "💳", to: "/m/orders" },
{ label: "交易中", icon: "🪙", to: "/m/orders" },
{ label: "已完成", icon: "☑️", to: "/m/orders" },
{ label: "退款/售后", icon: "🧾", to: "/m/orders" },
];
const serviceItems = ["收款账户", "余额明细", "提现记录", "商务合作", "我的代练", "我的代肝", "我的收藏", "我的打赏", "我的邀请"];
const serviceIcons = ["👥", "🪙", "💸", "💼", "⚔️", "💎", "⭐", "💰", "🎁"];
function logout() {
session.logout();
}
function goToLogin() {
router.push("/m/login");
}
</script>
<template>
<main class="mobile-profile-shell">
<!-- 未登录区 - 自定义卡片布局 -->
<template v-if="!isLoggedIn">
<section class="guest-card">
<div class="guest-logo">锤</div>
<h1>登录大锤商行</h1>
<p>登录后查看订单、管理发布、提现余额,并享受平台担保交易服务。</p>
<van-button type="primary" block round class="guest-login-btn" @click="goToLogin">
立即登录
</van-button>
<div class="guest-benefits">
<van-tag type="primary" plain size="medium" round>担保交易</van-tag>
<van-tag type="primary" plain size="medium" round>订单留痕</van-tag>
<van-tag type="primary" plain size="medium" round>安全交接</van-tag>
</div>
</section>
</template>
<!-- 已登录区 -->
<template v-else>
<!-- 头像区 -->
<section class="profile-header">
<van-image
round
width="64px"
height="64px"
src=""
class="avatar-image"
>
<template #error>
<div class="avatar-fallback">👤</div>
</template>
</van-image>
<div class="profile-user">
<h1>{{ displayName }}<span class="edit-icon">✎</span></h1>
<p>ID:{{ displayId }} · {{ maskedPhone }}</p>
</div>
<van-icon name="setting-o" size="24" class="setting-icon" />
</section>
<!-- 余额卡片 - 两行结构 -->
<van-cell-group inset class="balance-group">
<van-cell center class="balance-main">
<template #title>
<span class="balance-label">账户余额(元)</span>
</template>
<template #value>
<strong class="balance-value">¥0.00</strong>
</template>
</van-cell>
<van-cell class="balance-actions">
<template #title>
<van-button size="mini" plain hairline type="warning" class="detail-btn">查看明细</van-button>
</template>
<template #value>
<van-button type="primary" size="small" round class="withdraw-btn">提现</van-button>
</template>
</van-cell>
</van-cell-group>
</template>
<!-- 订单菜单 -->
<section class="menu-section">
<h2>我的订单</h2>
<van-grid :column-num="4" :border="false" class="order-grid">
<van-grid-item
v-for="item in sellerOrders"
:key="item.label"
:to="item.to"
>
<template #icon>
<span class="menu-icon">{{ item.icon }}</span>
</template>
<template #text>
<span class="menu-text">{{ item.label }}</span>
</template>
</van-grid-item>
</van-grid>
</section>
<!-- 我买的 -->
<section class="menu-section">
<h2>我买的</h2>
<van-grid :column-num="4" :border="false" class="order-grid">
<van-grid-item
v-for="item in buyerOrders"
:key="item.label"
:to="item.to"
>
<template #icon>
<span class="menu-icon">{{ item.icon }}</span>
</template>
<template #text>
<span class="menu-text">{{ item.label }}</span>
</template>
</van-grid-item>
</van-grid>
</section>
<!-- 服务菜单 -->
<van-cell-group inset class="service-group">
<van-grid :column-num="4" :border="false" class="service-grid">
<van-grid-item
v-for="(item, index) in serviceItems"
:key="item"
>
<template #icon>
<span class="menu-icon">{{ serviceIcons[index] }}</span>
</template>
<template #text>
<span class="menu-text">{{ item }}</span>
</template>
</van-grid-item>
</van-grid>
</van-cell-group>
<!-- 退出登录 -->
<van-button
v-if="isLoggedIn"
plain
type="danger"
block
class="logout-btn"
@click="logout"
>
退出登录
</van-button>
<!-- 底部导航 - 手写原生,和首页一致 -->
<nav class="bottom-nav">
<RouterLink to="/m" class="nav-item">
<van-icon name="home-o" :size="22" />
<span>首页</span>
</RouterLink>
<RouterLink to="/m/listings" class="nav-item">
<van-icon name="search" :size="22" />
<span>租号</span>
</RouterLink>
<RouterLink to="/m/seller/listings/create" class="nav-item nav-publish">
<div class="publish-pill">+</div>
<span>发布</span>
</RouterLink>
<RouterLink to="/m/orders" class="nav-item">
<van-icon name="orders-o" :size="22" />
<span>订单</span>
</RouterLink>
<RouterLink to="/m/profile" class="nav-item active">
<van-icon name="manager-o" :size="22" />
<span>我的</span>
</RouterLink>
</nav>
</main>
</template>
<style scoped>
.mobile-profile-shell {
min-height: 100vh;
background: #f5f6f8;
color: #1a202c;
padding: 28px 12px 60px;
}
/* ========== 未登录区 - 自定义卡片 ========== */
.guest-card {
text-align: center;
padding: 34px 26px;
margin: 0 2px;
border-radius: 16px;
background: #fff;
box-shadow: 0 8px 26px rgba(24, 30, 45, 0.06);
}
.guest-card h1 {
margin: 18px 0 0;
font-size: 22px;
font-weight: 900;
color: #1a202c;
}
.guest-card p {
margin: 10px 0 0;
font-size: 14px;
color: #667386;
line-height: 1.7;
}
.guest-logo {
display: grid;
width: 74px;
height: 74px;
margin: 0 auto;
place-items: center;
border-radius: 22px;
background: #1477ff;
color: #fff;
font-size: 30px;
font-weight: 900;
}
.guest-login-btn {
margin-top: 20px;
border-radius: 13px;
background: #1477ff;
border-color: transparent;
font-size: 16px;
font-weight: 900;
height: 48px;
}
.guest-benefits {
display: flex;
justify-content: center;
gap: 8px;
margin-top: 16px;
}
.guest-benefits :deep(.van-tag) {
font-weight: 800;
}
/* ========== 已登录头像区 ========== */
.profile-header {
display: flex;
align-items: center;
gap: 14px;
min-height: 120px;
}
.avatar-image {
flex: 0 0 auto;
}
.avatar-fallback {
display: grid;
width: 64px;
height: 64px;
place-items: center;
background: #fff;
border-radius: 50%;
font-size: 32px;
box-shadow: 0 10px 24px rgba(24, 30, 45, 0.08);
}
.profile-user {
min-width: 0;
flex: 1;
}
.profile-user h1 {
overflow: hidden;
margin: 0;
font-size: 20px;
text-overflow: ellipsis;
white-space: nowrap;
}
.edit-icon {
margin-left: 4px;
color: #b7bcc6;
font-size: 14px;
}
.profile-user p {
margin: 7px 0 0;
color: #666f7c;
font-size: 13px;
}
.setting-icon {
color: #8b8f99;
cursor: pointer;
}
/* ========== 余额卡片 - 两行结构 ========== */
.balance-group {
margin-top: 10px;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 8px 26px rgba(24, 30, 45, 0.06);
}
.balance-main :deep(.van-cell__title) {
flex: none;
}
.balance-main :deep(.van-cell__value) {
flex: 1;
text-align: right;
}
.balance-label {
color: #8b8f99;
font-size: 13px;
font-weight: 700;
}
.balance-value {
font-size: 32px;
line-height: 1;
color: #1a202c;
}
.balance-actions {
padding-top: 4px !important;
padding-bottom: 12px !important;
}
.balance-actions :deep(.van-cell__title) {
flex: none;
}
.balance-actions :deep(.van-cell__value) {
flex: 1;
text-align: right;
}
.detail-btn {
border-color: #ff8a42;
color: #ff5f00;
background: #fff5ee;
font-weight: 800;
}
.withdraw-btn {
background: #1477ff;
border-color: transparent;
font-weight: 800;
height: 32px;
padding: 0 20px;
}
/* ========== 订单菜单 ========== */
.menu-section {
margin-top: 12px;
border-radius: 16px;
background: #fff;
padding: 16px 14px;
box-shadow: 0 8px 26px rgba(24, 30, 45, 0.06);
}
.menu-section h2 {
margin: 0 0 12px;
font-size: 18px;
}
.order-grid :deep(.van-grid-item__content) {
padding: 8px 4px;
background: transparent;
}
.menu-icon {
font-size: 25px;
line-height: 1;
}
.menu-text {
font-size: 13px;
font-weight: 700;
color: #5f6671;
}
/* ========== 服务菜单 ========== */
.service-group {
margin-top: 12px;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 8px 26px rgba(24, 30, 45, 0.06);
}
.service-group :deep(.van-cell-group) {
margin: 0;
}
.service-grid :deep(.van-grid-item__content) {
padding: 14px 4px;
background: #fff;
}
/* ========== 退出登录 ========== */
.logout-btn {
margin-top: 14px;
border-radius: 14px;
font-weight: 900;
height: 48px;
font-size: 16px;
}
/* ========== 底部导航 - 手写原生 ========== */
.bottom-nav {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
display: flex;
height: 50px;
background: #fff;
border-top: 1px solid #eee;
}
.nav-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2px;
color: #999;
font-size: 10px;
text-decoration: none;
}
.nav-item.active {
color: #1477ff;
}
.nav-item span {
font-weight: 600;
}
.publish-pill {
width: 36px;
height: 26px;
display: grid;
place-items: center;
border-radius: 13px;
background: #ff6a00;
color: #fff;
font-size: 18px;
font-weight: 900;
}
.nav-publish span {
color: #ff6a00;
}
/* ========== 响应式适配 ========== */
@media (min-width: 520px) {
.mobile-profile-shell {
max-width: 430px;
margin: 0 auto;
box-shadow: 0 0 0 1px rgba(23, 35, 61, 0.08);
}
.bottom-nav {
left: calc((100vw - 430px) / 2);
right: calc((100vw - 430px) / 2);
}
}
</style>