- 사용자 매뉴얼: league/commonmark 기반 bag/manual(로그인 전용), ManualRenderer + Config\Manual manifest, 콘텐츠 8종, E2E - 번호알기(봉투번호확인): bag/number-lookup, BagNumberLookup, E2E - gov-portal 대시보드 시안(기본/strip)·기본코드관리 화면 - 메뉴 관리: 등록·수정 후 메뉴 화면 유지, 수정 버튼 클릭 시 상단 스크롤 - 수불/분석 리포트(LOT 수불·반품/파기·수급계획·추이) 표시 보강 - .gitignore: docs/ → /docs/ 앵커링(최상위 개발문서만 제외, app/Docs는 추적) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
93 lines
4.7 KiB
PHP
93 lines
4.7 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
/**
|
|
* 사용자 매뉴얼 뷰.
|
|
*
|
|
* @var array<string, array{title:string,file:string}> $pages 목차
|
|
* @var string $current 현재 slug
|
|
* @var string $title 현재 페이지 제목
|
|
* @var string $body commonmark 로 변환된 HTML (신뢰된 콘텐츠)
|
|
*/
|
|
$pages = $pages ?? [];
|
|
$current = (string) ($current ?? '');
|
|
$title = (string) ($title ?? '사용자 매뉴얼');
|
|
$body = (string) ($body ?? '');
|
|
|
|
$slugs = array_keys($pages);
|
|
$pos = array_search($current, $slugs, true);
|
|
$prevSlug = ($pos !== false && $pos > 0) ? $slugs[$pos - 1] : null;
|
|
$nextSlug = ($pos !== false && $pos < count($slugs) - 1) ? $slugs[$pos + 1] : null;
|
|
?>
|
|
<style>
|
|
/* 매뉴얼 본문 스코프 스타일 (사이트 레이아웃 Tailwind 에 typography 플러그인 없음) */
|
|
.manual-prose { color: #1f2937; font-size: 0.95rem; line-height: 1.75; max-width: 52rem; }
|
|
.manual-prose h1 { font-size: 1.6rem; font-weight: 800; margin: 0 0 1rem; color: #111827; }
|
|
.manual-prose h2 { font-size: 1.25rem; font-weight: 700; margin: 1.8rem 0 0.7rem; padding-bottom: 0.35rem; border-bottom: 2px solid #e5e7eb; color: #1d4ed8; scroll-margin-top: 1rem; }
|
|
.manual-prose h3 { font-size: 1.05rem; font-weight: 700; margin: 1.3rem 0 0.5rem; color: #374151; }
|
|
.manual-prose p { margin: 0.6rem 0; }
|
|
.manual-prose ul, .manual-prose ol { margin: 0.6rem 0 0.6rem 1.4rem; }
|
|
.manual-prose ul { list-style: disc; }
|
|
.manual-prose ol { list-style: decimal; }
|
|
.manual-prose li { margin: 0.25rem 0; }
|
|
.manual-prose li > ul, .manual-prose li > ol { margin-top: 0.25rem; }
|
|
.manual-prose a { color: #1c4e80; text-decoration: underline; }
|
|
.manual-prose a:hover { color: #2563eb; }
|
|
.manual-prose strong { font-weight: 700; color: #111827; }
|
|
.manual-prose blockquote { margin: 0.9rem 0; padding: 0.6rem 1rem; border-left: 4px solid #60a5fa; background: #eff6ff; color: #1e3a8a; border-radius: 0 6px 6px 0; }
|
|
.manual-prose code { background: #f3f4f6; color: #b91c1c; padding: 0.1rem 0.35rem; border-radius: 4px; font-size: 0.85em; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
|
|
.manual-prose pre { background: #1e293b; color: #e2e8f0; padding: 0.9rem 1rem; border-radius: 8px; overflow-x: auto; margin: 0.9rem 0; font-size: 0.85rem; line-height: 1.6; }
|
|
.manual-prose pre code { background: transparent; color: inherit; padding: 0; }
|
|
.manual-prose table { border-collapse: collapse; width: 100%; margin: 1rem 0; font-size: 0.875rem; }
|
|
.manual-prose th, .manual-prose td { border: 1px solid #d1d5db; padding: 0.45rem 0.7rem; text-align: left; vertical-align: top; }
|
|
.manual-prose th { background: #e9ecef; font-weight: 700; color: #333; }
|
|
.manual-prose tbody tr:nth-child(even) td { background: #f9fafb; }
|
|
.manual-prose hr { margin: 1.6rem 0; border: 0; border-top: 1px solid #e5e7eb; }
|
|
.manual-toc a.active { background: #1c4e80; color: #fff; font-weight: 700; }
|
|
@media print {
|
|
.manual-toc, .manual-actions, .manual-nav { display: none !important; }
|
|
.manual-layout { display: block !important; }
|
|
.manual-prose { max-width: none; }
|
|
}
|
|
</style>
|
|
|
|
<div class="manual-layout flex gap-6 items-start max-w-6xl mx-auto">
|
|
<!-- 좌측 목차 -->
|
|
<nav class="manual-toc no-print w-56 shrink-0 sticky top-0 self-start">
|
|
<div class="bg-title-bar text-white text-sm font-bold px-3 py-2 rounded-t">사용자 매뉴얼</div>
|
|
<ul class="border border-t-0 border-gray-300 rounded-b divide-y divide-gray-100 bg-white text-sm">
|
|
<?php foreach ($pages as $slug => $p): ?>
|
|
<li>
|
|
<a href="<?= base_url('bag/manual/' . $slug) ?>"
|
|
class="block px-3 py-2 text-gray-700 hover:bg-blue-50 <?= $slug === $current ? 'active' : '' ?>">
|
|
<?= esc($p['title']) ?>
|
|
</a>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</nav>
|
|
|
|
<!-- 본문 -->
|
|
<div class="flex-grow min-w-0">
|
|
<div class="manual-actions no-print flex justify-end mb-3">
|
|
<button type="button" onclick="window.print()"
|
|
class="text-sm border border-gray-300 rounded px-3 py-1.5 text-gray-600 hover:bg-gray-50">
|
|
인쇄
|
|
</button>
|
|
</div>
|
|
|
|
<article class="manual-prose"><?= $body ?></article>
|
|
|
|
<!-- 이전/다음 -->
|
|
<div class="manual-nav no-print flex justify-between mt-8 pt-4 border-t border-gray-200 text-sm">
|
|
<?php if ($prevSlug !== null): ?>
|
|
<a href="<?= base_url('bag/manual/' . $prevSlug) ?>" class="text-blue-700 hover:underline">← <?= esc($pages[$prevSlug]['title']) ?></a>
|
|
<?php else: ?>
|
|
<span></span>
|
|
<?php endif; ?>
|
|
<?php if ($nextSlug !== null): ?>
|
|
<a href="<?= base_url('bag/manual/' . $nextSlug) ?>" class="text-blue-700 hover:underline"><?= esc($pages[$nextSlug]['title']) ?> →</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|