feat: 주문리스트를 /orderlist/ 리버스 프록시 경로로 통합

- 메뉴 카드 새 탭 열기 + /orderlist/health/db 헬스 배지 (온라인/오프라인) 추가
- CUSTOMER_ORDER_LIST_URL 기본값을 /orderlist/ 로 (NPM 같은 도메인 하위 경로)
- orderlist 측 compose 정리 스크립트 추가 (ports 제거, npm_default 외부 네트워크 attach)
This commit is contained in:
2026-05-24 05:04:06 +09:00
parent 0c007e6432
commit e8a85be36c
5 changed files with 218 additions and 4 deletions
+3 -1
View File
@@ -113,11 +113,13 @@ async def home(request: Request) -> HTMLResponse:
"title": "CS 발주 업무",
"description": "CS 발주 업무 페이지로 이동",
"url": env("CS_ORDER_URL", "#"),
"health_url": "",
},
{
"title": "고객 주문리스트 프로그램",
"description": "고객 주문리스트 프로그램으로 이동",
"url": env("CUSTOMER_ORDER_LIST_URL", "#"),
"url": env("CUSTOMER_ORDER_LIST_URL", "/orderlist/"),
"health_url": "/orderlist/health/db",
},
]
return render_template(
+34
View File
@@ -789,3 +789,37 @@ a { color: inherit; text-decoration: none; }
.header-portal { display: none; }
.btn-logout span { display: none; }
}
/* ── 상태 배지 ─────────────────────────────────── */
.status-badge {
display: inline-flex;
align-items: center;
gap: 6px;
margin-left: 8px;
padding: 2px 8px;
font-size: 11px;
font-weight: 600;
border-radius: 999px;
vertical-align: middle;
line-height: 1.4;
background: #eef2f7;
color: var(--muted);
border: 1px solid var(--border);
}
.status-badge::before {
content: "";
width: 6px;
height: 6px;
border-radius: 50%;
background: currentColor;
}
.status-badge[data-status="online"] {
background: #e7f6ee;
color: var(--success);
border-color: #b6e0c6;
}
.status-badge[data-status="offline"] {
background: #fdecec;
color: var(--danger);
border-color: #f1c2c2;
}
+29 -2
View File
@@ -55,7 +55,8 @@
<div class="card-grid">
{% for item in menu_items %}
<a class="menu-card" href="{{ item.url }}">
<a class="menu-card" href="{{ item.url }}" target="_blank" rel="noopener noreferrer"
{% if item.health_url %}data-health-url="{{ item.health_url }}"{% endif %}>
<div class="card-icon">
{% if loop.index == 1 %}
<!-- 클립보드 / 발주 아이콘 -->
@@ -98,7 +99,12 @@
</div>
<div class="card-body">
<p class="card-title">{{ item.title }}</p>
<p class="card-title">
{{ item.title }}
{% if item.health_url %}
<span class="status-badge" data-status="checking" aria-live="polite">확인 중</span>
{% endif %}
</p>
<p class="card-desc">{{ item.description }}</p>
</div>
@@ -123,6 +129,27 @@
const days = ["일요일","월요일","화요일","수요일","목요일","금요일","토요일"];
document.getElementById("today-date").textContent =
d.getFullYear() + "년 " + (d.getMonth()+1) + "월 " + d.getDate() + "일 " + days[d.getDay()];
// 헬스 배지 — data-health-url 이 있는 카드만 갱신
async function refreshHealthBadges() {
const cards = document.querySelectorAll(".menu-card[data-health-url]");
await Promise.all(Array.from(cards).map(async (card) => {
const url = card.getAttribute("data-health-url");
const badge = card.querySelector(".status-badge");
if (!badge) return;
try {
const res = await fetch(url, { cache: "no-store", credentials: "omit" });
const ok = res.ok;
badge.dataset.status = ok ? "online" : "offline";
badge.textContent = ok ? "온라인" : "오프라인";
} catch {
badge.dataset.status = "offline";
badge.textContent = "오프라인";
}
}));
}
refreshHealthBadges();
setInterval(refreshHealthBadges, 30000);
</script>
</body>
</html>