[UI] v0.4.2.11 - CCTV Monitoring UI Revamp for design consistency
This commit is contained in:
parent
991ef773be
commit
93de44bc22
23
backup/.env.backup.2026-01-26-01-54-52
Normal file
23
backup/.env.backup.2026-01-26-01-54-52
Normal file
@ -0,0 +1,23 @@
|
||||
# ==============================================
|
||||
# [Common Settings]
|
||||
# ==============================================
|
||||
DB_HOST=sokuree.com
|
||||
DB_USER=choibk
|
||||
DB_PASSWORD=^Ocean1472bk
|
||||
PORT=3005
|
||||
|
||||
# ==============================================
|
||||
# [Development Environment] - Local Windows
|
||||
# ==============================================
|
||||
# 로컬 개발용 DB (분리됨: sokuree_platform_dev)
|
||||
DB_NAME=sokuree_platform_dev
|
||||
DB_PORT=3307
|
||||
# Windows 환경 호환성 (tcp는 권한 오류 발생 가능)
|
||||
CCTV_TRANSPORT_OVERRIDE=auto
|
||||
|
||||
# ==============================================
|
||||
# [Production Environment] - Synology NAS
|
||||
# ==============================================
|
||||
# DB_NAME=sokuree_platform_prod
|
||||
# DB_PORT=3307
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
**프로젝트명:** SOKUREE Platform - Smart Integrated Management System
|
||||
**최초 작성일:** 2026-01-25
|
||||
**최근 업데이트:** 2026-01-26
|
||||
**버전:** v0.4.2.9
|
||||
**버전:** v0.4.2.11
|
||||
|
||||
---
|
||||
|
||||
@ -46,6 +46,13 @@
|
||||
- **업데이트 안정성**: 소스 교체 전 `.env`/`.env.local` 2중 백업 및 복구 시퀀스 적용
|
||||
- **서버 가용성**: Synology NAS 등 저사양 환경에서의 블로킹 방지를 위한 `execSync` 차단 및 에러 핸들링 강화
|
||||
|
||||
#### 🏷️ Tag: `v0.4.2.11` (완료)
|
||||
- [x] **CCTV 모니터링 UI 리뉴얼**
|
||||
- 페이지 배경색을 플랫폼 표준인 연한 그레이(`var(--sokuree-bg-main)`)로 변경하여 일체감 형성
|
||||
- 카메라 슬롯을 독립적인 카드(Card) 형태로 디자인하고 둥근 모서리(`rounded-xl`) 및 그림자(`shadow-sm`) 적용
|
||||
- 고정된 검은색 배경 대신 브랜드 컬러인 다크 슬레이트(`var(--sokuree-brand-secondary)`) 배경 적용
|
||||
- 빈 슬롯 디자인을 깔끔한 화이트 카드 형태로 개선하여 시각적 피로도 감소
|
||||
|
||||
|
||||
#### 🏷️ Tag: `v0.4.3.0`
|
||||
- [ ] **소모품 관리**
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "smartims",
|
||||
"private": true,
|
||||
"version": "0.4.2.10",
|
||||
"version": "0.4.2.11",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "0.4.2.10",
|
||||
"version": "0.4.2.11",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -64,7 +64,7 @@ export function JSMpegPlayer({ url, width, height, className }: JSMpegPlayerProp
|
||||
}, [url, retryCount]); // Re-run when url or retryCount changes
|
||||
|
||||
return (
|
||||
<div className={`video-container bg-black flex items-center justify-center overflow-hidden ${className || ''}`} style={{ width, height }}>
|
||||
<div className={`video-container bg-transparent flex items-center justify-center overflow-hidden ${className || ''}`} style={{ width, height }}>
|
||||
<canvas key={`${url}-${retryCount}`} ref={canvasRef} className="w-full h-full object-contain" />
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -40,7 +40,7 @@ function SortableCamera({ camera, children, disabled }: { camera: Camera, childr
|
||||
};
|
||||
|
||||
return (
|
||||
<div ref={setNodeRef} style={style} {...attributes} {...listeners} className={`relative bg-black overflow-hidden border ${disabled ? 'border-slate-800' : 'border-slate-700 hover:border-indigo-500'} transition-colors group h-full w-full`}>
|
||||
<div ref={setNodeRef} style={style} {...attributes} {...listeners} className={`relative bg-[#0f172a] rounded-xl overflow-hidden border shadow-sm ${disabled ? 'border-slate-200' : 'border-slate-200 hover:border-indigo-500'} transition-all group h-full w-full`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
@ -309,7 +309,7 @@ export function MonitoringPage() {
|
||||
const slots = Array.from({ length: totalSlots }).map((_, i) => filteredCameras[i] || null);
|
||||
|
||||
return (
|
||||
<div className="w-full h-full bg-[#0a0a0a] flex flex-col min-h-0">
|
||||
<div className="w-full h-full bg-[#f1f5f9] flex flex-col min-h-0">
|
||||
<HeaderDropdown />
|
||||
|
||||
<div className="flex-1 p-2 overflow-hidden flex flex-col min-h-0">
|
||||
@ -323,7 +323,7 @@ export function MonitoringPage() {
|
||||
strategy={rectSortingStrategy}
|
||||
disabled={true}
|
||||
>
|
||||
<div className={`grid h-full w-full gap-1 ${layoutInfo.cols} ${totalSlots > layoutInfo.total ? 'overflow-y-auto' : ''}`}
|
||||
<div className={`grid h-full w-full gap-4 ${layoutInfo.cols} ${totalSlots > layoutInfo.total ? 'overflow-y-auto' : ''}`}
|
||||
style={{ gridAutoRows: (viewLayout === '1' || viewLayout === '1*2') ? '100%' : `${100 / Math.sqrt(layoutInfo.total)}%` }}>
|
||||
{slots.map((camera, index) => (
|
||||
<div key={camera ? camera.id : `empty-${index}`} className="h-full w-full">
|
||||
@ -362,7 +362,7 @@ export function MonitoringPage() {
|
||||
</div>
|
||||
|
||||
{/* Streaming Video */}
|
||||
<div className="flex-1 bg-black flex items-center justify-center">
|
||||
<div className="flex-1 bg-[#0f172a] flex items-center justify-center">
|
||||
<JSMpegPlayer
|
||||
key={`${camera.id}-${streamVersions[camera.id] || 0}`}
|
||||
url={getStreamUrl(camera.id)}
|
||||
@ -377,9 +377,9 @@ export function MonitoringPage() {
|
||||
</div>
|
||||
</SortableCamera>
|
||||
) : (
|
||||
<div className="h-full w-full bg-[#121212] border border-slate-900/50 flex flex-col items-center justify-center text-slate-700 select-none">
|
||||
<Video size={32} className="opacity-10 mb-2" />
|
||||
<span className="text-[11px] font-bold opacity-20 uppercase tracking-widest">No Buffer</span>
|
||||
<div className="h-full w-full bg-white rounded-xl border border-slate-200 flex flex-col items-center justify-center text-slate-300 select-none shadow-sm">
|
||||
<Video size={32} className="opacity-20 mb-2" />
|
||||
<span className="text-[11px] font-bold opacity-40 uppercase tracking-widest">No Buffer</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user