Files
Groupware/Project/Web/wwwroot/react/react-jobreport.html
ChiKyun Kim 6bd4f84192 feat(service): Console_SendMail을 Windows 서비스로 변환
- MailService.cs 추가: ServiceBase 상속받는 Windows 서비스 클래스
- Program.cs 수정: 서비스/콘솔 모드 지원, 설치/제거 기능 추가
- 프로젝트 설정: System.ServiceProcess 참조 추가
- 배치 파일 추가: 서비스 설치/제거/콘솔실행 스크립트

주요 기능:
- Windows 서비스로 백그라운드 실행
- 명령행 인수로 모드 선택 (-install, -uninstall, -console)
- EventLog를 통한 서비스 로깅
- 안전한 서비스 시작/중지 처리

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 09:08:40 +09:00

261 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>업무일지 (React)</title>
<link rel="stylesheet" href="/lib/css/tailwind.min.css">
<script src="/lib/js/tailwind-config.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
.glass-effect {
background: rgba(255, 255, 255, 0.25);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.card-hover {
transition: all 0.3s ease;
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
/* 스크롤바 스타일링 */
.custom-scrollbar::-webkit-scrollbar {
width: 16px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 8px;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 8px;
border: 2px solid rgba(255, 255, 255, 0.1);
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.5);
}
/* 애니메이션 */
.animate-fade-in {
animation: fadeIn 0.5s ease-in-out;
}
.animate-slide-up {
animation: slideUp 0.3s ease-out;
}
/* 셀렉트 박스 옵션 스타일링 */
select option {
background-color: #374151 !important;
color: white !important;
}
select option:hover {
background-color: #4B5563 !important;
}
select option:checked {
background-color: #6366F1 !important;
}
/* 개발중 경고 스타일 */
.dev-warning {
position: fixed;
bottom: 20px;
right: 20px;
background: linear-gradient(135deg, #fbbf24, #f59e0b);
color: white;
padding: 12px 20px;
border-radius: 12px;
box-shadow: 0 10px 25px rgba(245, 158, 11, 0.3);
z-index: 1000;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.dev-warning .icon {
width: 20px;
height: 20px;
margin-right: 8px;
flex-shrink: 0;
}
.dev-warning .title {
font-weight: 600;
margin: 0;
font-size: 14px;
}
.dev-warning .description {
font-size: 12px;
opacity: 0.9;
margin: 2px 0 0 0;
}
</style>
</head>
<body class="bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 min-h-screen text-white">
<!-- 로딩 스켈레톤 UI -->
<div id="react-jobreport-app" class="animate-fade-in">
<div class="container mx-auto px-4 py-8">
{/* 스켈레톤 UI */}
<div className="space-y-6">
{/* 경고 메시지 스켈레톤 */}
<div className="bg-white/10 rounded-lg p-4 animate-pulse">
<div className="h-6 bg-white/20 rounded w-3/4"></div>
</div>
{/* 통계 카드 스켈레톤 */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<div className="glass-effect rounded-lg p-6 animate-pulse">
<div className="flex items-center">
<div className="w-12 h-12 bg-white/20 rounded-lg mr-4"></div>
<div>
<div className="h-4 bg-white/20 rounded w-20 mb-2"></div>
<div className="h-6 bg-white/20 rounded w-12"></div>
</div>
</div>
</div>
<div className="glass-effect rounded-lg p-6 animate-pulse">
<div className="flex items-center">
<div className="w-12 h-12 bg-white/20 rounded-lg mr-4"></div>
<div>
<div className="h-4 bg-white/20 rounded w-24 mb-2"></div>
<div className="h-6 bg-white/20 rounded w-16"></div>
</div>
</div>
</div>
<div className="glass-effect rounded-lg p-6 animate-pulse">
<div className="flex items-center">
<div className="w-12 h-12 bg-white/20 rounded-lg mr-4"></div>
<div>
<div className="h-4 bg-white/20 rounded w-20 mb-2"></div>
<div className="h-6 bg-white/20 rounded w-14"></div>
</div>
</div>
</div>
<div className="glass-effect rounded-lg p-6 animate-pulse">
<div className="flex items-center">
<div className="w-12 h-12 bg-white/20 rounded-lg mr-4"></div>
<div>
<div className="h-4 bg-white/20 rounded w-28 mb-2"></div>
<div className="h-6 bg-white/20 rounded w-8"></div>
</div>
</div>
</div>
</div>
{/* 필터 스켈레톤 */}
<div className="glass-effect rounded-lg p-4 animate-pulse">
<div className="grid grid-cols-3 gap-4">
<div className="col-span-2 space-y-3">
<div className="grid grid-cols-3 gap-3">
<div className="h-8 bg-white/10 rounded"></div>
<div className="h-8 bg-white/10 rounded"></div>
<div className="h-8 bg-white/10 rounded"></div>
</div>
<div className="grid grid-cols-2 gap-3">
<div className="h-8 bg-white/10 rounded"></div>
<div className="h-8 bg-white/10 rounded"></div>
</div>
</div>
<div className="space-y-2">
<div className="h-10 bg-white/10 rounded"></div>
<div className="h-10 bg-white/10 rounded"></div>
<div className="h-10 bg-white/10 rounded"></div>
</div>
</div>
</div>
{/* 테이블 스켈레톤 */}
<div className="glass-effect rounded-lg p-4 animate-pulse">
<div className="space-y-3">
<div className="grid grid-cols-7 gap-4">
<div className="h-6 bg-white/20 rounded"></div>
<div className="h-6 bg-white/20 rounded"></div>
<div className="h-6 bg-white/20 rounded"></div>
<div className="h-6 bg-white/20 rounded"></div>
<div className="h-6 bg-white/20 rounded"></div>
<div className="h-6 bg-white/20 rounded"></div>
<div className="h-6 bg-white/20 rounded"></div>
</div>
<div className="space-y-2">
<div className="grid grid-cols-7 gap-4">
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
</div>
<div className="grid grid-cols-7 gap-4">
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
</div>
<div className="grid grid-cols-7 gap-4">
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
<div className="h-4 bg-white/10 rounded"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- React Local -->
<script crossorigin src="/lib/js/react.development.js"></script>
<script crossorigin src="/lib/js/react-dom.development.js"></script>
<script src="/lib/js/babel.min.js"></script>
<!-- 공통 컴포넌트 로드 -->
<script type="text/babel" src="/react/component/CommonNavigation"></script>
<script type="text/babel" src="/react/component/DevWarning"></script>
<!-- 앱 컴포넌트 -->
<script type="text/babel">
const { useState, useEffect } = React;
function App() {
return (
<div>
<CommonNavigation currentPage="jobreport" />
<JobReport />
<DevWarning />
</div>
);
}
</script>
<!-- 업무일지 컴포넌트 로드 -->
<script type="text/babel" src="/react/component/JobReport"></script>
<!-- 앱 초기화 -->
<script type="text/babel">
const root = ReactDOM.createRoot(document.getElementById('react-jobreport-app'));
root.render(<App />);
</script>
</body>
</html>