- screenHelp 앵커(?hl=)로 '이 화면 설명' 클릭 시 해당 소제목으로 스크롤·강조, 재오픈 시 재강조(postMessage) - 글씨 크기(A−/A+)가 상단 대메뉴·좌측 사이드바까지 확대, 관리자 페이지에도 조절 기능 추가 - 화면 설명 드로어 양방향 리사이즈(좁히기 가능) + 기본 너비 2배 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
191 lines
9.7 KiB
PHP
191 lines
9.7 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
/**
|
||
* 관리자 공통 레이아웃 — gov-portal 디자인 적용판.
|
||
* 헤더 + 관리자 대메뉴(클릭) + 좌측 사이드바(소메뉴) + 본문($content).
|
||
*
|
||
* @var string $title
|
||
* @var string $content
|
||
*/
|
||
helper('admin');
|
||
|
||
$mbLevel = (int) session()->get('mb_level');
|
||
$isSuperAdmin = \Config\Roles::isSuperAdminEquivalent($mbLevel);
|
||
$mbName = (string) (session()->get('mb_name') ?? '담당자');
|
||
$levelName = config(\Config\Roles::class)->getLevelName($mbLevel);
|
||
|
||
$effectiveLgIdx = admin_effective_lg_idx();
|
||
$effectiveLgName = '';
|
||
if ($effectiveLgIdx) {
|
||
$lgRow = model(\App\Models\LocalGovernmentModel::class)->find($effectiveLgIdx);
|
||
$effectiveLgName = $lgRow ? (string) $lgRow->lg_name : '';
|
||
}
|
||
|
||
$adminTree = function_exists('get_admin_nav_tree') ? get_admin_nav_tree() : [];
|
||
$gov = gov_portal_nav_context(false, $adminTree);
|
||
|
||
// 관리자 메뉴가 비어 있으면(지자체 미선택 등) 핵심 항목 폴백 노출
|
||
$navItems = $gov['navItems'];
|
||
if ($navItems === []) {
|
||
$mk = static fn (string $name, string $path): array => [
|
||
'idx' => 0, 'name' => $name, 'href' => $path, 'url' => base_url($path),
|
||
];
|
||
$navItems = [
|
||
['idx' => 0, 'name' => '대시보드', 'href' => 'admin', 'url' => base_url('admin'), 'children' => [], 'hasChildren' => false],
|
||
['idx' => 0, 'name' => '회원·접근', 'href' => '', 'url' => '', 'hasChildren' => true, 'children' => [
|
||
$mk('회원 관리', 'admin/users'), $mk('로그인 이력', 'admin/access/login-history'), $mk('승인 대기', 'admin/access/approvals'),
|
||
]],
|
||
['idx' => 0, 'name' => '시스템', 'href' => '', 'url' => '', 'hasChildren' => true, 'children' => [
|
||
$mk('역할', 'admin/roles'), $mk('메뉴', 'admin/menus'),
|
||
]],
|
||
];
|
||
if ($isSuperAdmin) {
|
||
$navItems[] = ['idx' => 0, 'name' => '지자체', 'href' => '', 'url' => '', 'hasChildren' => true, 'children' => [
|
||
$mk('지자체 전환', 'admin/select-local-government'), $mk('지자체 관리', 'admin/local-governments'),
|
||
]];
|
||
}
|
||
}
|
||
$navJson = json_encode($navItems, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS);
|
||
|
||
$navPartial = [
|
||
'govNavItems' => $navItems,
|
||
'govNavJson' => $navJson,
|
||
'govActiveParentIdx' => $gov['activeParentIdx'],
|
||
'govCurrentPath' => $gov['currentPath'],
|
||
'govDashboardAliases' => $gov['dashboardAliases'],
|
||
'govActiveChildHref' => $gov['currentPath'],
|
||
];
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="ko" class="gov-portal-html">
|
||
<head>
|
||
<meta charset="utf-8"/>
|
||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||
<title><?= esc($title ?? '관리자') ?> - GBLS</title>
|
||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"/>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css"/>
|
||
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||
<script>
|
||
tailwind.config = {
|
||
theme: {
|
||
extend: {
|
||
fontFamily: { sans: ['Pretendard', '"Malgun Gothic"', '"Noto Sans KR"', 'sans-serif'] },
|
||
colors: {
|
||
'system-header': '#ffffff', 'title-bar': '#1a2b4b', 'control-panel': '#f8f9fa',
|
||
'btn-search': '#243a5e', 'btn-excel-border': '#28a745', 'btn-excel-text': '#28a745',
|
||
'btn-print-border': '#ced4da', 'btn-exit': '#d9534f',
|
||
},
|
||
fontSize: { 'xxs': '0.65rem' }
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
<style>
|
||
<?php include __DIR__ . '/../home/_dashboard_gov_portal_brand_css.php'; ?>
|
||
<?php include __DIR__ . '/../home/_dashboard_gov_portal_topnav_css.php'; ?>
|
||
<?php include __DIR__ . '/../home/_dashboard_gov_portal_chrome_css.php'; ?>
|
||
.data-table { width: 100%; border-collapse: collapse; font-family: 'Pretendard', 'Malgun Gothic', 'Noto Sans KR', sans-serif; }
|
||
.data-table { font-size: 13px; }
|
||
.data-table th, .data-table td { text-align: left; padding: 0.55rem 0.5rem; white-space: nowrap; border: 0; border-bottom: 1px solid #e5e7eb; }
|
||
.data-table thead th { font-size: 0.6875rem; font-weight: 600; color: #6b7280; background: transparent; vertical-align: middle; }
|
||
.data-table tbody td { color: #374151; }
|
||
.data-table tbody tr:last-child td { border-bottom: 0; }
|
||
.data-table tbody tr:hover td { background-color: #f9fafb; }
|
||
@media print {
|
||
.portal-header, .sidebar, .portal-footer, .no-print, nav.portal-top-nav { display: none !important; }
|
||
body.gov-portal-shell { background: #fff; display: block; }
|
||
.gov-portal-shell .main.work-main { overflow: visible !important; padding: 0 !important; }
|
||
.print-header { display: block !important; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body class="gov-portal-shell select-none">
|
||
<header class="portal-header">
|
||
<div class="portal-header-inner">
|
||
<?= view('home/_dashboard_gov_portal_brand', ['brandHref' => base_url('/')]) ?>
|
||
<?= view('home/_dashboard_gov_portal_topnav_click', $navPartial) ?>
|
||
<div class="portal-header-utils" style="display:flex;align-items:center;gap:.5rem;">
|
||
<div class="ws-fontctl" title="글씨 크기 조절" style="display:inline-flex;align-items:center;gap:2px;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.25);border-radius:6px;padding:1px;">
|
||
<button type="button" id="wsFontMinus" title="글씨 작게" style="width:24px;height:22px;border:0;background:transparent;color:#fff;cursor:pointer;font-size:11px;line-height:1;border-radius:5px;">A−</button>
|
||
<span id="wsFontPct" style="min-width:34px;text-align:center;color:#fff;font-size:.68rem;font-weight:600;">100%</span>
|
||
<button type="button" id="wsFontPlus" title="글씨 크게" style="width:24px;height:22px;border:0;background:transparent;color:#fff;cursor:pointer;font-size:14px;line-height:1;border-radius:5px;">A+</button>
|
||
</div>
|
||
<span class="user-line">
|
||
<?php if ($effectiveLgName !== ''): ?><strong><?= esc($effectiveLgName) ?></strong> · <?php endif; ?>
|
||
<?= esc($levelName) ?> · <?= esc($mbName) ?>님
|
||
</span>
|
||
<a href="<?= base_url('/') ?>" title="사이트로"
|
||
style="display:inline-flex;align-items:center;gap:.3rem;padding:.25rem .6rem;border-radius:6px;background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.3);color:#fff;text-decoration:none;font-size:.75rem;font-weight:600;white-space:nowrap;">
|
||
<i class="fa-solid fa-house"></i> 사이트
|
||
</a>
|
||
<a href="<?= base_url('logout') ?>" title="로그아웃"
|
||
style="display:inline-flex;align-items:center;gap:.3rem;padding:.25rem .6rem;border-radius:6px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.22);color:#fff;text-decoration:none;font-size:.75rem;font-weight:600;white-space:nowrap;">
|
||
<i class="fa-solid fa-right-from-bracket"></i> 로그아웃
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="layout">
|
||
<?= view('home/_dashboard_gov_portal_sidebar', $navPartial) ?>
|
||
|
||
<main class="main work-main main-content-area">
|
||
<?php if (! empty($title)): ?>
|
||
<h1 class="work-titlebar"><i class="fa-solid fa-gear tb-ico"></i><?= esc($title) ?></h1>
|
||
<?php endif; ?>
|
||
<?php if (session()->getFlashdata('success')): ?>
|
||
<div class="work-flash ok"><?= esc(session()->getFlashdata('success')) ?></div>
|
||
<?php endif; ?>
|
||
<?php if (session()->getFlashdata('error')): ?>
|
||
<div class="work-flash err"><?= esc(session()->getFlashdata('error')) ?></div>
|
||
<?php endif; ?>
|
||
<?php if (session()->getFlashdata('errors')): ?>
|
||
<div class="work-flash err"><?php foreach (session()->getFlashdata('errors') as $err): ?><div><?= esc($err) ?></div><?php endforeach; ?></div>
|
||
<?php endif; ?>
|
||
<div class="work-surface">
|
||
<?= $content ?>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
|
||
<footer class="portal-footer">
|
||
<span>GBLS 관리자</span>
|
||
<span><?= date('Y.m.d (D) H:i') ?></span>
|
||
</footer>
|
||
|
||
<?= view('home/_dashboard_gov_portal_nav_script_base', $navPartial) ?>
|
||
<script>
|
||
(function () {
|
||
// bfcache 복원 시 열린 채 남은 모달/팝업으로 회색 레이어가 클릭을 막는 문제 방지
|
||
function closeStuckOverlays() {
|
||
document.querySelectorAll('.fixed.inset-0[id$="-modal"], .fixed.inset-0[id$="-popup"]').forEach(function (el) {
|
||
el.classList.add('hidden'); el.setAttribute('aria-hidden', 'true');
|
||
});
|
||
document.body.style.overflow = '';
|
||
}
|
||
window.addEventListener('pageshow', function (e) { if (e.persisted) closeStuckOverlays(); });
|
||
window.addEventListener('pagehide', closeStuckOverlays);
|
||
})();
|
||
|
||
// 글씨 크기 조절(A−/A+) — 본문 + 상단 대메뉴 + 좌측 사이드바에 zoom 적용. 사이트/워크스페이스와 배율 공유.
|
||
(function () {
|
||
var FONT_KEY = 'jrj_font_scale';
|
||
var scaleSelectors = ['.portal-header', '.sidebar', '.work-main'];
|
||
function curScale() { var s = parseInt(localStorage.getItem(FONT_KEY) || '100', 10); return (s >= 70 && s <= 150) ? s : 100; }
|
||
function applyScale(s) {
|
||
s = Math.min(150, Math.max(70, s));
|
||
try { localStorage.setItem(FONT_KEY, String(s)); } catch (e) {}
|
||
var z = s / 100;
|
||
scaleSelectors.forEach(function (sel) { var el = document.querySelector(sel); if (el) el.style.zoom = z; });
|
||
var pct = document.getElementById('wsFontPct'); if (pct) pct.textContent = s + '%';
|
||
}
|
||
applyScale(curScale());
|
||
var plus = document.getElementById('wsFontPlus'), minus = document.getElementById('wsFontMinus');
|
||
if (plus) plus.addEventListener('click', function () { applyScale(curScale() + 10); });
|
||
if (minus) minus.addEventListener('click', function () { applyScale(curScale() - 10); });
|
||
window.addEventListener('storage', function (e) { if (e.key === FONT_KEY) applyScale(curScale()); });
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|