Files
MovieLog_Server/nav.php
T
laoyang 3a3c5890cc 安装向导 + PHP 8.5 兼容修复
新增 install.php:全新部署时自动接管,用户只需上传文件、打开站点即进入
安装向导。安装页自己做三件事:
  - 建 db/ 与 uploads/{posters,tickets,photos,avatars}/,权限调到 775
  - 逐目录真写临时文件实测可写,不靠 is_writable 猜
  - 建库、建管理员、写 db/.installed 锁、自删本文件

配套改动:
  - config.php 把安装检查前置于建库之前,未安装一律 302 到 install.php。
    原实现无条件调用 initDB(),导致「打开首页」就等于建库并种下 admin/123456。
  - lib/db.php 的 initDB(\$seedDefaultAdmin = true);安装向导传 false,
    管理员由用户自己设,绝不种弱口令。新增 isInstalled()。
  - login.php / nav.php 接上 siteName(),站点名称不再只存不用。
  - lib/settings.php 新增 siteName(),缺省回退「电影日志」。

PHP 8.5 兼容:
  - 删掉 fetch_movie.php 与 lib/storage/http.php 的 curl_close()。
    8.5 起该函数 deprecated,调用会往输出插一行警告,把 JSON 响应污染成
    「警告 + JSON」,前端 JSON.parse 失败 → 电影名联想功能完全失灵。
  - config.php 的 display_errors 由 1 改为 0(生产环境不应向浏览器吐错误),
    错误仍写日志;需要调试时设 MOVIELOG_DEBUG=1 打开。

线上验证(movie.yangyq.net,PHP 8.5.12):
  未安装时 / 、/login.php 均 302 → install.php;
  安装页 200、体检 10/10 通过、自动建好 5 个目录;
  安装后 install.php 404、管理员登录成功、首页 200 无报错;
  联想接口带会话请求「流浪地球/星际穿越/霸王别姬」均返回纯 JSON(首字符 {)。
2026-10-31 21:35:41 +08:00

90 lines
4.3 KiB
PHP
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.
<?php
// ============================================
// 文件: nav.php (导航栏组件,显示用户头像)
// ============================================
if (!isset($admin)) {
if (isset($_SESSION['admin_id'])) {
require_once 'config.php';
$admin = getCurrentAdmin();
} else {
$admin = ['username' => '未登录'];
}
}
$current_page = basename($_SERVER['PHP_SELF']);
?>
<nav class="navbar">
<div class="nav-container">
<!-- 左上角系统名做成一个「回到首页」的链接:
右侧折叠菜单里的「首页」要点两下(先展开再点),这里一下就到。 -->
<a href="index.php" class="nav-brand" title="回到首页" aria-label="回到首页">
<span class="brand-icon">🎬</span>
<span class="brand-name"><?= h(siteName()) ?></span>
</a>
<div class="nav-actions">
<span class="nav-user">
<img src="<?= getAvatarUrl($admin['avatar'] ?? null, $admin['username'] ?? '') ?>" style="width:28px;height:28px;border-radius:50%;object-fit:cover;vertical-align:middle;margin-right:4px;">
<?= h($admin['username'] ?? '管理员') ?>
</span>
<a href="add.php" class="btn btn-primary btn-sm">➕ 添加电影</a>
<div class="nav-dropdown">
<button class="dropbtn" onclick="toggleDropdown(event)">☰ 菜单 <span class="arrow">▼</span></button>
<div class="dropdown-content" id="dropdownMenu">
<a href="index.php" <?= $current_page == 'index.php' ? 'class="active"' : '' ?>>
<span class="icon">🏠</span> 首页
</a>
<a href="search.php" <?= $current_page == 'search.php' ? 'class="active"' : '' ?>>
<span class="icon">🔍</span> 高级搜索
</a>
<a href="stats.php" <?= $current_page == 'stats.php' ? 'class="active"' : '' ?>>
<span class="icon">📊</span> 统计
</a>
<a href="annual_report.php" <?= $current_page == 'annual_report.php' ? 'class="active"' : '' ?>>
<span class="icon">📅</span> 年度报告
</a>
<div class="divider"></div>
<a href="cinemas.php" <?= $current_page == 'cinemas.php' ? 'class="active"' : '' ?>>
<span class="icon">🏛️</span> 影院管理
</a>
<a href="persons.php" <?= $current_page == 'persons.php' ? 'class="active"' : '' ?>>
<span class="icon">👥</span> 观影人管理
</a>
<a href="import.php" <?= $current_page == 'import.php' ? 'class="active"' : '' ?>>
<span class="icon">📥</span> CSV导入
</a>
<div class="divider"></div>
<a href="change_password.php" <?= $current_page == 'change_password.php' ? 'class="active"' : '' ?>>
<span class="icon">🔑</span> 修改密码
</a>
<a href="users.php" <?= $current_page == 'users.php' ? 'class="active"' : '' ?>>
<span class="icon">👤</span> 用户管理
</a>
<div class="divider"></div>
<a href="settings.php" <?= $current_page == 'settings.php' ? 'class="active"' : '' ?>>
<span class="icon">⚙️</span> 系统设置
</a>
<div class="divider"></div>
<a href="logout.php" style="color: #e74c3c;">
<span class="icon">🚪</span> 退出登录
</a>
</div>
</div>
</div>
</div>
</nav>
<script>
function toggleDropdown(e) {
e.stopPropagation();
var menu = document.getElementById('dropdownMenu');
menu.classList.toggle('show');
}
document.addEventListener('click', function(e) {
if (!e.target.closest('.nav-dropdown')) {
document.querySelectorAll('.nav-dropdown .dropdown-content').forEach(function(el) {
el.classList.remove('show');
});
}
});
</script>