Files
pingxiangcard/src/pages/profile/index.vue
T
2026-07-29 13:53:24 +08:00

394 lines
8.0 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.
<template>
<view class="page">
<!-- 头部:风景图 + 用户信息 -->
<image
class="hero-bg"
src="https://aliyunoss.hn12301.net/sd/pingxiang_wo_bj.png"
mode="widthFix"
/>
<view class="profile-hero">
<view class="hero-overlay" />
<view class="hero-content">
<view class="avatar-wrap">
<image class="avatar" src="/static/logo.png" mode="aspectFill" />
</view>
<view class="user-info">
<text class="nickname">{{ userStore.isLogin ? formatPhone(userStore.userInfo?.phone) : '未登录' }}</text>
<text class="user-desc" v-if="userStore.isLogin">欢迎使用爱上萍乡</text>
<text class="user-desc user-desc--link" v-else @click="goLogin">点击登录 →</text>
</view>
</view>
</view>
<!-- 功能菜单 -->
<view class="menu-section">
<view class="menu-card">
<view class="menu-item" @click="goOrders">
<view class="menu-icon-wrap menu-icon-wrap--warning">
<view class="icon-order" />
</view>
<text class="menu-text">订单管理</text>
<view class="menu-chevron" />
</view>
<view class="menu-item" @click="goUsageGuide">
<view class="menu-icon-wrap menu-icon-wrap--primary">
<view class="icon-rule" />
</view>
<text class="menu-text">使用说明</text>
<view class="menu-chevron" />
</view>
<view class="menu-item" @click="goFaq">
<view class="menu-icon-wrap menu-icon-wrap--success">
<view class="icon-faq" />
</view>
<text class="menu-text">常见问题</text>
<view class="menu-chevron" />
</view>
<view class="menu-item menu-item--last" @click="callService">
<view class="menu-icon-wrap menu-icon-wrap--error">
<view class="icon-phone" />
</view>
<text class="menu-text">客服热线</text>
<view class="menu-chevron" />
</view>
</view>
</view>
<!-- 退出登录 -->
<view class="btn-area" v-if="userStore.isLogin">
<view class="btn-logout" @click="handleLogout">
<text>退出登录</text>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { useUserStore } from '../../store/user'
const userStore = useUserStore()
/** 跳转到登录页 */
function goLogin() { uni.navigateTo({ url: '/pages/login/login' }) }
/** 跳转到指定页面(未登录则先跳登录页) */
function goTo(url: string) {
if (!userStore.isLogin) { uni.navigateTo({ url: '/pages/login/login' }); return }
uni.navigateTo({ url })
}
/** 退出登录(弹窗确认后清除 token) */
function handleLogout() {
uni.showModal({
title: '提示', content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
userStore.logout()
uni.showToast({ title: '已退出', icon: 'success' })
}
}
})
}
/** 显示「即将上线」提示 */
function showComingSoon() { uni.showToast({ title: '即将上线,敬请期待', icon: 'none' }) }
/** 跳转 FAQ */
function goFaq() { uni.navigateTo({ url: '/packages/content/pages/faq' }) }
/** 跳转使用说明 */
function goUsageGuide() { uni.navigateTo({ url: '/packages/content/pages/usage-guide' }) }
/** 跳转订单列表 */
function goOrders() { uni.navigateTo({ url: '/packages/user/pages/order/list' }) }
/** 拨打客服热线 */
function callService() { uni.makePhoneCall({ phoneNumber: '400-123-0101' }) }
/** 手机号脱敏显示(138****5678) */
function formatPhone(phone?: string) {
if (!phone) return '已登录'
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
</script>
<style>
page{
background: #fff;
}
</style>
<style lang="scss" scoped>
.page {
min-height: 100vh;
}
/* Hero header */
.profile-hero {
position: relative;
height: 380rpx;
overflow: hidden;
padding-top: 120rpx;
}
.hero-bg {
position: absolute;
left: 0;
width: 100%;
height: 100%;
}
.hero-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.hero-content {
position: relative;
z-index: 2;
display: flex;
align-items: center;
padding: $spacing-10 $spacing-4 $spacing-4;
}
.avatar-wrap {
margin-right: $spacing-3;
flex-shrink: 0;
}
.avatar {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
border: 4rpx solid rgba(255, 255, 255, 0.4);
background: $uv-info-light;
}
.user-info {
display: flex;
flex-direction: column;
}
.nickname {
font-family: $font-family-display;
font-size: $font-size-title;
font-weight: $font-weight-bold;
color: #1B1613;
margin-bottom: $spacing-1;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.3);
}
.user-desc {
font-size: $font-size-sm;
color: #403D3A;
&--link {
color: $uv-warning;
}
}
/* Menu section */
.menu-section {
padding: $spacing-3;
margin-top: -25rpx;
position: relative;
z-index: 3;
}
.menu-card {
background: $color-card;
border-radius: $radius-lg;
box-shadow: 0 4rpx 16rpx rgba(15, 23, 42, 0.15);
overflow: hidden;
}
.menu-item {
display: flex;
align-items: center;
padding: $spacing-3 $spacing-4;
border-bottom: $border-width solid $uv-border-color;
transition: background $transition-fast;
&:active {
background: $uv-info-light;
}
&--last {
border-bottom: none;
}
}
.menu-icon-wrap {
width: 64rpx;
height: 64rpx;
border-radius: $radius-lg;
display: flex;
align-items: center;
justify-content: center;
margin-right: $spacing-3;
flex-shrink: 0;
&--primary {
background: $uv-primary-light;
}
&--warning {
background: $uv-warning-light;
}
&--success {
background: $uv-success-light;
}
&--error {
background: $uv-error-light;
}
}
/* CSS icons */
.icon-order {
width: 22rpx;
height: 26rpx;
border: 3rpx solid $uv-warning;
border-radius: 4rpx;
position: relative;
&::before {
content: '';
position: absolute;
top: 6rpx;
left: 4rpx;
width: 10rpx;
height: 3rpx;
background: $uv-warning;
}
&::after {
content: '';
position: absolute;
top: 14rpx;
left: 4rpx;
width: 8rpx;
height: 3rpx;
background: $uv-warning;
}
}
.icon-rule {
width: 22rpx;
height: 26rpx;
border: 3rpx solid $uv-primary;
border-radius: 4rpx;
position: relative;
&::before {
content: '';
position: absolute;
top: 5rpx;
left: 4rpx;
width: 10rpx;
height: 3rpx;
background: $uv-primary;
}
&::after {
content: '';
position: absolute;
top: 12rpx;
left: 4rpx;
width: 10rpx;
height: 3rpx;
background: $uv-primary;
}
}
.icon-faq {
width: 24rpx;
height: 24rpx;
border: 3rpx solid $uv-success;
border-radius: 50%;
position: relative;
&::before {
content: '?';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 16rpx;
font-weight: $font-weight-bold;
color: $uv-success;
line-height: 1;
}
}
.icon-phone {
width: 18rpx;
height: 26rpx;
border: 3rpx solid $uv-error;
border-radius: 6rpx;
position: relative;
&::before {
content: '';
position: absolute;
bottom: 3rpx;
left: 50%;
transform: translateX(-50%);
width: 8rpx;
height: 3rpx;
background: $uv-error;
border-radius: 2rpx;
}
}
.menu-text {
flex: 1;
font-size: $font-size-base;
color: $uv-main-color;
font-weight: $font-weight-medium;
}
.menu-chevron {
width: 10rpx;
height: 10rpx;
border-top: 2rpx solid $uv-light-color;
border-right: 2rpx solid $uv-light-color;
transform: rotate(45deg);
flex-shrink: 0;
}
/* Logout button */
.btn-area {
padding: $spacing-5 $spacing-3;
}
.btn-logout {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 88rpx;
background: $color-card;
border-radius: $radius-full;
box-shadow: $shadow-sm;
transition: transform $transition-fast;
&:active {
transform: scale(0.98);
}
text {
font-size: $font-size-base;
color: $uv-error;
font-weight: $font-weight-medium;
}
}
</style>