feat: 워크스페이스 탭 자동복원 + 주문 입금확인 토글 + 메뉴 개명(전화접수→주문접수)
종량제3 세션 작업. - 워크스페이스 탭 계정별 저장·자동복원(member_workspace_tabs 자동생성, pref/workspace-tabs) - 주문접수 관리 입금확인(so_paid) 수동 토글(phoneOrderMarkPaid, order/phone/manage/paid) - 메뉴 '전화 접수 관리' → '주문접수관리' 개명(피드백 #35) + 시드/개명 SQL Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -191,18 +191,33 @@ if ($effectiveLgIdx) {
|
||||
|
||||
var STORE_KEY = 'jrj_ws_tabs';
|
||||
var WS_OWNER = '<?= (string) (session()->get('mb_idx') ?? '') ?>'; // 탭 저장 소유자(로그인 사용자) 식별
|
||||
var WS_SAVE_URL = '<?= site_url('bag/pref/workspace-tabs') ?>';
|
||||
var WS_CSRF_NAME = '<?= csrf_token() ?>';
|
||||
var wsCsrfHash = '<?= csrf_hash() ?>';
|
||||
var wsSaveTimer = null;
|
||||
function wsStateObj() {
|
||||
return {
|
||||
owner: WS_OWNER,
|
||||
tabs: order.map(function (id) { return { url: tabs[id].url, title: tabs[id].title }; }),
|
||||
layout: layout,
|
||||
focused: focused,
|
||||
vRatio: vRatio,
|
||||
hRatio: hRatio,
|
||||
slots: slots.map(function (id) { return (id && tabs[id]) ? tabs[id].url : null; })
|
||||
};
|
||||
}
|
||||
function persist() {
|
||||
try {
|
||||
sessionStorage.setItem(STORE_KEY, JSON.stringify({
|
||||
owner: WS_OWNER,
|
||||
tabs: order.map(function (id) { return { url: tabs[id].url, title: tabs[id].title }; }),
|
||||
layout: layout,
|
||||
focused: focused,
|
||||
vRatio: vRatio,
|
||||
hRatio: hRatio,
|
||||
slots: slots.map(function (id) { return (id && tabs[id]) ? tabs[id].url : null; })
|
||||
}));
|
||||
} catch (e) {}
|
||||
var obj = wsStateObj();
|
||||
var json = JSON.stringify(obj);
|
||||
try { sessionStorage.setItem(STORE_KEY, json); } catch (e) {}
|
||||
// 계정(DB)에 저장 → 다음 로그인/다른 기기에서도 자동 복원 (연속 변경은 디바운스)
|
||||
clearTimeout(wsSaveTimer);
|
||||
wsSaveTimer = setTimeout(function () {
|
||||
var b = new URLSearchParams();
|
||||
b.set(WS_CSRF_NAME, wsCsrfHash); b.set('state', json);
|
||||
fetch(WS_SAVE_URL, { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: b.toString() })
|
||||
.then(function (r) { return r.json(); }).then(function (d) { if (d && d.csrf) wsCsrfHash = d.csrf; }).catch(function () {});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// 분할 칸 헤더·빈칸 안내 요소 4개 미리 생성
|
||||
@@ -560,11 +575,19 @@ if ($effectiveLgIdx) {
|
||||
});
|
||||
});
|
||||
|
||||
// 첫 화면: 세션 저장 복원(레이아웃·분할 배치 포함), 없으면 대시보드 1분할
|
||||
// 첫 화면: ① 계정(DB) 저장 자동복원 → ② 세션 저장 → ③ 없으면 대시보드 1분할
|
||||
var SERVER_STATE = <?= $savedWorkspaceJson ?? 'null' ?>;
|
||||
(function restore() {
|
||||
var saved = null;
|
||||
try { saved = JSON.parse(sessionStorage.getItem(STORE_KEY) || 'null'); } catch (e) {}
|
||||
if (saved && saved.owner !== WS_OWNER) { try { sessionStorage.removeItem(STORE_KEY); } catch (e) {} saved = null; }
|
||||
// ① 계정 DB에 저장된 상태 우선(다음 로그인·다른 기기에서도 복원)
|
||||
if (SERVER_STATE && SERVER_STATE.tabs && SERVER_STATE.tabs.length) {
|
||||
saved = SERVER_STATE;
|
||||
}
|
||||
// ② 없으면 이 브라우저 세션 저장 사용
|
||||
if (!saved) {
|
||||
try { saved = JSON.parse(sessionStorage.getItem(STORE_KEY) || 'null'); } catch (e) {}
|
||||
if (saved && saved.owner !== WS_OWNER) { try { sessionStorage.removeItem(STORE_KEY); } catch (e) {} saved = null; }
|
||||
}
|
||||
if (saved && saved.tabs && saved.tabs.length) {
|
||||
saved.tabs.forEach(function (t) { if (t && t.url) openTab(t.url, t.title, { noFocus: true }); });
|
||||
layout = (saved.layout === 'lr' || saved.layout === 'tb' || saved.layout === 'quad') ? saved.layout : 'single';
|
||||
|
||||
Reference in New Issue
Block a user