style: 표/패널 UI 전면 통일 + 화면설명 드로어·글씨크기·탭 개선
표 디자인 - 모든 표를 가벼운 스타일로 통일(.data-table 경량화: 작은 회색 헤더·연한 구분선·hover) - 표/패널 바깥 테두리 둥글게(rounded-lg) 일괄 적용, 표 래퍼에 패딩 카드(p-4) 통일 - 표 헤더·데이터 정렬을 전 화면 좌측 기준으로 통일 - .data-table th/td text-align:left (전역), 흩어진 center/right 정렬 정리 - 재디자인 Tailwind 표(포장단위·단가·기본코드·담당자·업체·판매대행소·무료대상자·지정판매소)도 셀 좌측화 - 기본정보관리 등 나머지 소메뉴 표를 기본 코드 관리 스타일(가벼운 표·상태 pill)로 재디자인 워크스페이스/공통 - "이 화면 설명" → 새 탭 대신 우측 드로어 팝업(현재 화면과 동시에 보기, Esc·드래그 폭조절) - 상단바 글씨 크기 조절(A−/A+), 작업 내용에 zoom 적용 - 탭 최대치 도달 시 자동 삭제 대신 안내 토스트, "모두 닫기"(업무 현황 탭은 보존) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -76,6 +76,8 @@ if ($effectiveLgIdx) {
|
||||
.ws-drag-overlay.v { cursor: col-resize; }
|
||||
.ws-drag-overlay.h { cursor: row-resize; }
|
||||
.ws-empty { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; color: #94a3b8; font-size: .9rem; gap: .5rem; z-index: 2; background: #f0f4f8; }
|
||||
.ws-toast { position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%) translateY(10px); background: #243a5e; color: #fff; padding: .6rem 1rem; border-radius: 8px; font-size: .8rem; font-weight: 600; box-shadow: 0 8px 22px rgba(0,0,0,.25); opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s; z-index: 10000; max-width: 80vw; text-align: center; }
|
||||
.ws-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
|
||||
</style>
|
||||
</head>
|
||||
<body class="gov-portal-shell">
|
||||
@@ -84,6 +86,11 @@ if ($effectiveLgIdx) {
|
||||
<?= view('home/_dashboard_gov_portal_brand', ['brandHref' => base_url('workspace')]) ?>
|
||||
<?= 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 ($lgLabel !== ''): ?><strong><?= esc($lgLabel) ?></strong> · <?php endif; ?>
|
||||
<?= esc($levelName) ?> · <?= esc($mbName) ?>님
|
||||
@@ -107,8 +114,10 @@ if ($effectiveLgIdx) {
|
||||
<button type="button" data-mode="lr" title="2분할 (좌우)"><i class="fa-solid fa-table-columns"></i></button>
|
||||
<button type="button" data-mode="tb" title="2분할 (상하)"><i class="fa-solid fa-table-columns fa-rotate-90"></i></button>
|
||||
<button type="button" data-mode="quad" title="4분할"><i class="fa-solid fa-table-cells-large"></i></button>
|
||||
<button type="button" id="wsCloseAll" title="모든 탭 닫기" style="margin-left:6px;width:auto;padding:0 8px;gap:4px;"><i class="fa-regular fa-rectangle-xmark"></i><span style="font-size:11px;">모두 닫기</span></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ws-toast" id="wsToast" role="status" aria-live="polite"></div>
|
||||
<div class="ws-panels" id="wsPanels">
|
||||
<div class="ws-empty" id="wsEmpty">
|
||||
<i class="fa-regular fa-window-restore" style="font-size:1.6rem;opacity:.5;"></i>
|
||||
@@ -133,6 +142,15 @@ if ($effectiveLgIdx) {
|
||||
var slots = [null]; // 칸별로 배치된 tab id (길이 = 칸 수)
|
||||
var focused = 0; // 포커스된 칸 인덱스
|
||||
|
||||
var toastEl = document.getElementById('wsToast'), toastTimer = null;
|
||||
function showToast(msg) {
|
||||
if (!toastEl) return;
|
||||
toastEl.textContent = msg;
|
||||
toastEl.classList.add('show');
|
||||
clearTimeout(toastTimer);
|
||||
toastTimer = setTimeout(function () { toastEl.classList.remove('show'); }, 2800);
|
||||
}
|
||||
|
||||
function norm(u) { try { var a = new URL(u, location.origin); return a.pathname + a.search; } catch (e) { return u; } }
|
||||
function withEmbed(u) {
|
||||
try { var a = new URL(u, location.origin); a.searchParams.set('embed', '1'); return a.pathname + a.search; }
|
||||
@@ -342,6 +360,20 @@ if ($effectiveLgIdx) {
|
||||
b.addEventListener('click', function () { setLayout(b.getAttribute('data-mode')); });
|
||||
});
|
||||
|
||||
// 모든 탭 닫기 — 기본 "업무 현황"(대시보드) 탭은 남긴다
|
||||
var DASH_URL = '<?= base_url('/') ?>';
|
||||
function closeAllTabs() {
|
||||
var dashId = norm(DASH_URL);
|
||||
var others = order.filter(function (id) { return id !== dashId; });
|
||||
if (!others.length) return; // 업무 현황만 있으면 닫을 것 없음
|
||||
if (!window.confirm('업무 현황을 제외한 모든 탭(' + others.length + '개)을 닫을까요?')) return;
|
||||
others.forEach(function (id) { closeTab(id); });
|
||||
if (!tabs[dashId]) openTab(DASH_URL, '업무 현황'); else placeInFocused(dashId);
|
||||
showToast('업무 현황만 남기고 모두 닫았습니다.');
|
||||
}
|
||||
var closeAllBtn = document.getElementById('wsCloseAll');
|
||||
if (closeAllBtn) closeAllBtn.addEventListener('click', closeAllTabs);
|
||||
|
||||
function reloadTab(id) {
|
||||
var t = tabs[id];
|
||||
if (!t) return;
|
||||
@@ -362,7 +394,11 @@ if ($effectiveLgIdx) {
|
||||
function openTab(url, title, opts) {
|
||||
var id = norm(url);
|
||||
if (tabs[id]) { if (!(opts && opts.noFocus)) placeInFocused(id); return; }
|
||||
if (order.length >= MAX) { closeTab(order[0]); } // 오래된 탭 정리
|
||||
// 최대치 도달 시: 자동 삭제하지 않고 안내만 (복원 중에는 안내 생략)
|
||||
if (order.length >= MAX) {
|
||||
if (!(opts && opts.noFocus)) showToast('탭은 최대 ' + MAX + '개까지 열 수 있습니다. 사용하지 않는 탭을 닫아 주세요.');
|
||||
return;
|
||||
}
|
||||
var frame = document.createElement('iframe');
|
||||
frame.className = 'ws-frame';
|
||||
frame.src = withEmbed(url);
|
||||
@@ -430,6 +466,22 @@ if ($effectiveLgIdx) {
|
||||
}
|
||||
document.addEventListener('keydown', handleShortcut);
|
||||
|
||||
// 글씨 크기 조절 — 각 탭(iframe) 내용에 zoom 적용. localStorage 공유 + storage 이벤트로 새 탭/실시간 반영.
|
||||
var FONT_KEY = 'jrj_font_scale';
|
||||
function curFontScale() { var s = parseInt(localStorage.getItem(FONT_KEY) || '100', 10); return (s >= 70 && s <= 150) ? s : 100; }
|
||||
function setFontScale(s) {
|
||||
s = Math.min(150, Math.max(70, s));
|
||||
try { localStorage.setItem(FONT_KEY, String(s)); } catch (e) {}
|
||||
var pct = document.getElementById('wsFontPct'); if (pct) pct.textContent = s + '%';
|
||||
Object.keys(tabs).forEach(function (k) { try { tabs[k].frame.contentDocument.documentElement.style.zoom = (s / 100); } catch (e) {} });
|
||||
}
|
||||
(function () {
|
||||
var pct = document.getElementById('wsFontPct'); if (pct) pct.textContent = curFontScale() + '%';
|
||||
var plus = document.getElementById('wsFontPlus'), minus = document.getElementById('wsFontMinus');
|
||||
if (plus) plus.addEventListener('click', function () { setFontScale(curFontScale() + 10); });
|
||||
if (minus) minus.addEventListener('click', function () { setFontScale(curFontScale() - 10); });
|
||||
})();
|
||||
|
||||
// 좌측 사이드바 소메뉴 클릭 → 포커스 칸에 열기
|
||||
document.querySelector('.sidebar').addEventListener('click', function (e) {
|
||||
var a = e.target.closest('a[href]');
|
||||
|
||||
Reference in New Issue
Block a user