搜索

📄 文章 📚 合集
热门搜索
🐘 PHP ⚡ Laravel 🎨 Vue.js ⚛️ React 📦 Yii 📘 JavaScript 🗄️ MySQL 🐳 Docker
返回合集

[板块3:Vue 3 + Element Plus 后台(含认证+核心功能)] - 13- 搭建后台布局和仪表盘

代码示例
# 后台布局与仪表盘

## 1. 修改 MainLayout.vue

### 1.1 文件路径

`resources\js\admin\layouts\MainLayout.vue`

### 1.2 操作说明

该文件在阶段3已创建为占位文件,现在将占位内容替换为完整的后台布局代码。

### 1.3 完整代码

```vue
<template>
    <el-container>
        <!-- 侧边栏 -->
        <el-aside :width="isCollapse ? '64px' : '220px'">
            <div>
                <span v-if="!isCollapse">好站站</span>
                <span v-else>好</span>
            </div>
            <el-menu
                :collapse="isCollapse"
                router
                :default-active="$route.path"
                background-color="#001529"
                text-color="#bfbfbf"
                active-text-color="#fff"
            >
                <el-menu-item index="/admin">
                    <el-icon><Odometer /></el-icon>
                    <span>仪表盘</span>
                </el-menu-item>
                <el-menu-item index="/admin/pages">
                    <el-icon><Document /></el-icon>
                    <span>页面管理</span>
                </el-menu-item>
                <el-menu-item index="/admin/site">
                    <el-icon><Setting /></el-icon>
                    <span>站点配置</span>
                </el-menu-item>
            </el-menu>
        </el-aside>

        <el-container>
            <!-- 顶部栏 -->
            <el-header>
                <div>
                    <el-icon @click="toggleCollapse">
                        <Fold v-if="!isCollapse" />
                        <Expand v-else />
                    </el-icon>
                </div>
                <div>
                    <el-dropdown @command="handleCommand">
                        <span>
                            {{ authStore.user?.name }}
                            <el-icon><CaretBottom /></el-icon>
                        </span>
                        <template #dropdown>
                            <el-dropdown-menu>
                                <el-dropdown-item command="logout">退出登录</el-dropdown-item>
                            </el-dropdown-menu>
                        </template>
                    </el-dropdown>
                </div>
            </el-header>

            <!-- 主内容区 -->
            <el-main>
                <router-view />
            </el-main>
        </el-container>
    </el-container>
</template>

<script setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { ElMessage } from 'element-plus';
import { useAuthStore } from '../stores/auth';
import {
    Odometer,
    Document,
    Setting,
    Fold,
    Expand,
    CaretBottom,
} from '@element-plus/icons-vue';

const router = useRouter();
const authStore = useAuthStore();
const isCollapse = ref(false);

const toggleCollapse = () => {
    isCollapse.value = !isCollapse.value;
};

const handleCommand = async (command: string) => {
    if (command === 'logout') {
        await authStore.logout();
        ElMessage.success('已退出登录');
        router.push('/admin/login');
    }
};
</script>

<style scoped>
.layout-container {
    height: 100vh;
}

.aside {
    background-color: #001529;
    transition: width 0.3s;
}

.logo {
    height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 20px;
    font-weight: bold;
    background-color: #002140;
}

.header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: #fff;
    border-bottom: 1px solid #e8e8e8;
    padding: 0 20px;
}

.collapse-btn {
    font-size: 20px;
    cursor: pointer;
}

.user-info {
    display: flex;
    align-items: center;
    gap: 5px;
    cursor: pointer;
}

.main {
    background-color: #f0f2f5;
    padding: 20px;
}
</style>
```

### 1.4 代码说明

| 代码 | 作用 |
|------|------|
| `el-container`、`el-aside`、`el-header`、`el-main` | Element Plus 布局组件,构建经典后台布局 |
| `:collapse="isCollapse"` | 控制侧边栏折叠状态 |
| `router` 属性 | 启用路由模式,点击菜单自动跳转 |
| `:default-active="$route.path"` | 根据当前路由高亮对应菜单 |
| `el-dropdown` | 用户下拉菜单,放置退出登录操作 |
| `authStore.user?.name` | 显示当前登录用户名(可选链防止空值报错) |
| `toggleCollapse` | 切换侧边栏折叠/展开 |
| `handleCommand` | 处理下拉菜单命令,执行退出登录 |

### 1.5 布局结构说明

