2026-09-22 23:09:37 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
$__isLoggedIn = \App\Auth::check();
|
|
|
|
|
|
$__user = $__isLoggedIn ? \App\Auth::user() : null;
|
|
|
|
|
|
$__isAdmin = $__isLoggedIn && \App\Auth::isAdmin();
|
|
|
|
|
|
$__name = (string)($__user['name'] ?? ($_SESSION['user_name'] ?? ''));
|
2026-09-23 00:01:05 +08:00
|
|
|
|
// 用 media_avatar() 解析后再判断,不能拿原始值判断:
|
|
|
|
|
|
// 外站地址(https://…)会被 media_avatar() 拒掉返回空串,若还按非空处理,
|
|
|
|
|
|
// 就会渲染出 <img src=""> —— 一个破图占位。
|
|
|
|
|
|
$__avatar = media_avatar((string)($__user['avatar'] ?? ''));
|
2026-09-22 23:09:37 +08:00
|
|
|
|
$__initial = $__name !== '' ? mb_substr($__name, 0, 1) : '·';
|
|
|
|
|
|
?>
|
2026-09-22 22:03:08 +08:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
|
<html lang="zh-CN">
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="UTF-8">
|
2026-09-22 23:09:37 +08:00
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
2026-09-22 22:03:08 +08:00
|
|
|
|
<title><?= e($pageTitle ?? '家庭出行记录') ?></title>
|
|
|
|
|
|
<link rel="stylesheet" href="/assets/style.css">
|
|
|
|
|
|
<link rel="stylesheet" href="/assets/vendor/cropper/cropper.min.css">
|
|
|
|
|
|
<script src="/assets/vendor/cropper/cropper.min.js"></script>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
window._AMapSecurityConfig = {
|
|
|
|
|
|
securityJsCode: '<?= e(app_config()['amap']['security_js'] ?? '') ?>',
|
|
|
|
|
|
};
|
|
|
|
|
|
window.__AMAP_LOADED = false;
|
|
|
|
|
|
window.__AMAP_ERROR = null;
|
|
|
|
|
|
</script>
|
|
|
|
|
|
<script src="https://webapi.amap.com/maps?v=2.0&key=<?= e(app_config()['amap']['key'] ?? '') ?>&plugin=AMap.AutoComplete"
|
|
|
|
|
|
onload="window.__AMAP_LOADED = true;"
|
|
|
|
|
|
onerror="window.__AMAP_ERROR = 'script load failed';">
|
|
|
|
|
|
</script>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<?php if ($__isLoggedIn): ?>
|
|
|
|
|
|
<header class="topbar">
|
2026-09-22 23:09:37 +08:00
|
|
|
|
<a href="<?= url('activities/index') ?>" class="brand">
|
|
|
|
|
|
<span class="brand-mark">🧭</span>
|
|
|
|
|
|
<span class="brand-text">家庭出行记录</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="topbar-right">
|
|
|
|
|
|
<a href="<?= url('activities/create') ?>" class="btn-primary btn-sm topbar-new">+ 新建活动</a>
|
|
|
|
|
|
|
|
|
|
|
|
<?php /* 原生 details 做下拉:不依赖 JS,键盘可用,点外部失焦由 JS 兜底 */ ?>
|
|
|
|
|
|
<details class="menu" id="user-menu">
|
|
|
|
|
|
<summary class="menu-trigger" aria-label="打开菜单">
|
|
|
|
|
|
<?php if ($__avatar !== ''): ?>
|
2026-09-23 00:01:05 +08:00
|
|
|
|
<img class="avatar-xs" src="<?= e($__avatar) ?>" alt="">
|
2026-09-22 23:09:37 +08:00
|
|
|
|
<?php else: ?>
|
|
|
|
|
|
<span class="avatar-xs avatar-initial"><?= e($__initial) ?></span>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
<span class="menu-name"><?= e($__name) ?></span>
|
|
|
|
|
|
<span class="menu-caret" aria-hidden="true">▾</span>
|
|
|
|
|
|
</summary>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="menu-panel">
|
|
|
|
|
|
<div class="menu-head">
|
|
|
|
|
|
<div class="menu-head-name"><?= e($__name) ?></div>
|
|
|
|
|
|
<div class="menu-head-role"><?= $__isAdmin ? '管理员' : '家庭成员' ?></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<a class="menu-item" href="<?= url('activities/index') ?>">
|
|
|
|
|
|
<span class="menu-icon">📋</span> 活动列表
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<a class="menu-item" href="<?= url('activities/create') ?>">
|
|
|
|
|
|
<span class="menu-icon">➕</span> 新建活动
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<?php if (\App\Auth::id()): ?>
|
|
|
|
|
|
<a class="menu-item" href="<?= url('users/edit', ['id' => \App\Auth::id()]) ?>">
|
|
|
|
|
|
<span class="menu-icon">🙋</span> 我的资料
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
|
|
<?php if ($__isAdmin): ?>
|
|
|
|
|
|
<div class="menu-sep">管理</div>
|
|
|
|
|
|
<a class="menu-item" href="<?= url('travel_modes/index') ?>">
|
|
|
|
|
|
<span class="menu-icon">🚄</span> 出行方式
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<a class="menu-item" href="<?= url('vehicles/index') ?>">
|
|
|
|
|
|
<span class="menu-icon">🚗</span> 车辆
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<a class="menu-item" href="<?= url('node_types/index') ?>">
|
|
|
|
|
|
<span class="menu-icon">🏷️</span> 节点类型
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<a class="menu-item" href="<?= url('role_tags/index') ?>">
|
|
|
|
|
|
<span class="menu-icon">🎭</span> 角色标签
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<a class="menu-item" href="<?= url('users/index') ?>">
|
|
|
|
|
|
<span class="menu-icon">👥</span> 用户管理
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<a class="menu-item" href="<?= url('settings/index') ?>">
|
|
|
|
|
|
<span class="menu-icon">🗄️</span> 存储设置
|
|
|
|
|
|
</a>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="menu-sep"></div>
|
|
|
|
|
|
<a class="menu-item menu-item-danger" href="<?= url('auth/logout') ?>">
|
|
|
|
|
|
<span class="menu-icon">🚪</span> 退出登录
|
|
|
|
|
|
</a>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</details>
|
|
|
|
|
|
</div>
|
2026-09-22 22:03:08 +08:00
|
|
|
|
</header>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
|
|
<main class="container<?= $__isLoggedIn ? '' : ' container-guest' ?>">
|
|
|
|
|
|
<?php if ($err = flash('error')): ?>
|
|
|
|
|
|
<div class="alert"><?= e($err) ?></div>
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
<?php require $content; ?>
|
|
|
|
|
|
</main>
|
|
|
|
|
|
|
|
|
|
|
|
<?php if ($__isLoggedIn): ?>
|
2026-09-22 23:09:37 +08:00
|
|
|
|
<footer class="footer">家庭出行记录</footer>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
// 原生 details 不会因为点击面板外部而收起,这里补一句(不依赖它也能用)
|
|
|
|
|
|
document.addEventListener('click', function (ev) {
|
|
|
|
|
|
var menu = document.getElementById('user-menu');
|
|
|
|
|
|
if (menu && menu.open && !menu.contains(ev.target)) {
|
|
|
|
|
|
menu.open = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
// Esc 收起
|
|
|
|
|
|
document.addEventListener('keydown', function (ev) {
|
|
|
|
|
|
var menu = document.getElementById('user-menu');
|
|
|
|
|
|
if (ev.key === 'Escape' && menu && menu.open) {
|
|
|
|
|
|
menu.open = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
2026-09-22 22:03:08 +08:00
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
</body>
|
2026-09-22 23:09:37 +08:00
|
|
|
|
</html>
|