치과 대기실 TV

관리 시스템

아임웹 위젯 코드 (아임웹 로그인 자동 연동)

복사됨!
<iframe id="dental-tv-frame" src="" width="100%" height="800" frameborder="0" style="border:none; min-height:600px;" srcdoc="<!DOCTYPE html><html><head><meta charset=UTF-8><style>*{margin:0;padding:0;box-sizing:border-box}body{background:#fff;font-family:-apple-system,BlinkMacSystemFont,sans-serif}@keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}@keyframes spin{to{transform:rotate(360deg)}}.sk{animation:pulse 1.5s ease-in-out infinite;background:#e5e7eb;border-radius:8px}.hdr{background:linear-gradient(135deg,#4f46e5,#6d28d9);padding:16px 20px;border-radius:12px 12px 0 0}.hdr .t{height:20px;width:120px;background:rgba(255,255,255,.3);border-radius:4px;margin-bottom:6px}.hdr .s{height:12px;width:200px;background:rgba(255,255,255,.15);border-radius:4px}.tabs{display:flex;gap:0;border-bottom:1px solid #e5e7eb;padding:0 8px}.tabs span{padding:11px 14px;font-size:13px;color:#6b7280}.tabs span:first-child{color:#2563eb;font-weight:700;border-bottom:2px solid #2563eb}.body{padding:16px;background:#f9fafb;border:1px solid #e5e7eb;border-top:none;border-radius:0 0 12px 12px}.card{background:#fff;border-radius:14px;border:1px solid #e5e7eb;padding:14px 16px;margin-bottom:10px}.card .r{display:flex;align-items:center;gap:10px}.card .ic{width:36px;height:36px;border-radius:10px;background:linear-gradient(135deg,#6d28d9,#4f46e5)}.card .ln{flex:1}.card .l1{height:14px;width:100px;margin-bottom:6px}.card .l2{height:10px;width:160px}.card .btns{display:flex;gap:6px;margin-top:10px;padding-left:46px}.card .btn{height:28px;width:80px;border-radius:8px}</style></head><body><div class=hdr><div class=t></div><div class=s></div></div><div class=tabs><span>대기실</span><span>체어</span><span>공지사항</span><span>설정</span></div><div class=body><div style='display:flex;justify-content:space-between;align-items:center;margin-bottom:16px'><div style='display:flex;align-items:center;gap:8px'><div class='sk' style='width:28px;height:28px;border-radius:8px;background:linear-gradient(135deg,#4f46e5,#6d28d9)'></div><div class='sk' style='height:18px;width:90px'></div></div><div class='sk' style='height:32px;width:100px;border-radius:10px'></div></div><div class=card><div class=r><div class='sk ic'></div><div class=ln><div class='sk l1'></div><div class='sk l2'></div></div></div><div class=btns><div class='sk btn'></div><div class='sk btn'></div><div class='sk btn'></div></div></div><div class=card><div class=r><div class='sk ic'></div><div class=ln><div class='sk l1'></div><div class='sk l2'></div></div></div><div class=btns><div class='sk btn'></div><div class='sk btn'></div><div class='sk btn'></div></div></div></div></body></html>"></iframe>
<script>
(function() {
  var host = 'https://dental-tv-app.pages.dev';
  var frame = document.getElementById('dental-tv-frame');
  var launched = false;

  function getMemberCode() {
    // 방법1: window.__IMWEB__.member
    try { var m = window.__IMWEB__ && window.__IMWEB__.member; if (m && (m.code||m.id)) return { mc: String(m.code||m.id), em: m.email||'' }; } catch(e){}

    // 방법2: __bs_imweb 쿠키에서 JWT 파싱 (아임웹 DVUE SDK)
    try {
      var cookies = document.cookie.split('; ');
      for (var i=0; i<cookies.length; i++) {
        if (cookies[i].startsWith('__bs_imweb=')) {
          var data = JSON.parse(decodeURIComponent(cookies[i].substring('__bs_imweb='.length)));
          if (data.sdk_jwt) {
            var parts = data.sdk_jwt.split('.');
            if (parts.length === 3) {
              var p = JSON.parse(atob(parts[1]));
              var mc = p.sub || p.member_code || p.mc || '';
              if (mc && mc.startsWith('m')) return { mc: mc, em: p.email||'' };
            }
          }
          // browser_session_id 패턴 매칭
          var match = JSON.stringify(data).match(/m\d{8,}[a-f0-9]+/);
          if (match) return { mc: match[0], em: '' };
        }
      }
    } catch(e){}

    // 방법3: window._imweb_page_info
    try { var info = window._imweb_page_info; if (info && info.member_code) return { mc: info.member_code, em: info.member_email||info.email||'' }; } catch(e){}

    // 방법4: 아임웹 템플릿 변수
    var mc='{{ member_code }}', em='{{ user_email }}';
    if (mc && mc.indexOf('{{') === -1) return { mc:mc, em:(em && em.indexOf('{{') === -1)?em:'' };
    return null;
  }

  function launch() {
    if (launched) return;
    var info = getMemberCode();
    if (info && info.mc) {
      launched = true;
      var url = host + '/embed/' + encodeURIComponent(info.mc);
      if (info.em) url += '?email=' + encodeURIComponent(info.em);
      // skeleton을 iframe 위에 overlay로 복사 (src 교체 시 흰화면 방지)
      var wrap = frame.parentNode;
      if (wrap) {
        wrap.style.position = 'relative';
        var ov = document.createElement('div');
        ov.id = 'dtv-overlay';
        ov.innerHTML = frame.srcdoc || '';
        ov.style.cssText = 'position:absolute;top:0;left:0;width:100%;z-index:1;background:#fff';
        wrap.insertBefore(ov, frame);
      }
      frame.style.opacity = '0';
      frame.src = url;
    }
  }

  // iframe top offset을 iframe 내부로 전달하는 함수
  function sendIframeTop() {
    try {
      var rect = frame.getBoundingClientRect();
      var scrollY = window.pageYOffset || document.documentElement.scrollTop || 0;
      var topFromPage = rect.top + scrollY;
      frame.contentWindow.postMessage({ type: 'iframeTop', top: Math.round(topFromPage) }, '*');
    } catch(err) {}
  }

  // 최대 5초간 100ms마다 폴링
  var n=0, t=setInterval(function(){ launch(); if(launched||++n>=50){ clearInterval(t); if(!launched) frame.src=host+'/not-logged-in'; }}, 100);
  // iframe 로드 완료 시 top offset 전달
  frame.addEventListener('load', function(){ setTimeout(sendIframeTop, 300); });
  // 창 리사이즈/스크롤 시 재전달
  window.addEventListener('resize', sendIframeTop);
  window.addEventListener('scroll', sendIframeTop);
  window.addEventListener('message', function(e){ if(e.data&&e.data.type==='setHeight'){ var newH=(e.data.height+30)+'px'; if(frame.style.height!==newH) frame.style.height=newH; } if(e.data&&e.data.type==='contentReady'){ frame.style.opacity='1'; var ov=document.getElementById('dtv-overlay'); if(ov) ov.parentNode.removeChild(ov); } if(e.data&&e.data.type==='scrollToTop'){ try{ document.documentElement.scrollTop=0; document.body.scrollTop=0; frame.scrollIntoView({behavior:'instant',block:'start'}); setTimeout(sendIframeTop,50); }catch(err){} } });
})();
</script>

* 아임웹 로그인 회원의 계정으로 자동 접속됩니다 (비로그인/관리자 계정은 안내 페이지 표시)

마스터 관리자 위젯 코드

복사됨!
<iframe 
  src="https://dental-tv-app.pages.dev/master"
  width="100%" 
  height="800"
  frameborder="0"
></iframe>

* 마스터 관리자 비밀번호: dental2024master

마스터 관리자 바로가기