```
┌─────────────────────────────────────────────────────────┐
│  ┌──────┐  ┌─────────────────────────────────────────┐  │
│  │ 好站 │  │  折叠按钮                    用户名 ▼   │  │
│  │ 站   │  ├─────────────────────────────────────────┤  │
│  ├──────┤  │                                         │  │
│  │ 仪表 │  │                                         │  │
│  │ 盘   │  │              主内容区                    │  │
│  ├──────┤  │          (router-view)                │  │
│  │ 页面 │  │                                         │  │
│  │ 管理 │  │                                         │  │
│  ├──────┤  │                                         │  │
│  │ 站点 │  │                                         │  │
│  │ 配置 │  │                                         │  │
│  └──────┘  └─────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
```

---

## 2. 修改 Dashboard.vue

### 2.1 文件路径

`resources\js\admin\views\Dashboard.vue`

### 2.2 操作说明

该文件在阶段3已创建为占位文件,现在将占位内容替换为仪表盘代码。

### 2.3 完整代码

```vue
<template>
    <div>
        <el-row :gutter="20">
            <el-col :span="6">
                <el-card>
                    <div>{{ pageCount }}</div>
                    <div>页面总数</div>
                </el-card>
            </el-col>
            <el-col :span="6">
                <el-card>
                    <div>0</div>
                    <div>组件总数</div>
                </el-card>
            </el-col>
            <el-col :span="6">
                <el-card>
                    <div>0</div>
                    <div>今日访问</div>
                </el-card>
            </el-col>
            <el-col :span="6">
                <el-card>
                    <div>v1.0</div>
                    <div>系统版本</div>
                </el-card>
            </el-col>
        </el-row>

        <el-card style="margin-top: 20px">
            <h3>欢迎使用好站站</h3>
            <p>点击左侧菜单开始建站,或查看使用文档了解更多功能。</p>
        </el-card>
    </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';

const pageCount = ref(0);

onMounted(async () => {
    try {
        const response = await axios.get('/api/admin/pages');
        pageCount.value = response.data.length || 0;
    } catch (error) {
        console.error('获取页面统计失败', error);
    }
});
</script>

<style scoped>
.stat-card {
    text-align: center;
}

.stat-value {
    font-size: 32px;
    font-weight: bold;
    color: #1890ff;
}

.stat-label {
    color: #666;
    margin-top: 10px;
}

.welcome-card h3 {
    margin-bottom: 10px;
}

.welcome-card p {
    color: #666;
}
</style>
```

### 2.4 代码说明

| 代码 | 作用 |
|------|------|
| `el-row` + `el-col` | Element Plus 栅格布局,实现响应式列布局 |
| `:gutter="20"` | 列间距 20px |
| `:span="6"` | 每列占 6/24,一行显示 4 列 |
| `el-card` | 卡片容器,展示统计数据和欢迎信息 |
| `pageCount` | 响应式数据,存储页面总数 |
| `onMounted` | 组件挂载后调用 API 获取数据 |
| `stat-value` | 蓝色大字体,突出统计数据 |

---

## 3. 编译验证

### 3.1 执行命令

```bash
npm run build
```

### 3.2 预期结果

编译成功,无报错。

---

## 4. 访问测试

### 4.1 登录后台

浏览器打开:`http://engine-api.test/admin/login`

输入账号密码登录。

### 4.2 验证后台布局

| 验证项 | 预期结果 |
|--------|---------|
| 侧边栏 | 显示「好站站」Logo 和三个菜单 |
| 侧边栏折叠 | 点击折叠按钮,侧边栏收缩 |
| 顶部栏 | 显示当前登录用户名 |
| 退出登录 | 点击退出,跳转到登录页 |
| 仪表盘 | 显示四个统计卡片和欢迎卡片 |

---

## 5. 验证结果

| 验证项 | 预期结果 | 实际结果 |
|--------|---------|---------|
| 编译 | 无报错 | ✅ 通过 |
| 侧边栏显示 | 显示菜单 | ✅ 通过 |
| 侧边栏折叠 | 正常折叠/展开 | ✅ 通过 |
| 顶部栏用户名 | 显示当前用户 | ✅ 通过 |
| 退出登录 | 跳转登录页 | ✅ 通过 |
| 仪表盘统计卡片 | 显示页面总数 | ✅ 通过 |
| 仪表盘欢迎卡片 | 显示欢迎信息 | ✅ 通过 |

---

🧸 adorable code

专注 PHP、JavaScript、Laravel、Vue.js、React、Yii 全栈开发。记录技术探索过程中的灵感与经验,分享工程实践洞见。

hello@adorablecode.com