stdproject/frontend/src/data-public/Dashboard.vue
2025-06-19 11:21:06 +08:00

364 lines
7.9 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>
<div class="dashboard-container">
<div class="dashboard-header">
<h1>仪表板</h1>
<p>欢迎回来{{ userStore.nickname || userStore.username }}</p>
</div>
<!-- 统计卡片 -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon user-icon">
<el-icon><User /></el-icon>
</div>
<div class="stat-content">
<h3>{{ stats.userCount }}</h3>
<p>用户总数</p>
</div>
</div>
<div class="stat-card">
<div class="stat-icon role-icon">
<el-icon><UserFilled /></el-icon>
</div>
<div class="stat-content">
<h3>{{ stats.roleCount }}</h3>
<p>角色总数</p>
</div>
</div>
<div class="stat-card">
<div class="stat-icon org-icon">
<el-icon><OfficeBuilding /></el-icon>
</div>
<div class="stat-content">
<h3>{{ stats.orgCount }}</h3>
<p>组织总数</p>
</div>
</div>
<div class="stat-card">
<div class="stat-icon dict-icon">
<el-icon><Document /></el-icon>
</div>
<div class="stat-content">
<h3>{{ stats.dictCount }}</h3>
<p>字典总数</p>
</div>
</div>
</div>
<!-- 快捷操作 -->
<div class="quick-actions">
<h2>快捷操作</h2>
<div class="actions-grid">
<el-card class="action-card" @click="routerclick('/Permission')">
<div class="action-content">
<el-icon class="action-icon"><User /></el-icon>
<span>用户管理</span>
</div>
</el-card>
<el-card class="action-card" @click="routerclick('/UserLogin')">
<div class="action-content">
<el-icon class="action-icon"><UserFilled /></el-icon>
<span>角色管理</span>
</div>
</el-card>
<el-card class="action-card" >
<div class="action-content">
<el-icon class="action-icon"><OfficeBuilding /></el-icon>
<span>组织管理</span>
</div>
</el-card>
<el-card class="action-card" @click="$router.push('/dictionaries')">
<div class="action-content">
<el-icon class="action-icon"><Document /></el-icon>
<span>字典管理</span>
</div>
</el-card>
</div>
</div>
<!-- 快捷操作 -->
<div class="quick-actions">
<h2>快捷操作</h2>
<div class="actions-grid">
<el-card class="action-card" @click="$router.push('/FormCreate?appId=1927666485224894465')">
<div class="action-content">
<el-icon class="action-icon"><User /></el-icon>
<span>FormCreat</span>
</div>
</el-card>
<el-card class="action-card" @click="$router.push('/visualization?id=1927640677370306561&busiFlag=dataV')">
<div class="action-content">
<el-icon class="action-icon"><User /></el-icon>
<span>GIS大屏</span>
</div>
</el-card>
<el-card class="action-card" @click="$router.push('/visualization?id=1927658989605187585&busiFlag=dashboard')">
<div class="action-content">
<el-icon class="action-icon"><User /></el-icon>
<span>数据看板</span>
</div>
</el-card>
</div>
</div>
<!-- 最近活动 -->
<div class="recent-activities">
<h2>最近活动</h2>
<el-card>
<el-timeline>
<el-timeline-item
v-for="activity in activities"
:key="activity.id"
:timestamp="activity.time"
:type="activity.type"
>
{{ activity.content }}
</el-timeline-item>
</el-timeline>
</el-card>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { useUserStore } from '@/store/user'
import { User, UserFilled, OfficeBuilding, Document } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'
const userStore = useUserStore()
const router = useRouter()
// 统计数据
const stats = reactive({
userCount: 0,
roleCount: 0,
orgCount: 0,
dictCount: 0
})
const activities = ref([
{
id: 1,
content: '系统启动成功',
time: '2024-01-01 09:00:00',
type: 'success'
},
{
id: 2,
content: '用户登录系统',
time: '2024-01-01 09:30:00',
type: 'primary'
},
{
id: 3,
content: '创建新用户',
time: '2024-01-01 10:00:00',
type: 'info'
},
{
id: 4,
content: '更新角色权限',
time: '2024-01-01 10:30:00',
type: 'warning'
}
])
// 加载统计数据
const loadStats = async () => {
try {
// 这里应该调用实际的API获取统计数据
// 暂时使用模拟数据
stats.userCount = 156
stats.roleCount = 8
stats.orgCount = 23
stats.dictCount = 45
} catch (error) {
console.error('加载统计数据失败:', error)
}
}
// 组件挂载时加载数据
onMounted(() => {
loadStats()
})
function routerclick(path) {
if(path == '/Permission'){
router.push({
path: path,
query: {
id: '1927554158852841473'
}
})
}else if(path == '/UserLogin'){
const route = router.resolve({
path: path,
query: { id: '1927554158852841473' ,name:'测试项目'}
});
window.open(route.href, '_blank');
}
}
</script>
<style lang="scss" scoped>
.dashboard-container {
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
.dashboard-header {
margin-bottom: 30px;
h1 {
color: #333;
margin-bottom: 8px;
font-size: 28px;
font-weight: 600;
}
p {
color: #666;
font-size: 16px;
}
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 40px;
}
.stat-card {
background: white;
border-radius: 10px;
padding: 24px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
gap: 16px;
transition: transform 0.2s, box-shadow 0.2s;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
}
.stat-icon {
width: 60px;
height: 60px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: white;
&.user-icon {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
&.role-icon {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
&.org-icon {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
&.dict-icon {
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
}
}
.stat-content {
h3 {
font-size: 32px;
font-weight: 700;
color: #333;
margin-bottom: 4px;
}
p {
color: #666;
font-size: 14px;
}
}
.quick-actions {
margin-bottom: 40px;
h2 {
color: #333;
margin-bottom: 20px;
font-size: 20px;
font-weight: 600;
}
}
.actions-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
.action-card {
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
}
.action-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
padding: 20px;
.action-icon {
font-size: 32px;
color: #409eff;
}
span {
font-size: 16px;
font-weight: 500;
color: #333;
}
}
.recent-activities {
h2 {
color: #333;
margin-bottom: 20px;
font-size: 20px;
font-weight: 600;
}
.el-card {
padding: 20px;
}
}
@media (max-width: 768px) {
.dashboard-container {
padding: 16px;
}
.stats-grid {
grid-template-columns: 1fr;
}
.actions-grid {
grid-template-columns: repeat(2, 1fr);
}
}
</style>