OfficeSystem/pages/my/profile/index.vue
2025-11-24 09:16:54 +08:00

450 lines
11 KiB
Vue
Raw Permalink 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="profile-detail-page">
<!-- 自定义导航栏 -->
<view class="custom-navbar">
<view class="navbar-content">
<text class="nav-btn" @click="handleBack"></text>
<text class="nav-title">个人资料</text>
<text class="nav-btn" style="opacity: 0;">占位</text>
</view>
</view>
<!-- 内容区域 -->
<scroll-view class="content-scroll" scroll-y>
<!-- 头像和基本信息卡片 -->
<view class="profile-header-card">
<view class="avatar-section">
<view class="avatar-wrapper-large">
<image
v-if="userInfo?.user?.avatar"
class="avatar-img-large"
:src="userInfo.user.avatar"
mode="aspectFill"
/>
<view v-else class="avatar-placeholder-large">
<text class="avatar-text-large">{{ getAvatarText(userInfo?.user?.nickName) }}</text>
</view>
</view>
<view class="user-basic-info">
<text class="user-name-large">{{ userInfo?.user?.nickName || '--' }}</text>
<view style="display: flex;align-items: center;gap: 10px">
<view class="user-dept-large">{{ userInfo?.user?.deptName || '--' }}</view>
<!-- <view class="role-tags" v-if="userInfo?.roles && userInfo.roles.length > 0">-->
<!-- <text-->
<!-- class="role-tag"-->
<!-- v-for="(role, index) in userInfo.roles"-->
<!-- :key="index"-->
<!-- >-->
<!-- {{ role }}-->
<!-- </text>-->
<!-- </view>-->
</view>
</view>
</view>
</view>
<!-- 统计信息卡片 -->
<!-- <view class="info-card stats-card">-->
<!-- <view class="card-title">工作统计</view>-->
<!-- <view class="stats-grid">-->
<!-- <view class="stat-box">-->
<!-- <text class="stat-number">{{ userInfo?.user?.taskCount || 0 }}</text>-->
<!-- <text class="stat-desc">任务数</text>-->
<!-- </view>-->
<!-- <view class="stat-box">-->
<!-- <text class="stat-number">{{ userInfo?.user?.projectCount || 0 }}</text>-->
<!-- <text class="stat-desc">项目数</text>-->
<!-- </view>-->
<!-- <view class="stat-box">-->
<!-- <text class="stat-number">{{ userInfo?.user?.taskNum || 0 }}</text>-->
<!-- <text class="stat-desc">任务编号</text>-->
<!-- </view>-->
<!-- </view>-->
<!-- </view>-->
<!-- 基本信息卡片 -->
<view class="info-card">
<view class="card-title">基本信息</view>
<view class="info-list">
<view class="info-item">
<text class="info-label">用户名</text>
<text class="info-value">{{ userInfo?.user?.userName || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">工号</text>
<text class="info-value">{{ userInfo?.user?.userNo || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">手机号</text>
<text class="info-value">{{ userInfo?.user?.phonenumber || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">邮箱</text>
<text class="info-value">{{ userInfo?.user?.email || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">性别</text>
<text class="info-value">{{ getSexText(userInfo?.user?.sex) }}</text>
</view>
<view class="info-item">
<text class="info-label">生日</text>
<text class="info-value">{{ userInfo?.user?.birthday || '--' }}</text>
</view>
</view>
</view>
<!-- 部门信息卡片 -->
<view class="info-card" v-if="userInfo?.user?.dept">
<view class="card-title">部门信息</view>
<view class="info-list">
<view class="info-item">
<text class="info-label">部门名称</text>
<text class="info-value">{{ userInfo.user.dept.deptName || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">部门负责人</text>
<text class="info-value">{{ userInfo.user.dept.leader || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">部门邮箱</text>
<text class="info-value">{{ userInfo.user.dept.email || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">部门电话</text>
<text class="info-value">{{ userInfo.user.dept.phone || '--' }}</text>
</view>
</view>
</view>
<!-- 工作信息卡片 -->
<view class="info-card">
<view class="card-title">工作信息</view>
<view class="info-list">
<view class="info-item">
<text class="info-label">入职日期</text>
<text class="info-value">{{ userInfo?.user?.employDate || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">离职日期</text>
<text class="info-value">{{ userInfo?.user?.resignDate || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">创建时间</text>
<text class="info-value">{{ userInfo?.user?.createTime || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">最后登录</text>
<text class="info-value">{{ userInfo?.user?.loginDate || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">登录IP</text>
<text class="info-value">{{ userInfo?.user?.loginIp || '--' }}</text>
</view>
<view class="info-item">
<text class="info-label">状态</text>
<text class="info-value" :class="getStatusClass(userInfo?.user?.status)">
{{ getStatusText(userInfo?.user?.status) }}
</text>
</view>
</view>
</view>
<!-- 权限信息卡片 -->
<!-- <view class="info-card" v-if="userInfo?.permissions && userInfo.permissions.length > 0">-->
<!-- <view class="card-title">权限信息</view>-->
<!-- <view class="permissions-list">-->
<!-- <text -->
<!-- class="permission-tag" -->
<!-- v-for="(permission, index) in userInfo.permissions" -->
<!-- :key="index"-->
<!-- >-->
<!-- {{ permission }}-->
<!-- </text>-->
<!-- </view>-->
<!-- </view>-->
<!-- 备注信息 -->
<view class="info-card" v-if="userInfo?.user?.remark">
<view class="card-title">备注</view>
<view class="remark-content">
<text>{{ userInfo.user.remark }}</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
const { userInfo } = storeToRefs(userStore)
// 获取头像文字
const getAvatarText = (name) => {
if (!name) return '?'
return name.charAt(0).toUpperCase()
}
// 获取性别文本
const getSexText = (sex) => {
if (sex === '0') return '女'
if (sex === '1') return '男'
return '--'
}
// 获取状态文本
const getStatusText = (status) => {
if (status === '0') return '正常'
if (status === '1') return '停用'
return '--'
}
// 获取状态样式类
const getStatusClass = (status) => {
if (status === '0') return 'status-normal'
if (status === '1') return 'status-disabled'
return ''
}
// 返回
const handleBack = () => {
uni.navigateBack()
}
</script>
<style lang="scss" scoped>
.profile-detail-page {
box-sizing: border-box;
display: flex;
flex-direction: column;
//height: 100vh;
background-color: #f5f5f5;
}
.custom-navbar {
background-color: #fff;
padding-top: var(--status-bar-height, 0);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
position: relative;
z-index: 100;
}
.navbar-content {
display: flex;
align-items: center;
justify-content: space-between;
height: 44px;
padding: 0 16px;
}
.nav-btn {
font-size: 24px;
color: #333;
font-weight: bold;
min-width: 44px;
text-align: center;
}
.nav-title {
font-size: 18px;
font-weight: 600;
color: #333;
flex: 1;
text-align: center;
}
.content-scroll {
box-sizing: border-box;
flex: 1;
padding: 16px;
}
.profile-header-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 16px;
padding: 32px 24px;
margin-bottom: 16px;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}
.avatar-section {
display: flex;
align-items: center;
}
.avatar-wrapper-large {
width: 64px;
height: 64px;
border-radius: 50%;
overflow: hidden;
background: rgba(255, 255, 255, 0.2);
border: 4px solid rgba(255, 255, 255, 0.3);
margin-right: 24px;
flex-shrink: 0;
}
.avatar-img-large {
width: 100%;
height: 100%;
}
.avatar-placeholder-large {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.2);
}
.avatar-text-large {
font-size: 48px;
font-weight: 600;
color: #ffffff;
}
.user-basic-info {
flex: 1;
display: flex;
flex-direction: column;
}
.user-name-large {
font-size: 28px;
font-weight: 600;
color: #ffffff;
margin-bottom: 8px;
}
.user-dept-large {
font-size: 16px;
color: rgba(255, 255, 255, 0.9);
}
.role-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.role-tag {
font-size: 12px;
background: rgba(255, 255, 255, 0.25);
color: #ffffff;
padding: 4px 12px;
border-radius: 12px;
font-weight: 500;
}
.info-card {
background: #ffffff;
border-radius: 12px;
padding: 20px;
margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.card-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid #f0f0f0;
}
.stats-card {
.stats-grid {
display: flex;
justify-content: space-around;
padding: 16px 0;
}
.stat-box {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.stat-number {
font-size: 32px;
font-weight: 600;
color: #667eea;
margin-bottom: 8px;
}
.stat-desc {
font-size: 14px;
color: #666;
}
}
.info-list {
display: flex;
flex-direction: column;
}
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 0;
border-bottom: 1px solid #f5f5f5;
&:last-child {
border-bottom: none;
}
}
.info-label {
font-size: 14px;
color: #666;
flex-shrink: 0;
}
.info-value {
font-size: 14px;
color: #333;
text-align: right;
flex: 1;
margin-left: 16px;
&.status-normal {
color: #67c23a;
}
&.status-disabled {
color: #f56c6c;
}
}
.permissions-list {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.permission-tag {
font-size: 12px;
background: #f0f7ff;
color: #409eff;
padding: 6px 12px;
border-radius: 12px;
font-weight: 500;
}
.remark-content {
font-size: 14px;
color: #666;
line-height: 1.6;
padding: 8px 0;
}
</style>