index.vue 6.85 KB
<template>
  <div class="dashboard-container">
    <div class="dashboard-header">
      <h2>系统概览</h2>
      <p v-if="loading">正在加载用户信息...</p>
      <p v-else>欢迎回来,{{ userInfo?.username || '未知' }}!</p>
    </div>
    
    <div class="dashboard-stats">
      <div class="stat-card">
        <div class="stat-icon">👤</div>
        <div class="stat-content">
          <h3>用户总数</h3>
          <p class="stat-number">1,234</p>
        </div>
      </div>
      
      <div class="stat-card">
        <div class="stat-icon">📈</div>
        <div class="stat-content">
          <h3>今日访问</h3>
          <p class="stat-number">567</p>
        </div>
      </div>
      
      <div class="stat-card">
        <div class="stat-icon">✅</div>
        <div class="stat-content">
          <h3>系统状态</h3>
          <p class="stat-number">正常</p>
        </div>
      </div>
      
      <div class="stat-card">
        <div class="stat-icon">⏱️</div>
        <div class="stat-content">
          <h3>运行时间</h3>
          <p class="stat-number">{{ currentTime }}</p>
        </div>
      </div>
    </div>
    
    <div class="dashboard-content">
      <div class="dashboard-card">
        <h3>系统信息</h3>
        <div class="info-grid">
          <div class="info-item">
            <label>用户名:</label>
            <span v-if="loading">加载中...</span>
            <span v-else>{{ userInfo?.username || '未知' }}</span>
          </div>
          <div class="info-item">
            <label>角色:</label>
            <span v-if="loading">加载中...</span>
            <span v-else>{{ getRoleName(userInfo) || '普通用户' }}</span>
          </div>
          <div class="info-item">
            <label>登录时间:</label>
            <span>{{ currentTime }}</span>
          </div>
          <div class="info-item">
            <label>系统版本:</label>
            <span>v1.0.0</span>
          </div>
        </div>
            </div>
      
      <div class="dashboard-card">
        <h3>快速操作</h3>
        <div class="quick-actions">
          <button class="action-btn">👤 用户管理</button>
          <button class="action-btn">🛡️ 角色管理</button>
          <button class="action-btn">⚙️ 系统设置</button>
          <button class="action-btn">📊 查看日志</button>
        </div>
            </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { request } from '@/utils/request'

const router = useRouter()
const currentTime = ref('')
const userInfo = ref<any>(null)
const loading = ref(false)

// 获取角色名称
const getRoleName = (userInfo: any) => {
  // 优先使用roles字段中的角色信息
  if (userInfo?.roles && Array.isArray(userInfo.roles) && userInfo.roles.length > 0) {
    return userInfo.roles[0].roleName || '普通用户'
  }
  
  // 如果没有roles字段,回退到authorities
  const authorities = userInfo?.authorities
  if (authorities && Array.isArray(authorities)) {
    // 查找ROLE_开头的权限
    const roleAuthority = authorities.find(auth => 
      auth.authority && auth.authority.startsWith('ROLE_')
    )
    
    if (roleAuthority) {
      // 移除ROLE_前缀并转换为中文
      const roleName = roleAuthority.authority.replace('ROLE_', '')
      const roleMap: { [key: string]: string } = {
        'ADMIN': '管理员',
        'USER': '普通用户',
        'MANAGER': '经理',
        'OPERATOR': '操作员'
      }
      return roleMap[roleName] || roleName
    }
  }
  
  return '普通用户'
}

// 获取用户信息
const fetchUserInfo = async () => {
  try {
    loading.value = true
    const response = await request.get('/api/auth/userinfo')
    userInfo.value = response
    console.log('用户信息:', response)
  } catch (error) {
    console.error('获取用户信息失败:', error)
    // 如果获取失败,尝试从本地存储获取
    const storedUserInfo = localStorage.getItem('userInfo')
    if (storedUserInfo) {
      userInfo.value = JSON.parse(storedUserInfo)
    }
  } finally {
    loading.value = false
  }
}

onMounted(() => {
  // 获取当前时间
  currentTime.value = new Date().toLocaleString()
  
  // 检查是否已登录
  const token = localStorage.getItem('token')
  if (!token) {
    router.push('/')
    return
  }
  
  // 获取用户信息
  fetchUserInfo()
})

const logout = () => {
  // 清除本地存储
  localStorage.removeItem('token')
  localStorage.removeItem('userInfo')
  
  // 跳转到登录页
  router.push('/')
}
</script>

<style scoped>
.dashboard-container {
  padding: 20px;
  min-height: 100vh;
}

.dashboard-header {
  margin-bottom: 30px;
}

.dashboard-header h2 {
  font-size: 20px;
  color: #333;
            margin: 0 0 8px 0;
          }
          
.dashboard-header p {
  color: #666;
            margin: 0;
}

.dashboard-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
  margin-bottom: 30px;
}
    
    .stat-card {
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        display: flex;
        align-items: center;
  gap: 15px;
  transition: transform 0.3s ease;
}

.stat-card:hover {
  transform: translateY(-2px);
}

.stat-icon {
  font-size: 20px;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f8f9fa;
  border-radius: 6px;
}

.stat-content h3 {
  margin: 0 0 5px 0;
  font-size: 12px;
  color: #666;
  font-weight: 500;
}

.stat-number {
  margin: 0;
  font-size: 18px;
  font-weight: bold;
  color: #333;
}

.dashboard-content {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}

.dashboard-card {
  background: white;
  padding: 24px;
        border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.dashboard-card h3 {
  margin: 0 0 16px 0;
  color: #333;
  font-size: 16px;
  font-weight: 600;
}

.info-grid {
  display: grid;
  gap: 12px;
}

      .info-item {
        display: flex;
        justify-content: space-between;
        align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid #f0f0f0;
}
        
.info-item:last-child {
          border-bottom: none;
        }
        
.info-item label {
          font-weight: 500;
  color: #666;
}

.info-item span {
  color: #333;
}

.quick-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.action-btn {
  background: #3498db;
  color: white;
  border: none;
  padding: 8px 12px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
  transition: background-color 0.3s;
}

.action-btn:hover {
  background: #2980b9;
}

@media (max-width: 768px) {
  .dashboard-stats {
    grid-template-columns: 1fr;
  }
  
  .dashboard-content {
    grid-template-columns: 1fr;
    }
    
    .quick-actions {
    grid-template-columns: 1fr;
  }
}
</style>