7635412b7b
- 작업자 폰(/mobile)을 SCADA 데모와 ws 로 연결, 알람 발생 시 풀스크린 푸시
· v5 솔리드+글로우 톤, 진동/Web Audio 비프/Wake Lock/auto reconnect
· 시연 안전망: ?test=1 자동 발동, 우상단 hidden 트리거
- backend: com.erp.alarm 신규 패키지 (WebSocketConfig + Handshake + Handler + Controller)
· JWT 토큰 핸드셰이크 검증, userId 기반 채널 매핑 (멀티 디바이스 지원)
· spring-boot-starter-websocket 의존성 추가
· path 를 /api/demo/* 안에 두어 Traefik 라우트 추가 불필요 + 정식 알람과 분리
- SCADA scenario.js 의 emergency 시퀀스(2700ms)에 fetch('/api/demo/alarm/trigger') 배선
· /scada?worker=<user_id> query 로 target user 지정 (iframe src 로 전달)
- 운영 시연 URL: siflex.invyone.com/mobile (siflex_user) ↔ /scada?worker=siflex_user
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
168 lines
5.6 KiB
CSS
168 lines
5.6 KiB
CSS
/* INVYONE Mobile Alarm — 작업자 동반 화면 (siflex.invyone.com/mobile)
|
|
* v5 토큰만 사용. 메인 화면 이후 영역이라 backdrop-filter 금지 — solid + glow.
|
|
* 알람 모드는 위험 분위기 (red/orange) 로 전환. */
|
|
|
|
.m-shell{
|
|
position:fixed; inset:0;
|
|
display:flex; flex-direction:column;
|
|
background:var(--v5-surface-solid);
|
|
color:var(--v5-text);
|
|
overflow:hidden;
|
|
font-family:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Apple SD Gothic Neo","Malgun Gothic",sans-serif;
|
|
-webkit-tap-highlight-color:transparent;
|
|
user-select:none;
|
|
touch-action:manipulation;
|
|
}
|
|
|
|
/* ===== 헤더 (브랜드 + 연결 상태 + 사용자) ===== */
|
|
.m-head{
|
|
flex:0 0 auto;
|
|
display:flex; align-items:center; justify-content:space-between; gap:10px;
|
|
padding:14px 18px;
|
|
border-bottom:1px solid var(--v5-border);
|
|
font-size:13px;
|
|
}
|
|
.m-brand{
|
|
font-weight:700; letter-spacing:0.02em;
|
|
background:linear-gradient(135deg,var(--v5-primary),var(--v5-cyan));
|
|
-webkit-background-clip:text; background-clip:text; color:transparent;
|
|
}
|
|
.m-conn{display:inline-flex; align-items:center; gap:6px; font-size:11px; color:#888;}
|
|
.m-conn.ok{color:#4ade80}
|
|
.m-conn.off{color:#f87171}
|
|
.m-dot{width:8px; height:8px; border-radius:50%; background:currentColor; box-shadow:0 0 8px currentColor;}
|
|
.m-conn.ok .m-dot{animation:m-pulse 1.5s ease-in-out infinite}
|
|
@keyframes m-pulse{0%,100%{opacity:1} 50%{opacity:0.45}}
|
|
|
|
/* ===== IDLE — 평상시 ===== */
|
|
.m-idle{
|
|
flex:1 1 auto;
|
|
display:flex; flex-direction:column; align-items:center; justify-content:center;
|
|
gap:14px; position:relative;
|
|
}
|
|
.m-clock{
|
|
font-size:clamp(56px,16vw,110px);
|
|
font-weight:200; letter-spacing:0.04em;
|
|
font-variant-numeric:tabular-nums;
|
|
background:linear-gradient(135deg,var(--v5-primary),var(--v5-cyan));
|
|
-webkit-background-clip:text; background-clip:text; color:transparent;
|
|
text-shadow:0 0 30px rgba(var(--v5-primary-rgb),0.18);
|
|
z-index:1;
|
|
}
|
|
.m-user{font-size:16px; color:var(--v5-text); z-index:1}
|
|
.m-user-dept{font-size:12px; color:#888; margin-top:-8px; z-index:1}
|
|
.m-idle-hint{
|
|
font-size:12px; color:#888;
|
|
margin-top:24px; padding:0 24px; text-align:center; line-height:1.6;
|
|
z-index:1;
|
|
}
|
|
.m-glow-orb{
|
|
position:absolute;
|
|
width:340px; height:340px; border-radius:50%;
|
|
background:radial-gradient(circle,
|
|
rgba(var(--v5-primary-rgb),0.20),
|
|
rgba(var(--v5-cyan-rgb),0.10) 50%,
|
|
transparent 75%);
|
|
animation:m-orb 6s ease-in-out infinite;
|
|
z-index:0;
|
|
pointer-events:none;
|
|
}
|
|
@keyframes m-orb{
|
|
0%,100%{transform:scale(1); opacity:0.85}
|
|
50% {transform:scale(1.15); opacity:1}
|
|
}
|
|
|
|
/* ===== ALARM — 위험 모드 ===== */
|
|
.m-shell-alarm{background:#0d0202; color:#fff}
|
|
.m-shell-alarm .m-head{
|
|
background:rgba(255,45,107,0.08);
|
|
border-bottom-color:rgba(255,79,154,0.4);
|
|
}
|
|
.m-shell-alarm .m-brand{
|
|
background:linear-gradient(135deg,#ff2d6b,#ff8a3a);
|
|
-webkit-background-clip:text; background-clip:text; color:transparent;
|
|
}
|
|
|
|
.m-alarm{flex:1 1 auto; position:relative; overflow:hidden}
|
|
.m-alarm-bg{
|
|
position:absolute; inset:0;
|
|
background:
|
|
radial-gradient(circle at 50% 30%, rgba(255,79,154,0.35), transparent 60%),
|
|
repeating-linear-gradient(135deg,
|
|
rgba(255,79,154,0.05) 0 14px,
|
|
transparent 14px 28px);
|
|
animation:m-bg-pulse 1.4s ease-in-out infinite;
|
|
pointer-events:none;
|
|
}
|
|
@keyframes m-bg-pulse{0%,100%{opacity:0.85} 50%{opacity:1}}
|
|
|
|
.m-alarm-card{
|
|
position:relative; height:100%;
|
|
display:flex; flex-direction:column; align-items:center; justify-content:center;
|
|
padding:32px 22px; text-align:center; gap:12px;
|
|
animation:m-shake 0.55s ease-in-out 0s 3;
|
|
}
|
|
@keyframes m-shake{
|
|
0%,100%{transform:translateX(0)}
|
|
20%{transform:translateX(-6px)}
|
|
40%{transform:translateX(6px)}
|
|
60%{transform:translateX(-4px)}
|
|
80%{transform:translateX(4px)}
|
|
}
|
|
|
|
.m-alarm-sev{
|
|
font-size:11px; letter-spacing:0.18em; font-weight:700;
|
|
color:#fff; background:#ff2d6b;
|
|
padding:4px 12px; border-radius:4px;
|
|
box-shadow:0 0 14px rgba(255,45,107,0.6);
|
|
}
|
|
.m-alarm-icon{
|
|
font-size:92px; line-height:1;
|
|
filter:drop-shadow(0 0 22px rgba(255,79,154,0.7));
|
|
animation:m-icon-pulse 0.8s ease-in-out infinite;
|
|
}
|
|
@keyframes m-icon-pulse{
|
|
0%,100%{transform:scale(1)}
|
|
50% {transform:scale(1.08)}
|
|
}
|
|
.m-alarm-code{font-size:28px; font-weight:800; letter-spacing:0.08em; color:#ff8a3a}
|
|
.m-alarm-title{font-size:18px; font-weight:600; color:#fff; max-width:340px; line-height:1.4}
|
|
.m-alarm-loc{
|
|
font-size:13px; color:#ffb380;
|
|
background:rgba(255,138,58,0.1);
|
|
padding:6px 14px; border-radius:14px;
|
|
border:1px solid rgba(255,138,58,0.4);
|
|
}
|
|
.m-alarm-msg{
|
|
font-size:14px; color:#ddd; line-height:1.6;
|
|
white-space:pre-wrap; max-width:360px; margin-top:8px;
|
|
}
|
|
.m-alarm-actions{
|
|
display:flex; flex-direction:column; gap:10px;
|
|
width:100%; max-width:320px; margin-top:22px;
|
|
}
|
|
.m-btn-ack{
|
|
background:linear-gradient(135deg,#ff2d6b,#ff8a3a);
|
|
color:#fff; font-size:16px; font-weight:700; letter-spacing:0.04em;
|
|
padding:16px; border:0; border-radius:12px;
|
|
box-shadow:0 6px 20px rgba(255,45,107,0.4), 0 0 30px rgba(255,138,58,0.3);
|
|
cursor:pointer;
|
|
}
|
|
.m-btn-ack:active{transform:translateY(1px)}
|
|
.m-btn-skip{
|
|
background:transparent; color:#aaa; font-size:13px;
|
|
padding:10px; border:1px solid rgba(255,255,255,0.15); border-radius:10px;
|
|
cursor:pointer;
|
|
}
|
|
.m-alarm-time{margin-top:14px; font-size:11px; color:#888; font-variant-numeric:tabular-nums}
|
|
|
|
/* 시연 안전망 — 우상단 hidden trigger */
|
|
.m-test-trigger{
|
|
position:fixed; top:8px; right:8px;
|
|
width:18px; height:18px; border-radius:50%;
|
|
background:rgba(var(--v5-primary-rgb),0.05);
|
|
border:0; cursor:pointer; opacity:0.4;
|
|
z-index:50;
|
|
}
|
|
.m-test-trigger:hover{opacity:0.9}
|