feat: 대시보드 바로가기 새 탭 열기 + 탭 새로고침 시각 피드백

- 업무 현황의 "자주 가는 화면"·"최근 방문 메뉴"·메뉴검색 결과 클릭 시
  워크스페이스 새 탭으로 열기(부모 wsOpenTab 호출, 밖이면 화면 이동 폴백)
- 탭 새로고침(↻): 아이콘 회전 + 화면 잠깐 페이드 후 복구로 새로고침 확인 가능하게

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
taekyoungc
2026-06-13 23:53:22 +09:00
parent fd3da428ab
commit 287691328e
2 changed files with 36 additions and 9 deletions

View File

@@ -51,6 +51,8 @@ if ($effectiveLgIdx) {
.ws-tab.focused-tab { box-shadow: 0 -2px 0 #243a5e inset; }
.ws-tab .t-refresh, .ws-tab .t-close { width: 16px; height: 16px; line-height: 14px; text-align: center; border-radius: 50%; color: #999; font-size: 12px; }
.ws-tab .t-refresh:hover { background: #dbeafe; color: #1d4ed8; }
.ws-tab .t-refresh.spin { animation: ws-spin .6s linear; }
@keyframes ws-spin { to { transform: rotate(360deg); } }
.ws-tab .t-close:hover { background: #e2e8f0; color: #333; }
/* 분할 레이아웃 컨트롤 */
.ws-layout { display: flex; align-items: center; gap: 3px; padding: 4px 8px; flex-shrink: 0; border-left: 1px solid var(--border); }
@@ -58,7 +60,7 @@ if ($effectiveLgIdx) {
.ws-layout button:hover { background: #e2e8f0; color: #334155; }
.ws-layout button.active { background: #243a5e; color: #fff; border-color: #243a5e; }
.ws-panels { flex: 1; position: relative; min-height: 0; background: #cbd5e1; }
.ws-frame { position: absolute; left: 0; top: 0; width: 100%; height: 100%; border: 0; display: none; background: #fff; box-sizing: border-box; }
.ws-frame { position: absolute; left: 0; top: 0; width: 100%; height: 100%; border: 0; display: none; background: #fff; box-sizing: border-box; transition: opacity .15s; }
/* 분할 칸 헤더 */
.ws-slot-head { position: absolute; display: none; align-items: center; gap: .3rem; height: 28px; padding: 0 .3rem 0 .6rem; background: #eef2f7; border-bottom: 1px solid var(--border); font-size: .72rem; color: #475569; box-sizing: border-box; cursor: pointer; z-index: 3; }
.ws-slot-head.focused { background: #dbeafe; color: var(--navy); box-shadow: inset 0 2px 0 #007bff; font-weight: 700; }
@@ -385,6 +387,9 @@ if ($effectiveLgIdx) {
function reloadTab(id) {
var t = tabs[id];
if (!t) return;
t.frame.style.opacity = '0.35'; // 새로고침 시각 피드백(load 시 복구)
var ic = t.btn && t.btn.querySelector('.t-refresh');
if (ic) { ic.classList.remove('spin'); void ic.offsetWidth; ic.classList.add('spin'); setTimeout(function () { ic.classList.remove('spin'); }, 650); }
try { t.frame.contentWindow.location.reload(); }
catch (e) { t.frame.src = t.frame.src; }
}
@@ -413,6 +418,7 @@ if ($effectiveLgIdx) {
frame.setAttribute('title', title || '탭');
// iframe 내부 포커스에서도 단축키 동작 + 칸 클릭 시 그 칸 포커스
frame.addEventListener('load', function () {
frame.style.opacity = ''; // 새로고침 페이드 복구
try {
var d = frame.contentDocument;
d.addEventListener('keydown', handleShortcut);