From 25df88d0ab9d7444ed1d162b9efa1259ac2f6f66 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期一, 27 四月 2026 10:13:53 +0800
Subject: [PATCH] 小程序对接finish
---
yuyueMiniProgram/src/pages/mine/index.vue | 150 ++++++++++++++++++++++++++++++-------------------
1 files changed, 91 insertions(+), 59 deletions(-)
diff --git a/yuyueMiniProgram/src/pages/mine/index.vue b/yuyueMiniProgram/src/pages/mine/index.vue
index b4a44cf..2ef937c 100644
--- a/yuyueMiniProgram/src/pages/mine/index.vue
+++ b/yuyueMiniProgram/src/pages/mine/index.vue
@@ -1,5 +1,6 @@
<script setup lang="ts">
-import { ref } from 'vue'
+import { logoutMini } from '@/api/auth'
+import { useMiniAuthStore } from '@/store/auth'
definePage({
name: 'mine',
@@ -9,114 +10,145 @@
},
})
+interface MenuItem {
+ title: string
+ icon: string
+ path: string
+ showFor: Array<'employee' | 'normal'>
+}
+
+const router = useRouter()
+const authStore = useMiniAuthStore()
const sysInfo = uni.getSystemInfoSync()
const statusBarHeight = sysInfo.statusBarHeight || 0
const navBarHeight = 44
-const userRole = ref('employee') // 'employee' 或 'normal'
-
-const menuList = ref([
+const profile = computed(() => authStore.profile)
+const userRole = computed<'employee' | 'normal'>(() => profile.value?.userType === 'EMPLOYEE' ? 'employee' : 'normal')
+const roleLabel = computed(() => {
+ if (userRole.value === 'employee') {
+ return profile.value?.deptLeaderFlag ? '部门领导' : '员工'
+ }
+ return '普通访客'
+})
+const secondaryText = computed(() => {
+ if (!profile.value) {
+ return ''
+ }
+ if (userRole.value === 'employee') {
+ return profile.value.deptName || ''
+ }
+ return profile.value.companyName || ''
+})
+const menuList = ref<MenuItem[]>([
{ title: '预约审核', icon: '/static/mine/review.png', path: '/pages/reviewList/index', showFor: ['employee'] },
{ title: '来访记录', icon: '/static/mine/record.png', path: '/pages/visitRecord/index', showFor: ['employee'] },
{ title: '关于我们', icon: '/static/mine/aboutUs.png', path: '/pages/aboutUs/index', showFor: ['employee', 'normal'] },
{ title: '退出登录', icon: '/static/mine/logout.png', path: '', showFor: ['employee', 'normal'] },
])
-
-function handleMenuClick(item: any) {
- if (item.path) {
- uni.navigateTo({ url: item.path })
- } else if (item.title === '退出登录') {
- uni.showToast({ title: '已退出登录', icon: 'none' })
- }
-}
+const visibleMenus = computed(() => menuList.value.filter(item => item.showFor.includes(userRole.value)))
function handleEditProfile() {
uni.navigateTo({ url: '/pages/profile/index' })
}
+
+async function handleLogout() {
+ try {
+ await logoutMini()
+ }
+ catch (error) {
+ console.warn('mini logout failed', error)
+ }
+ finally {
+ authStore.clearSession()
+ router.replaceAll({ name: 'login' })
+ }
+}
+
+function handleMenuClick(item: MenuItem) {
+ if (item.title === '退出登录') {
+ void handleLogout()
+ return
+ }
+
+ if (item.path) {
+ uni.navigateTo({ url: item.path })
+ }
+}
+
+onShow(() => {
+ authStore.restoreSession()
+})
</script>
<template>
- <view class="h-screen w-full relative box-border flex flex-col overflow-hidden m-0 p-0">
- <!-- 顶部背景图 (被覆盖层) 整个页面的背景 -->
- <view class="absolute left-0 top-0 z-0 h-full w-full pointer-events-none">
- <image src="/static/mine/bg.png" class="w-full h-full" mode="scaleToFill" />
+ <view class="relative m-0 h-screen w-full box-border flex flex-col overflow-hidden p-0">
+ <view class="pointer-events-none absolute left-0 top-0 z-0 h-full w-full">
+ <image src="/static/mine/bg.png" class="h-full w-full" mode="scaleToFill" />
</view>
- <!-- 整体内容背景图 (bgmask覆盖在上面约202rpx处) -->
- <view class="absolute left-0 top-[330rpx] w-full z-0 pointer-events-none" style="height: calc(100% - 330rpx);">
- <image src="/static/mine/bgmask.png" class="w-full h-full" mode="scaleToFill" />
+ <view class="pointer-events-none absolute left-0 top-[330rpx] z-0 w-full" style="height: calc(100% - 330rpx);">
+ <image src="/static/mine/bgmask.png" class="h-full w-full" mode="scaleToFill" />
</view>
- <!-- 自定义导航栏 -->
<view class="relative z-50 w-full shrink-0" :style="{ height: (statusBarHeight + navBarHeight) + 'px' }">
- <view class="fixed left-0 top-0 w-full z-50" :style="{ height: (statusBarHeight + navBarHeight) + 'px' }">
- <view class="flex items-center justify-between w-full absolute left-0 z-10"
+ <view class="fixed left-0 top-0 z-50 w-full" :style="{ height: (statusBarHeight + navBarHeight) + 'px' }">
+ <view class="absolute left-0 z-10 flex w-full items-center justify-between"
:style="{ top: statusBarHeight + 'px', height: navBarHeight + 'px' }">
- <view class="flex h-full w-[88rpx] items-center justify-center relative z-10">
- <!-- 占位,tabbar 页面不需要返回按钮 -->
- </view>
- <view class="absolute left-0 w-full text-center text-[34rpx] font-medium text-white z-0">
+ <view class="relative z-10 flex h-full w-[88rpx] items-center justify-center" />
+ <view class="absolute left-0 z-0 w-full text-center text-[34rpx] font-medium text-white">
预约小程序
</view>
- <view class="w-[88rpx]"></view>
+ <view class="w-[88rpx]" />
</view>
</view>
</view>
- <!-- 用户信息区 -->
- <view class="relative z-10 px-[48rpx] mt-[32rpx] flex items-center shrink-0">
- <view class="relative w-[122rpx] h-[122rpx] rounded-full border-[2rpx] border-solid border-[#0068ff] box-border shrink-0">
- <image src="/static/mine/header.png" class="w-full h-full rounded-full" mode="aspectFill" />
- <!-- 带有 #0068FF 边框的外圈 -->
- <view v-if="userRole === 'employee'" class="absolute bottom-[-4rpx] right-[4rpx] w-[32rpx] h-[32rpx] bg-white border-[2rpx] border-solid border-[#0068FF] box-border rounded-full z-10 flex items-center justify-center">
- <image src="/static/mine/change.png" class="w-[20rpx] h-[20rpx]" mode="aspectFit" />
+ <view class="relative z-10 mt-[32rpx] flex items-center px-[48rpx] shrink-0">
+ <view class="relative h-[122rpx] w-[122rpx] shrink-0 rounded-full border-[2rpx] border-solid border-[#0068ff] box-border">
+ <image :src="profile?.avatarUrl || '/static/mine/header.png'" class="h-full w-full rounded-full" mode="aspectFill" />
+ <view v-if="userRole === 'employee'" class="absolute bottom-[-4rpx] right-[4rpx] z-10 h-[32rpx] w-[32rpx] flex items-center justify-center rounded-full border-[2rpx] border-solid border-[#0068FF] bg-white box-border">
+ <image src="/static/mine/change.png" class="h-[20rpx] w-[20rpx]" mode="aspectFit" />
</view>
</view>
-
+
<view class="ml-[32rpx] flex flex-col justify-center">
- <view class="flex items-center mb-[12rpx]">
- <text class="text-[32rpx] text-[#333333] font-[500]">王明</text>
-
- <!-- 员工角色标签 -->
- <view v-if="userRole === 'employee'" class="ml-[16rpx] w-[96rpx] h-[32rpx] rounded-[18rpx] flex items-center justify-center box-border border-[1rpx] border-solid border-[#FFFFFF]" style="background: linear-gradient(90deg, #68A5FF 0%, #0068FF 107%, rgba(255, 255, 255, 0) 107%);">
- <text class="text-white text-[16rpx]">部门领导</text>
+ <view class="mb-[12rpx] flex items-center">
+ <text class="text-[32rpx] text-[#333333] font-[500]">{{ profile?.displayName || '用户' }}</text>
+
+ <view v-if="userRole === 'employee'" class="ml-[16rpx] flex h-[32rpx] min-w-[96rpx] items-center justify-center rounded-[18rpx] border-[1rpx] border-solid border-[#FFFFFF] px-[12rpx] box-border" style="background: linear-gradient(90deg, #68A5FF 0%, #0068FF 107%, rgba(255, 255, 255, 0) 107%);">
+ <text class="text-[16rpx] text-white">{{ roleLabel }}</text>
</view>
- <!-- 普通用户角色标签 -->
- <image v-else src="/static/mine/edit.png" class="w-[32rpx] mt-[4rpx] h-[32rpx] ml-[10rpx]" mode="aspectFit" @click="handleEditProfile" />
+ <image v-else src="/static/mine/edit.png" class="ml-[10rpx] mt-[4rpx] h-[32rpx] w-[32rpx]" mode="aspectFit" @click="handleEditProfile" />
</view>
-
- <text v-if="userRole === 'employee'" class="text-[28rpx] text-[#666666]">综合管理部</text>
- <view v-if="userRole === 'normal'" class="flex flex-col">
- <text class="text-[28rpx] text-[#666666] mb-[8rpx]">186****4567</text>
- <text class="text-[28rpx] text-[#666666]">成都xxxxx公司</text>
- </view>
+
+ <text v-if="secondaryText" class="mb-[8rpx] text-[28rpx] text-[#666666]">{{ secondaryText }}</text>
+ <text class="text-[28rpx] text-[#666666]">{{ profile?.mobile || '未绑定手机号' }}</text>
+ <text v-if="userRole === 'normal'" class="mt-[8rpx] text-[28rpx] text-[#666666]">{{ roleLabel }}</text>
</view>
</view>
- <!-- 菜单选项卡片 -->
- <view class="relative z-10 px-[32rpx] mt-[80rpx] shrink-0">
- <view class="bg-white rounded-[16rpx] py-[24rpx] w-full" style="box-shadow: 0px 4rpx 8rpx 0px rgba(6, 47, 108, 0.1608);">
- <template v-for="(item, index) in menuList.filter(m => m.showFor.includes(userRole))" :key="index">
- <view
+ <view class="relative z-10 mt-[80rpx] px-[32rpx] shrink-0">
+ <view class="w-full rounded-[16rpx] bg-white py-[24rpx]" style="box-shadow: 0px 4rpx 8rpx 0px rgba(6, 47, 108, 0.1608);">
+ <template v-for="(item, index) in visibleMenus" :key="item.title">
+ <view
class="flex items-center justify-between px-[40rpx] py-[20rpx] active:bg-gray-50 transition-colors"
- :class="index !== menuList.filter(m => m.showFor.includes(userRole)).length - 1 ? 'border-b1' : ''"
+ :class="index !== visibleMenus.length - 1 ? 'border-b1' : ''"
@click="handleMenuClick(item)"
>
<view class="flex items-center">
- <image :src="item.icon" class="w-[56rpx] h-[56rpx] shrink-0" mode="aspectFit" />
- <text class="ml-[16rpx] text-[#000000] text-[28rpx] font-normal">{{ item.title }}</text>
+ <image :src="item.icon" class="h-[56rpx] w-[56rpx] shrink-0" mode="aspectFit" />
+ <text class="ml-[16rpx] text-[28rpx] text-[#000000] font-normal">{{ item.title }}</text>
</view>
<wd-icon name="arrow-right" size="28rpx" color="#000000" />
</view>
</template>
</view>
</view>
-
</view>
</template>
<style>
-/* 针对整个页面的样式重置,强制隐藏原生滚动条并固定页面 */
page {
height: 100%;
overflow: hidden;
--
Gitblit v1.7.1