搜索

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

[板块6:前台展示] - 01 - 实现导航菜单动态生成和页面排序功能

代码示例
#导航菜单动态生成 + 页面排序

## 1.导航菜单动态生成

### (1)目标

实现前台网站根据后台页面管理中的页面列表,动态生成导航菜单。

### a。修改 PageController

**文件路径**:`app/Http/Controllers/Frontend/PageController.php`

**修改 `home` 方法**:

```php
public function home()
{
    $page = Page::where('is_home', true)->first();
    if (!$page) {
        $page = Page::first();
    }
    
    $pages = Page::where('status', true)->get();
    $html = $this->renderService->render($page);
    
    return view('frontend.layouts.app', [
        'title' => $page->title,
        'siteName' => $this->getSiteName(),
        'siteKeywords' => $this->getSiteKeywords(),
        'siteDescription' => $this->getSiteDescription(),
        'pages' => $pages,
        'content' => $html,
    ]);
}
```

**同样修改 `show` 方法**。

### b。修改 PageRenderService

**文件路径**:`app/Services/PageRenderService.php`

**修改 `wrapWithLayout` 方法**:

```php
protected function wrapWithLayout(Page $page, string $content): string
{
    $site = \App\Models\Site::first();
    $pages = \App\Models\Page::where('status', true)->get();
    
    return view('frontend.layouts.app', [
        'title' => $page->title,
        'siteName' => $site->site_name ?? '好站站',
        'siteKeywords' => $site->site_keywords ?? '',
        'siteDescription' => $site->site_description ?? '',
        'pages' => $pages,
        'content' => $content,
    ])->render();
}
```

### c。修改前台布局模板

**文件路径**:`resources/views/frontend/layouts/app.blade.php`

**添加导航栏 HTML**:

```blade
<nav class="navbar">
    <div class="nav-container">
        <a href="/" class="logo">{{ $siteName }}</a>
        <ul class="nav-menu">
            @foreach($pages as $page)
                <li class="nav-item">
                    <a href="/{{ $page->slug }}.html" class="nav-link">{{ $page->title }}</a>
                </li>
            @endforeach
        </ul>
    </div>
</nav>
```

**添加当前页面高亮(JavaScript)**:

```blade
<script>
    const currentPath = window.location.pathname;
    document.querySelectorAll('.nav-link').forEach(link => {
        if (link.getAttribute('href') === currentPath) {
            link.classList.add('active');
        }
    });
</script>
```

**添加导航栏样式**:

```css
.navbar {
    background: #fff;
    border-bottom: 1px solid #e8e8e8;
    position: sticky;
    top: 0;
    z-index: 100;
}
.nav-container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 20px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 64px;
}
.logo {
    font-size: 20px;
    font-weight: bold;
    color: #1890ff;
    text-decoration: none;
}
.nav-menu {
    display: flex;
    list-style: none;
    gap: 30px;
    margin: 0;
    padding: 0;
}
.nav-link {
    color: #333;
    text-decoration: none;
    transition: color 0.3s;
}
.nav-link:hover {
    color: #1890ff;
}
.nav-link.active {
    color: #1890ff;
    font-weight: bold;
}
@media (max-width: 768px) {
    .nav-menu { gap: 15px; }
}
```

### d。遇到的问题

| 问题 | 原因 | 解决 |
|------|------|------|
| `Undefined variable $pages` | `PageRenderService` 没有传递 `$pages` | 在 `wrapWithLayout` 中添加查询 |
| 静态页面高亮不生效 | PHP 方法无法在静态页面执行 | 改用 JavaScript 实现 |

---

## 2.页面排序功能

### (1)目标

为页面管理添加排序功能,后台手动调整顺序,前台按顺序显示导航菜单。

### a。添加数据库字段

**执行命令**:

```bash
php artisan make:migration add_sort_order_to_pages_table
```

**迁移文件**:

```php
public function up()
{
    Schema::table('pages', function (Blueprint $table) {
        $table->integer('sort_order')->default(0)->after('status');
    });
}
```

**执行迁移**:

```bash
php artisan migrate --force
```

### b.修改 Page 模型

**文件路径**:`app/Models/Page.php`

```php
protected $fillable = [
    'site_id',
    'title',
    'slug',
    'is_home',
    'status',
    'sort_order',   // 新增
];
```

### c.修改后台控制器

**文件路径**:`app/Http/Controllers/Admin/PageController.php`

**修改 `update` 方法**:

```php
$validated = $request->validate([
    'title' => 'string|max:255',
    'slug' => 'string|max:255|unique:pages,slug,' . $id,
    'is_home' => 'boolean',
    'status' => 'boolean',
    'sort_order' => 'integer',  // 新增
]);
```

### d。修改前台排序

**文件路径**:`app/Http/Controllers/Frontend/PageController.php`

```php
$pages = Page::where('status', true)->orderBy('sort_order')->get();
```

**文件路径**:`app/Services/PageRenderService.php`

```php
$pages = \App\Models\Page::where('status', true)->orderBy('sort_order')->get();
```

### e。修改前端页面管理

**文件路径**:`resources/js/admin/views/Pages.vue`

**表格添加排序列**:

```vue
<el-table-column prop="sort_order" label="排序" width="120">
    <template #default="{ row }">
        <el-input-number 
            v-model="row.sort_order" 
            size="small" 
            :min="0" 
            :max="999"
            controls-position="right"
            @change="(val) => updateSortOrder(row, val)"
        />
    </template>
</el-table-column>
```

**添加更新方法**:

```typescript
const updateSortOrder = async (row: any, val: number) => {
    try {
        await axios.put(`/api/admin/pages/${row.id}`, { sort_order: val });
        await pageStore.fetchPages();
        ElMessage.success('排序已更新');
    } catch (error) {
        ElMessage.error('更新失败');
        await pageStore.fetchPages();
    }
};
```

**编辑表单添加排序字段**:

```vue
<el-form-item label="排序" prop="sort_order">
    <el-input-number v-model="form.sort_order" :min="0" :max="999" />
</el-form-item>
```

**表单数据增加 `sort_order`**:

```typescript
const form = reactive({
    title: '',
    slug: '',
    is_home: false,
    status: false,
    sort_order: 0,
});
```

### f。修改 Store

**文件路径**:`resources/js/admin/stores/page.ts`

```typescript
pages.value = response.data.sort((a, b) => (a.sort_order || 0) - (b.sort_order || 0));
```

### g。遇到的问题

| 问题 | 原因 | 解决 |
|------|------|------|
| 前端发送 `sort_order`,数据库没更新 | `$fillable` 中没有 `sort_order` | 在模型中添加 |

---

## 3。验证结果

| 验证项 | 结果 |
|--------|------|
| 导航栏显示所有页面 | ✅ |
| 点击菜单跳转 | ✅ |
| 当前页面高亮 | ✅ |
| 后台表格显示排序输入框 | ✅ |
| 修改排序值 | ✅ |
| 前台菜单按新顺序显示 | ✅ |


🧸 adorable code

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

hello@adorablecode.com