279 lines
8.5 KiB
Vue
279 lines
8.5 KiB
Vue
<template>
|
||
<view class="mine-page">
|
||
<!-- 用户卡片 -->
|
||
<view class="user-card" :style="userCardSafeStyle" @click="openProfile">
|
||
<view class="user-row">
|
||
<view class="user-avatar" :style="avatarBg">
|
||
<image v-if="userInfo.avatar" :src="userInfo.avatar" class="avatar-img" mode="aspectFill" />
|
||
<text v-else class="avatar-letter">{{ initials }}</text>
|
||
</view>
|
||
<view class="user-meta">
|
||
<text class="user-name">{{ userInfo.name || '未设置' }}</text>
|
||
<text class="user-phone">{{ userInfo.phone || '' }}</text>
|
||
</view>
|
||
<view class="role-tag">{{ roleText }}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 店铺管理(老板):分组见 P0 B4 -->
|
||
<view v-if="userInfo.role === 'boss'" class="menu-group">
|
||
<text class="menu-label module-title">店铺与经营</text>
|
||
<view class="menu-card">
|
||
<view class="menu-item" @click="goServiceTypePage">
|
||
<view class="menu-icon-wrap"><AppIcon name="service" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">服务类型</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
<view class="menu-item" @click="goStorePage">
|
||
<view class="menu-icon-wrap"><AppIcon name="store" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">店铺设置</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
<view class="menu-item" @click="goSchedulePage">
|
||
<view class="menu-icon-wrap"><AppIcon name="calendar" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">门店日程</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
<view class="menu-item" @click="goLeadsPage">
|
||
<view class="menu-icon-wrap"><AppIcon name="orders" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">回访池</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="userInfo.role === 'boss'" class="menu-group">
|
||
<text class="menu-label module-title">团队与账号</text>
|
||
<view class="menu-card">
|
||
<view class="menu-item" @click="goStaffPage">
|
||
<view class="menu-icon-wrap"><AppIcon name="staff" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">员工管理</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 员工:仅门店设置(含营业时间) -->
|
||
<view v-else-if="userInfo.role === 'staff'" class="menu-group">
|
||
<text class="menu-label">门店</text>
|
||
<view class="menu-card">
|
||
<view class="menu-item" @click="goStorePage">
|
||
<view class="menu-icon-wrap"><AppIcon name="store" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">店铺设置</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
<view class="menu-item" @click="goSchedulePage">
|
||
<view class="menu-icon-wrap"><AppIcon name="calendar" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">门店日程</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
<view class="menu-item" @click="goLeadsPage">
|
||
<view class="menu-icon-wrap"><AppIcon name="orders" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">回访池</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 个人 -->
|
||
<view class="menu-group">
|
||
<text class="menu-label">个人中心</text>
|
||
<view class="menu-card">
|
||
<view class="menu-item" @click="openProfile">
|
||
<view class="menu-icon-wrap"><AppIcon name="profile" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">个人信息</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
<view class="menu-item" @click="goMyPetsPage">
|
||
<view class="menu-icon-wrap"><AppIcon name="service" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">我的宠物</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
<view class="menu-item" @click="goMyOrdersPage">
|
||
<view class="menu-icon-wrap"><AppIcon name="orders" :size="16" color="#666660" /></view>
|
||
<text class="menu-text">我的订单</text>
|
||
<text class="menu-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="logout-wrap">
|
||
<button class="app-btn-main app-btn-danger-outline" @click="logout">退出登录</button>
|
||
</view>
|
||
<TabBar current-page="mine" @change="goPage" />
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed } from 'vue'
|
||
import TabBar from '../../components/TabBar.vue'
|
||
import AppIcon from '../../components/AppIcon.vue'
|
||
import { clearSession, getUserSession } from '../../utils/session.js'
|
||
import { useNavigator } from '../../composables/useNavigator.js'
|
||
|
||
const userInfo = getUserSession()
|
||
const { goPage, openAppPage } = useNavigator()
|
||
|
||
const goStaffPage = () => uni.navigateTo({ url: '/pages/mine/Staff' })
|
||
const goServiceTypePage = () => uni.navigateTo({ url: '/pages/mine/ServiceType' })
|
||
const goStorePage = () => uni.navigateTo({ url: '/pages/mine/Store' })
|
||
const goSchedulePage = () => uni.navigateTo({ url: '/pages/mine/Schedule' })
|
||
const goLeadsPage = () => uni.navigateTo({ url: '/pages/mine/Leads' })
|
||
const openProfile = () => uni.navigateTo({ url: '/pages/mine/Profile' })
|
||
const goMyPetsPage = () => uni.navigateTo({ url: '/pages/mine/MyPets' })
|
||
const goMyOrdersPage = () => uni.navigateTo({ url: '/pages/mine/MyOrders' })
|
||
|
||
const userCardSafeStyle = (() => {
|
||
const statusBarHeight = uni.getSystemInfoSync?.().statusBarHeight || 20
|
||
let safeTop = statusBarHeight + 12
|
||
const menuRect = uni.getMenuButtonBoundingClientRect?.()
|
||
if (menuRect && menuRect.top && menuRect.height) {
|
||
safeTop = menuRect.top + menuRect.height + 8
|
||
}
|
||
return `padding-top:${safeTop}px;`
|
||
})()
|
||
|
||
const initials = computed(() => {
|
||
if (!userInfo.name) return '?'
|
||
return userInfo.name.slice(0, 1).toUpperCase()
|
||
})
|
||
|
||
const avatarBg = computed(() => {
|
||
if (userInfo.avatar) return {}
|
||
const colors = ['#f5913e', 'var(--c-brand)', '#5090d0', '#e06050', '#8b6914']
|
||
const idx = (userInfo.name?.charCodeAt(0) || 0) % colors.length
|
||
return { background: colors[idx] }
|
||
})
|
||
|
||
const roleText = computed(() => {
|
||
if (userInfo.role === 'boss') return '店长'
|
||
if (userInfo.role === 'customer') return '客户'
|
||
return '员工'
|
||
})
|
||
|
||
const logout = () => {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定退出登录?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
clearSession()
|
||
openAppPage('login')
|
||
}
|
||
}
|
||
})
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.mine-page {
|
||
padding-bottom: calc(76px + env(safe-area-inset-bottom));
|
||
background: #fafaf8;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
/* 用户卡片 */
|
||
.user-card {
|
||
padding: 20px 20px 24px;
|
||
background: #fff;
|
||
border-radius: 0 0 20px 20px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
|
||
}
|
||
.user-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 14px;
|
||
}
|
||
.user-avatar {
|
||
width: 52px; height: 52px;
|
||
border-radius: 16px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
overflow: hidden;
|
||
}
|
||
.avatar-img { width: 100%; height: 100%; }
|
||
.avatar-letter {
|
||
color: #fff;
|
||
font-size: 22px;
|
||
font-weight: 700;
|
||
}
|
||
.user-meta { flex: 1; min-width: 0; }
|
||
.user-name {
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
color: #1a1a1a;
|
||
}
|
||
.user-phone {
|
||
font-size: 13px;
|
||
color: var(--c-text-3);
|
||
margin-top: 2px;
|
||
}
|
||
.role-tag {
|
||
padding: 4px 12px;
|
||
border-radius: 8px;
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
background: var(--c-brand-light);
|
||
color: var(--c-brand);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* 菜单组 */
|
||
.menu-group {
|
||
padding: 0 16px;
|
||
margin-top: 20px;
|
||
}
|
||
.menu-label {
|
||
display: block;
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
color: #bbbbb5;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
margin-bottom: 8px;
|
||
padding-left: 4px;
|
||
}
|
||
.menu-card {
|
||
background: #fff;
|
||
border-radius: 14px;
|
||
overflow: hidden;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.03);
|
||
}
|
||
.menu-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 14px 16px;
|
||
gap: 12px;
|
||
}
|
||
.menu-item + .menu-item {
|
||
border-top: 1px solid #f5f5f2;
|
||
}
|
||
.menu-icon-wrap {
|
||
width: 32px; height: 32px;
|
||
border-radius: 10px;
|
||
background: #f5f5f2;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
.menu-text {
|
||
flex: 1;
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
color: #1a1a1a;
|
||
}
|
||
.menu-arrow {
|
||
color: #ddddd8;
|
||
font-size: 18px;
|
||
font-weight: 300;
|
||
}
|
||
|
||
/* 退出 */
|
||
.logout-wrap {
|
||
padding: 24px 16px;
|
||
}
|
||
</style>
|